diff --git a/apps/shared/src/gateway-contract.generated.ts b/apps/shared/src/gateway-contract.generated.ts new file mode 100644 index 0000000000..efa83f07ea --- /dev/null +++ b/apps/shared/src/gateway-contract.generated.ts @@ -0,0 +1,5025 @@ +// GENERATED by scripts/gen_gateway_contracts.py from tui_gateway/contracts — DO NOT EDIT. +// Regenerate: .venv/bin/python scripts/gen_gateway_contracts.py +// tests/contracts/test_generated.py fails when this file is stale. +/* eslint-disable */ +// ── Types ── +/** Any method the desktop may route to a named profile (``requestGatewayForProfile`` adds ``profile``). */ +export interface ProfileParams { + profile?: string | null +} +/** ``_serialize_usage_model`` — also embedded as ``usage`` in the billing / subscription states, where the fail-open form is a bare ``{available: false}`` (no ``ok``). */ +export interface UsageModel { + ok?: boolean | null + available: boolean + status?: string | null + plan_name?: string | null + renews_at?: string | null + renews_display?: string | null + subscription_remaining_display?: string | null + topup_remaining_display?: string | null + total_spendable_display?: string | null + has_topup?: boolean | null + plan_bar?: UsageBar | null + topup_bar?: UsageBar | null +} +/** ``_serialize_usage_bar``: one bar, magnitudes pre-formatted; ``pct_used`` only for ``plan``. */ +export interface UsageBar { + kind: UsageBarKind + remaining_display: string + total_display: string + spent_display: string + pct_used?: number | null + fill_fraction: number +} +export type UsageBarKind = 'plan' | 'topup' +/** ``_serialize_billing_state`` (money as strings); the ``except`` fallback emits only ``ok / logged_in / free_tier / error``, so everything else is optional. */ +export interface BillingStateResult { + ok: boolean + logged_in: boolean + free_tier?: boolean + free_tier_model?: string | null + org_name?: string | null + org_slug?: string | null + role?: string | null + is_admin?: boolean | null + can_change_plan?: boolean | null + can_charge?: boolean | null + balance_usd?: string | null + balance_display?: string | null + cli_billing_enabled?: boolean | null + charge_presets?: string[] | null + charge_presets_display?: string[] | null + min_usd?: string | null + max_usd?: string | null + card?: BillingCardInfo | null + payment_method?: BillingPaymentMethod | null + monthly_cap?: BillingMonthlyCap | null + auto_reload?: BillingAutoReload | null + portal_url?: string | null + error?: string | null + usage?: UsageModel | null +} +export interface BillingCardInfo { + brand: string + last4: string + masked: string + display?: string | null + resolved_via?: string | null +} +/** ``_serialize_payment_method``: each kind emits only its own fields (a ``card`` never carries ``email``; ``unknown`` carries what the server called it in ``raw_kind``). */ +export interface BillingPaymentMethod { + kind: PaymentMethodKind + brand?: string | null + last4?: string | null + wallet?: string | null + email?: string | null + raw_kind?: string | null + resolved_via?: string | null +} +export type PaymentMethodKind = 'card' | 'link' | 'unknown' +export interface BillingMonthlyCap { + limit_usd?: string | null + limit_display: string + spent_this_month_usd?: string | null + spent_display: string + is_default_ceiling: boolean +} +export interface BillingAutoReload { + enabled: boolean + threshold_usd?: string | null + threshold_display: string + reload_to_usd?: string | null + reload_to_display: string + card?: BillingAutoReloadCard | null +} +/** Only ``distinct`` carries the payment-method identity. */ +export interface BillingAutoReloadCard { + kind: AutoReloadCardKind + payment_method_id?: string | null + brand?: string | null + last4?: string | null +} +export type AutoReloadCardKind = 'canonical' | 'distinct' | 'none' +/** ``_serialize_subscription_state``; the view's fallback emits only ``ok / logged_in / error``. */ +export interface SubscriptionStateResult { + ok: boolean + logged_in: boolean + is_admin?: boolean | null + can_change_plan?: boolean | null + org_name?: string | null + org_id?: string | null + role?: string | null + context?: SubscriptionContext | null + current?: CurrentSubscription | null + tiers?: SubscriptionTierOption[] | null + portal_url?: string | null + error?: string | null + usage?: UsageModel | null +} +export type SubscriptionContext = 'personal' | 'team' +export interface CurrentSubscription { + tier_id?: string | null + tier_name?: string | null + monthly_credits?: string | null + credits_remaining?: string | null + cycle_ends_at?: string | null + pending_downgrade_tier_name?: string | null + pending_downgrade_at?: string | null + pending_downgrade_display?: string | null + cancel_at_period_end: boolean + cancellation_effective_at?: string | null + cancellation_effective_display?: string | null +} +export interface SubscriptionTierOption { + tier_id: string + name: string + tier_order: number + dollars_per_month_display: string + monthly_credits?: string | null + is_current: boolean + is_enabled: boolean +} +export interface SubscriptionPreviewParams { + profile?: string | null + subscription_type_id?: string | null +} +/** ``_serialize_subscription_preview`` on success; ``effect`` drives the confirm copy. */ +export interface SubscriptionPreviewResult { + ok: boolean + error?: string | null + message?: string | null + portal_url?: string | null + retry_after?: number | null + payload?: Record | null + actor?: string | null + code?: string | null + recovery?: string | null + effect?: SubscriptionChangeEffect | null + reason?: string | null + current_tier_id?: string | null + current_tier_name?: string | null + target_tier_id?: string | null + target_tier_name?: string | null + monthly_credits_delta?: string | null + amount_due_now_cents?: number | null + effective_at?: string | null +} +export type SubscriptionChangeEffect = 'charge_now' | 'scheduled' | 'no_op' | 'blocked' +/** Either a target tier (downgrade / same-price change) or ``cancel`` (period-end cancellation). */ +export interface SubscriptionChangeParams { + profile?: string | null + subscription_type_id?: string | null + cancel?: boolean +} +/** ``_billing_pending_change``: ``message`` + the raw NAS body in ``payload`` on success. */ +export interface BillingPendingChangeResult { + ok: boolean + error?: string | null + message?: string | null + portal_url?: string | null + retry_after?: number | null + payload?: Record | null + actor?: string | null + code?: string | null + recovery?: string | null +} +export interface SubscriptionUpgradeParams { + profile?: string | null + subscription_type_id?: string | null + idempotency_key?: string | null +} +/** The money route: ``status`` separates a completed upgrade from an SCA / decline that must finish in the portal at ``recovery_url``; ``idempotency_key`` is echoed (also on error) so a retry reuses it. */ +export interface SubscriptionUpgradeResult { + ok: boolean + error?: string | null + message?: string | null + portal_url?: string | null + retry_after?: number | null + payload?: Record | null + actor?: string | null + code?: string | null + recovery?: string | null + status?: string | null + target_tier_name?: string | null + recovery_url?: string | null + reason?: string | null + idempotency_key?: string | null +} +export interface BillingChargeParams { + profile?: string | null + amount_usd?: number | string | null + idempotency_key?: string | null +} +/** ``202 {chargeId}`` — money is not confirmed yet; poll ``billing.charge_status``. */ +export interface BillingChargeResult { + ok: boolean + error?: string | null + message?: string | null + portal_url?: string | null + retry_after?: number | null + payload?: Record | null + actor?: string | null + code?: string | null + recovery?: string | null + charge_id?: string | null + idempotency_key?: string | null +} +export interface BillingChargeStatusParams { + profile?: string | null + charge_id?: string | null +} +/** Single status read (pending | settled | failed); the caller drives the poll cadence. */ +export interface BillingChargeStatusResult { + ok: boolean + error?: string | null + message?: string | null + portal_url?: string | null + retry_after?: number | null + payload?: Record | null + actor?: string | null + code?: string | null + recovery?: string | null + status?: string | null + amount_usd?: string | number | null + settled_at?: string | null + reason?: string | null +} +export interface BillingAutoReloadParams { + profile?: string | null + enabled?: boolean + threshold?: number | string | null + top_up_amount?: number | string | null +} +/** A write with no success payload beyond ``ok``. */ +export interface BillingMutationResult { + ok: boolean + error?: string | null + message?: string | null + portal_url?: string | null + retry_after?: number | null + payload?: Record | null + actor?: string | null + code?: string | null + recovery?: string | null +} +export interface BillingStepUpParams { + profile?: string | null + session_id?: string | null +} +/** ``granted`` false when the server downscopes (also on every error envelope). */ +export interface BillingStepUpResult { + ok: boolean + error?: string | null + message?: string | null + portal_url?: string | null + retry_after?: number | null + payload?: Record | null + actor?: string | null + code?: string | null + recovery?: string | null + granted?: boolean | null +} +export interface DelegationStatusResult { + active: ActiveSubagent[] + paused: boolean + max_spawn_depth: number + max_concurrent_children: number +} +/** One live child from ``tools/delegate_tool_registry.py::list_active_subagents`` (the record is extended by the child runner — ``missed_steer`` etc. — so it stays open). */ +export interface ActiveSubagent { + subagent_id: string + parent_id?: string | null + depth?: number | null + goal?: string | null + delegation_id?: string | null + model?: string | null + started_at?: number | null + status?: string | null + tool_count?: number | null + owner_agent_session_id?: string | null + [key: string]: unknown +} +export interface DelegationPauseParams { + profile?: string | null + paused?: boolean +} +export interface DelegationPauseResult { + paused: boolean +} +export interface SubagentSteerParams { + session_id: string + profile?: string | null + subagent_id: string + text: string +} +/** ``queued`` is not ``delivered``: a child past its final tool batch surfaces ``missed_steer``. */ +export interface SubagentSteerResult { + status: SteerStatus + subagent_id: string + text: string +} +export type SteerStatus = 'queued' | 'rejected' +export interface HandoffRequestParams { + session_id: string + profile?: string | null + platform: string +} +export interface HandoffRequestResult { + queued: boolean + session_key: string + platform: string + home_name: string +} +/** Any method addressed at one live session. */ +export interface SessionParams { + session_id: string + profile?: string | null +} +/** ``state`` is pending | running | completed | failed, or '' when nothing was requested. */ +export interface HandoffStateResult { + state: string + platform: string + error: string +} +export interface HandoffFailParams { + session_id: string + profile?: string | null + error?: string | null +} +/** ``failed`` false when the watcher already claimed the row; ``state`` is what it is now. */ +export interface HandoffFailResult { + failed: boolean + state: string +} +/** ``row_id`` is ``messages.id``; a not-yet-persisted live message names ``newest_role`` instead. ``emoji`` null clears; the same emoji again retracts. */ +export interface MessageReactParams { + session_id: string + profile?: string | null + row_id?: number | null + newest_role?: string | null + emoji?: string | null + author?: ReactionAuthor | null +} +export type ReactionAuthor = 'user' | 'agent' +export interface MessageReactResult { + row_id: number + reactions: tui_gateway_contracts_billing_delegation_pets_MessageReaction[] +} +/** One persisted reaction (``hermes_state_messages.py``); ``seen`` is stamped once announced. */ +export interface tui_gateway_contracts_billing_delegation_pets_MessageReaction { + emoji: string + author: string + at?: number | null + seen?: boolean | null + [key: string]: unknown +} +export interface PetCancelParams { + profile?: string | null + token?: string | null +} +export interface PetCancelResult { + ok: boolean +} +export interface PetGenerateStatusResult { + available: boolean + providers: PetGenProvider[] +} +/** ``agent/pet/generate/imagegen.py::list_sprite_providers`` row. */ +export interface PetGenProvider { + name: string + label: string + default: boolean +} +/** ``prompt`` or a ``referenceImage`` data URL is required (the handler answers 4004 without one). */ +export interface PetGenerateParams { + profile?: string | null + prompt?: string | null + referenceImage?: string | null + count?: number | null + style?: string | null + provider?: string | null +} +export interface PetGenerateResult { + ok: boolean + token: string + drafts: PetDraft[] +} +export interface PetDraft { + index: number + dataUri: string +} +export interface PetHatchParams { + profile?: string | null + token: string + name: string + cancelToken?: string | null + index?: number | null + description?: string | null + prompt?: string | null + style?: string | null + provider?: string | null +} +/** The hatched pet is installed but NOT active (``pet.select`` adopts, ``pet.remove`` discards). */ +export interface PetHatchResult { + ok: boolean + slug: string + displayName: string + warnings?: unknown[] + pet: PetSpritePayload +} +export interface PetSpritePayload { + slug?: string | null + displayName?: string | null + mime?: string | null + spritesheetBase64?: string | null + spritesheetRevision?: string | null + frameW?: number | null + frameH?: number | null + framesPerState?: number | null + framesByState?: Record | null + framesByRow?: Record | null + loopMs?: number | null + scale?: number | null + stateRows?: string[] | null +} +export interface ProjectFactsParams { + profile?: string | null + cwd?: string | null +} +/** ``facts`` null outside a workspace (or when detection failed). */ +export interface ProjectFactsResult { + facts?: ProjectFacts | null +} +/** ``agent/coding_context.py::project_facts_for`` — the system prompt's coding-context detection. */ +export interface ProjectFacts { + root: string + manifests: string[] + packageManagers: string[] + verifyCommands: string[] + contextFiles: string[] +} +/** ``key`` selects one getter from ``_CONFIG_GETTERS``; ``cwd`` feeds the ``project`` getter, ``session_id`` lets ``reasoning`` / ``fast`` answer with the session's live pin. */ +export interface ConfigGetParams { + profile?: string | null + key: string + cwd?: string | null + session_id?: string | null +} +/** Union of every getter's payload: ``value`` for the simple words, ``config`` for ``full``, ``mtime`` / ``mcp_rev`` for the poller, ``model`` / ``provider`` / ``providers`` for ``provider``, ``home`` / ``display`` for ``profile``, ``cwd`` / ``branch`` for ``project``, ``prompt``. */ +export interface ConfigGetResult { + value?: string | null + display?: string | null + tool_progress?: string | null + model?: string | null + provider?: string | null + providers?: ConfigProviderRef[] | null + home?: string | null + cwd?: string | null + branch?: string | null + config?: Record | null + prompt?: string | null + mtime?: number | null + mcp_rev?: string | null +} +/** ``hermes_cli/models.py::list_available_providers`` row. */ +export interface ConfigProviderRef { + id: string + label: string + aliases?: string[] + authenticated?: boolean + [key: string]: unknown +} +/** ``key`` picks the setter (``_CONFIG_SETTERS``, ``details_mode.
``, display toggles); ``value`` is the raw word/string the setter normalises (falsy non-strings are reported back in the error). ``scope`` applies to ``yolo`` / ``reasoning``; ``confirm_expensive_model`` to ``model``. */ +export interface ConfigSetParams { + profile?: string | null + key: string + value?: unknown + session_id?: string | null + scope?: string | null + confirm_expensive_model?: boolean +} +/** ``{key, value}`` plus the setter's extras: model switches add ``warning`` / ``confirm_required`` / ``confirm_message`` / ``scope`` / ``deferred``; ``focus`` adds ``tool_progress``; ``cwd`` adds ``cwd`` / ``branch``; ``personality`` adds ``history_reset`` / ``info``; ``yolo`` reports its ``scope``. ``value`` is a bool only for the display toggles. */ +export interface ConfigSetResult { + key: string + value?: string | boolean | null + warning?: string | null + confirm_required?: boolean | null + confirm_message?: string | null + scope?: string | null + deferred?: boolean | null + tool_progress?: string | null + cwd?: string | null + branch?: string | null + history_reset?: boolean | null + info?: SessionLiveInfo | null +} +/** ``tui_gateway/server.py::_session_info`` — the ``session.info`` event and the ``info`` field of ``session.create`` / ``session.resume`` / ``session.activate`` results. */ +export interface SessionLiveInfo { + model?: string + provider?: string + reasoning_effort?: string + service_tier?: string + fast?: boolean + yolo?: boolean + approval_mode?: string + tools?: Record + skills?: Record + cwd?: string + branch?: string | null + project?: ProjectRef | null + terminal_backend?: string + personality?: string + running?: boolean + turn_started_at?: number | null + title?: string + stored_session_id?: string + desktop_contract?: number | string | null + version?: string + release_date?: string + update_behind?: unknown | null + update_command?: string + usage?: Usage | null + profile_name?: string | null + mcp_servers?: McpServerStatus[] + system_prompt?: string | null + credential_warning?: string | null + lazy?: boolean | null + [key: string]: unknown +} +/** ``tui_gateway/server.py::_project_info_for_cwd``. */ +export interface ProjectRef { + id: string + slug: string + name: string + primary_path?: string | null +} +/** ``tui_gateway/server.py::_get_usage`` + ``agent/context_breakdown.py::context_usage_fields``. */ +export interface Usage { + model?: string + input?: number + output?: number + reasoning?: number + prompt?: number + completion?: number + total?: number + calls?: number + compressions?: number | null + context_used?: number | null + context_max?: number | null + context_percent?: number | null + context_source?: string | null + context_estimated?: boolean | null + cache_hit_pct?: number | null + cache_read?: number | null + cache_write?: number | null + avg_latency_s?: number | null + avg_tps?: number | null + active_subagents?: number | null + dev_credits_spent_micros?: number | null + cost_usd?: number | null + cost_status?: string | null + [key: string]: unknown +} +export interface McpServerStatus { + name?: string + status?: string | null + tool_count?: number | null + error?: string | null + [key: string]: unknown +} +/** ``provider_configured`` is the loose answer; the boot record's fields (``ready``, ``free_tier``, ``other_providers``, ``inference_provider``) ride along on the launch profile. An unknown ``profile`` answers ``ok=False`` + ``error``. */ +export interface SetupStatusResult { + provider_configured?: boolean | null + ready?: boolean | null + free_tier?: boolean | null + other_providers?: boolean | null + inference_provider?: string | null + profile?: string | null + ok?: boolean | null + error?: string | null +} +export interface SetupRuntimeCheckParams { + profile?: string | null + provider?: string | null +} +/** ``ok=False`` + ``error`` when the resolved model can't be served; ``free_tier`` says the selected route is the welcome host. */ +export interface SetupRuntimeCheckResult { + ok: boolean + provider?: string | null + model?: string | null + source?: string | null + error?: string | null + free_tier?: boolean | null + profile?: string | null +} +export interface DiagnosticsShareNousParams { + error_context?: string | null + extra_files?: Record | null + log_lines?: number | null +} +/** Structured envelope: ``ok=False`` + ``error`` renders inline instead of failing the RPC. */ +export interface DiagnosticsShareNousResult { + ok: boolean + view_url?: string | null + upload_id?: string | null + expires_at?: string | null + error?: string | null +} +/** ``available`` = an identity exists AND the tier is on; whether inference runs on it is ``setup.runtime_check.free_tier``'s question. */ +export interface FreeTierStatusResult { + has_guest: boolean + enabled: boolean + available: boolean + notice_pending: boolean + model: string + label: string +} +export interface FreeTierProvisionResult { + has_guest: boolean + enabled: boolean + error?: string | null +} +export interface FreeTierAckNoticeResult { + acked: boolean +} +export interface ModelOptionsParams { + profile?: string | null + session_id?: string | null + explicit_only?: boolean + include_unconfigured?: boolean + refresh?: boolean +} +export interface ModelOptionsResult { + providers: ModelOptionProvider[] + model?: string + provider?: string +} +/** One ``hermes_cli/inventory.py::build_models_payload`` provider row (the union of every field the builder sets; ``pricing_pending`` / ``free_tier_pending`` mark the cached-only path). */ +export interface ModelOptionProvider { + slug: string + name: string + models?: string[] + total_models?: number | null + is_current?: boolean | null + is_user_defined?: boolean | null + source?: string | null + aliases?: string[] | null + api_url?: string | null + auth_type?: string | null + authenticated?: boolean | null + key_env?: string | null + warning?: string | null + featured_models?: string[] | null + capabilities?: Record | null + pricing?: Record | null + pricing_pending?: boolean | null + free_tier?: boolean | null + free_tier_pending?: boolean | null + free_tier_row?: boolean | null + unavailable_models?: string[] | null + [key: string]: unknown +} +/** ``hermes_cli/inventory.py::_apply_capabilities``. */ +export interface ModelCapabilities { + fast: boolean + reasoning: boolean + can_disable_reasoning?: boolean | null +} +/** ``hermes_cli/inventory.py::_apply_pricing`` — formatted $/Mtok strings (``""`` unknown, ``"free"``); the sale fields are Nous Portal-only. */ +export interface ModelPricing { + input: string + output: string + cache?: string | null + free: boolean + discount_percent?: number | null + was_input?: string | null + was_output?: string | null +} +export interface ConnectorsListParams { + profile?: string | null + session_id: string +} +export interface ConnectorsListResult { + available: boolean + connectors: ConnectorRow[] +} +/** One ``manage_connections`` status entry after ``connector_ui_payload`` redaction; the connector service owns the closed key set, so unknown metadata passes through. */ +export interface ConnectorRow { + connector?: string + connected?: boolean | null + enabled?: boolean | null + connectionStatus?: string | null + name?: string | null + description?: string | null + [key: string]: unknown +} +export interface ConnectorsConnectParams { + profile?: string | null + session_id: string + connectors: string[] + reconnect?: boolean +} +export interface ConnectorsConnectResult { + results: ConnectorConnectEntry[] + summary: Record +} +/** ``tools/connections_tool.py`` per-connector authorization outcome. */ +export interface ConnectorConnectEntry { + connector?: string + status?: string | null + connect_url?: string | null + note?: string | null + instruction?: string | null + [key: string]: unknown +} +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: tui_gateway_contracts_config_free_tier_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 tui_gateway_contracts_config_free_tier_control_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: tui_gateway_contracts_config_free_tier_control_SessionControlSnapshot + dispatch: SessionControlDispatch +} +/** ``_dispatch_envelope`` — the command result's user-visible envelope, every key always present. */ +export interface SessionControlDispatch { + type: string | null + output: string | null + notice: string | null + message: string | null + display: string | null +} +export interface VerificationStatusParams { + profile?: string | null + session_id?: string | null + session_key?: string | null + cwd?: string | null +} +export interface VerificationStatusResult { + verification: VerificationStatusInfo +} +/** ``verification_status()``: ``disabled`` / ``not_applicable`` / ``unverified`` / ``stale`` or the latest event's own status; ``root`` and friends only once a workspace was identified. */ +export interface VerificationStatusInfo { + status: string + evidence?: VerificationEvidenceRow | null + root?: string | null + session_id?: string | null + changed_paths?: string[] | null +} +/** One ``verification_events`` row (``agent/verification_evidence.py``). */ +export interface VerificationEvidenceRow { + id?: number | null + created_at?: string | null + session_id?: string | null + cwd?: string | null + root?: string | null + command?: string | null + canonical_command?: string | null + kind?: string | null + scope?: string | null + status?: string | null + exit_code?: number | null + output_summary?: string | null + [key: string]: unknown +} +export interface GroupsCapabilitiesParams { + profile?: string | null +} +export interface GroupsCapabilitiesResult { + protocol_version: number + driver: boolean + persistent_process: boolean + authority_gateway_id: string + room_link: RoomLinkStatus + features: string[] + methods: string[] + max_log_limit: number +} +/** ``enabled`` with ``profile``/``catalog``/``endpoint``, or disabled with a ``reason``. */ +export interface RoomLinkStatus { + enabled: boolean + profile?: string | null + catalog?: RoomLinkCatalog | null + endpoint?: RoomLinkEndpoint | null + reason?: string | null +} +/** ``gateway/hosted_room_peer.py::GatewayRoomCatalog.as_mapping``. */ +export interface RoomLinkCatalog { + installation_id: string + protocol_versions: number[] + link_modes: string[] + persistent_process: boolean + text: boolean + attachments: boolean + execution_policy: RoomExecutionPolicy + catalog_digest: string + endpoint?: RoomLinkEndpoint | null +} +/** ``gateway/hosted_room_execution_policy.py::execution_policy_mapping``. */ +export interface RoomExecutionPolicy { + version: number + target_profile: string + enabled_toolsets: string[] + approval_mode: string + max_iterations: number + policy_digest: string +} +/** ``GatewayRoomCatalog.endpoint_mapping``: ``url``/``transport_security`` when available, ``reason`` when not. */ +export interface RoomLinkEndpoint { + available: boolean + url?: string | null + transport_security?: string | null + reason?: string | null +} +export interface GroupsListParams { + profile?: string | null + include_disbanded?: boolean | null + limit?: number | null + offset?: number | null +} +export interface GroupsListResult { + rooms: Room[] + next_offset?: number | null +} +/** ``gateway/hosted_rooms.py::_room_from_row`` plus the branch-only keys ``create`` (legacy adoption), ``state`` (``authority_claim``) and ``rename`` (``event``) add. */ +export interface Room { + room_id: string + name: string + members: RoomMember[] + authority_gateway_id: string + authority_epoch: number + revision: number + created_at: number + updated_at: number + idempotent?: boolean + disbanded_at?: number | null + latest_seq?: number | null + adopted?: boolean | null + claim_event?: RoomEvent | null + authority_claim?: RoomEvent | null + event?: RoomEvent | null +} +/** One roster row (``hosted_room_discussion.validate_roster``); legacy rooms may carry pre-normalisation rows, so the set stays open. */ +export interface RoomMember { + member_id?: string | null + profile?: string | null + handle?: string | null + display_name?: string | null + target?: Record | null + [key: string]: unknown +} +/** ``gateway/hosted_rooms.py::_event_from_row``. */ +export interface RoomEvent { + room_id: string + seq: number + event_id: string + kind: string + actor: RoomActor + authority_epoch?: number | null + payload: Record + created_at: number + idempotent?: boolean +} +export interface RoomActor { + kind: string + id: string +} +export interface GroupsCreateParams { + profile?: string | null + room_id: string + name: string + members: RoomMemberInput[] + authority_gateway_id?: string | null +} +/** A roster row as the client proposes it; ``validate_roster`` owns the exact rules. */ +export interface RoomMemberInput { + member_id?: string | null + profile?: string | null + handle?: string | null + display_name?: string | null + target?: Record | null + [key: string]: unknown +} +export interface GroupsCreateResult { + room: Room +} +export interface GroupsStateParams { + profile?: string | null + room_id: string + include_disbanded?: boolean | null +} +export interface GroupsStateResult { + room: Room + driver_status?: RoomDriverStatus | null +} +/** ``HostedRoomService.status(room_id)``; ``pending_actions`` rows are ``{kind: retry, task_id}`` or the driver's approval action (``kind: approval`` + run/session/approval context). */ +export interface RoomDriverStatus { + running: boolean + working: boolean + blocked: boolean + counts: Record + pending_actions: Record[] + peer_routes: PeerRouteStatus[] +} +export interface PeerRouteStatus { + room_id: string + member_id: string + status: string +} +export interface GroupsSendParams { + profile?: string | null + room_id: string + event_id?: string | null + payload: Record +} +export interface GroupsSendResult { + event: RoomEvent + client_event_id?: string | null + accepted?: boolean + driver_started?: boolean +} +export interface GroupsRenameParams { + profile?: string | null + room_id: string + event_id: string + name: string +} +export interface GroupsRenameResult { + room: Room +} +export interface GroupsLogParams { + profile?: string | null + room_id: string + since_seq?: number | null + limit?: number | null + include_disbanded?: boolean | null +} +/** ``gateway/hosted_rooms.py::read_events`` page — also the ``page`` ``groups.replicate`` ingests. */ +export interface GroupsLogResult { + events: RoomEvent[] + cursor: number + latest_seq: number + has_more: boolean + authority: RoomAuthority +} +export interface RoomAuthority { + gateway_id: string + epoch: number +} +export interface GroupsDisbandParams { + profile?: string | null + room_id: string + cancel_id?: string | null +} +export interface GroupsDisbandResult { + tombstone: RoomTombstone +} +export interface RoomTombstone { + room_id: string + disbanded_at: number + idempotent: boolean + history_expired?: boolean | null + event?: RoomEvent | null +} +export interface GroupsStopParams { + profile?: string | null + room_id: string + cancel_id?: string | null +} +export interface GroupsStopResult { + cancelled: number +} +export interface GroupsApproveParams { + profile?: string | null + room_id: string + member_id: string + task_id: string + execution_generation: number + choice: tui_gateway_contracts_groups_bot_relay_ApprovalChoice + request_id: string +} +export type tui_gateway_contracts_groups_bot_relay_ApprovalChoice = 'once' | 'deny' +/** ``result`` is the local ``approval.respond`` answer or the peer's run-action receipt. */ +export interface GroupsApproveResult { + approved?: boolean + result: Record +} +export interface GroupsRetryParams { + profile?: string | null + room_id: string + task_id: string +} +export interface GroupsRetryResult { + retried?: boolean + task: RoomTaskReceipt +} +export interface RoomTaskReceipt { + room_id: string + task_id: string + thread_id: string + turn_id: string + status: string + execution_generation: number + cancel_generation: number +} +export interface GroupsReplicateParams { + profile?: string | null + room_id: string + room_name: string + members: RoomMemberInput[] + page: Record +} +export interface GroupsReplicateResult { + room_id: string + stored_seq: number + ingested: number + authority: RoomAuthority + caught_up: boolean +} +export interface GroupsReplicaStateParams { + profile?: string | null + room_id: string +} +export interface GroupsReplicaStateResult { + room_id: string + name: string + members: RoomMember[] + authority: RoomAuthority + last_seq: number + latest_seq: number + event_bytes: number + created_at: number + updated_at: number +} +export interface GroupsPromoteParams { + profile?: string | null + room_id: string + confirm?: boolean | null + reason?: string | null +} +export interface GroupsPromoteResult { + room_id: string + authority_gateway_id: string + authority_epoch: number + previous_gateway_id: string + previous_epoch: number + claim_seq: number + latest_seq: number +} +export interface GroupsDemoteParams { + profile?: string | null + room_id: string + observed_gateway_id: string + observed_epoch: number +} +export interface GroupsDemoteResult { + room_id: string + authority_gateway_id: string + authority_epoch: number + idempotent: boolean +} +export interface GroupsPeerInviteParams { + profile?: string | null + room_id?: string | null + home_install_id?: string | null + authority_gateway_id?: string | null + authority_epoch?: number | null + member_id?: string | null + grant_id?: string | null + ttl_seconds?: number | null +} +export interface GroupsPeerInviteResult { + grant: string + target_profile: string + catalog: RoomLinkCatalog + endpoint: RoomLinkEndpoint +} +export interface GroupsPeerRevokeParams { + profile?: string | null + grant: string +} +export interface GroupsPeerRevokeResult { + revoked?: boolean +} +export interface GroupsPeerRegisterParams { + profile?: string | null + room_id: string + member_id: string + target_url: string + target_profile: string + grant: string + catalog: Record + cancellation_scope_id?: string | null + trace_id?: string | null +} +export interface GroupsPeerRegisterResult { + registered?: boolean + mode: string + transport_security: string + target_install_id: string + target_profile: string +} +export interface BotRelayRosterSyncParams { + profile?: string | null + agents?: RelayAgentRow[] | null +} +/** A roster row the Desktop pushes (``tools/bot_relay.py::_normalize_roster_row``); invalid rows are dropped server-side, so the shape stays open. */ +export interface RelayAgentRow { + profile?: string | null + handle?: string | null + connection_id?: string | null + connection_label?: string | null + title?: string | null + description?: string | null + online?: boolean | null + [key: string]: unknown +} +export interface BotRelayRosterSyncResult { + count: number +} +export interface BotRelayOutboxDrainParams { + profile?: string | null +} +export interface BotRelayOutboxDrainResult { + envelopes: RelayEnvelope[] +} +/** ``tools/bot_relay.py::enqueue_envelope``. */ +export interface RelayEnvelope { + id: string + created_at: number + from_profile: string + from_handle: string + target_connection: string + target_profile: string + target_handle: string + message: string + [key: string]: unknown +} +/** ``profile`` here is the TARGET profile on this gateway (also what the desktop route wrapper adds). */ +export interface BotRelayDeliverParams { + profile: string + message: string + from_profile?: string | null + from_handle?: string | null + from_connection?: string | null +} +export interface BotRelayDeliverResult { + reply: string +} +export interface BotRelayReplyParams { + profile?: string | null + id: string + reply?: string | null + error?: string | null + reason?: string | null +} +export interface OkResult { + ok?: boolean +} +export interface BrowserControllerRegisterParams { + session_id: string + controller_id: string + browser_profile_id: string + capabilities?: string[] | null + protocol_version?: unknown | null + principal_id?: string | null +} +export interface BrowserControllerRegisterResult { + scope: ControllerScope +} +export interface ControllerScope { + principal_id: string + profile_id: string + session_id: string + controller_id: string + browser_profile_id: string + transport_family: string + capabilities: string[] +} +export interface BrowserControllerResultParams { + session_id: string + command_id: string + ok?: unknown | null + result?: unknown | null + error?: unknown | null +} +export interface BrowserControllerResultResult { + accepted: boolean +} +/** Every controller call names the session the controller is attached to. */ +export interface BrowserControllerParams { + session_id: string +} +export interface BrowserControllerDetachResult { + detached?: boolean +} +export type PingParams = Record +export interface PingResult { + pong: boolean +} +export interface GatewayCapabilitiesResult { + per_session_exclusive_submit: boolean +} +/** ``word`` is the token under the cursor (``@`` prefix = context reference); ``cwd`` / ``session_id`` pick the directory the listing resolves against. */ +export interface CompletePathParams { + profile?: string | null + word?: string | null + cwd?: string | null + session_id?: string | null +} +export interface CompletionItemsResult { + items?: CompletionItem[] +} +/** One popover row; ``kind`` rides only on slash completions (command vs skill). */ +export interface CompletionItem { + text: string + display?: string + meta?: string + kind?: string | null +} +export interface CompleteSlashParams { + text?: string | null +} +/** ``replace_from`` is the column the accepted item replaces from. */ +export interface CompleteSlashResult { + items?: CompletionItem[] + replace_from?: number | null +} +export interface PasteCollapseParams { + text?: string | null +} +export interface PasteCollapseResult { + placeholder: string + path: string + lines: number +} +export interface ModelSaveKeyParams { + slug: string + api_key: string + session_id?: string | null +} +export interface ModelSaveKeyResult { + provider: ModelProviderRow +} +/** One provider row of the shared inventory builder (``hermes_cli.inventory``); the closed set of keys is owned there. */ +export interface ModelProviderRow { + slug: string + name?: string + is_current?: boolean + is_user_defined?: boolean | null + models?: unknown[] + total_models?: number | null + authenticated?: boolean | null + auth_type?: string | null + key_env?: string | null + warning?: string | null + [key: string]: unknown +} +export interface ModelDisconnectParams { + slug: string + session_id?: string | null +} +export interface ModelDisconnectResult { + slug: string + name: string + disconnected: boolean +} +export interface ProfilesListParams { + profile?: string | null + include_sessions?: boolean | string | null +} +/** ``bot_mode_protocol`` tells clients this backend injects the teammate protocol itself. */ +export interface ProfilesListResult { + profiles?: ProfileRow[] + bot_mode_protocol?: boolean +} +/** One roster row; the session fields are present only with ``include_sessions``. */ +export interface ProfileRow { + name: string + path: string + is_default?: boolean + model?: string | null + provider?: string | null + description?: string + display_name?: string + skill_count?: number + last_session?: ProfileSessionPreview | null + worker_session?: ProfileWorkerSession | null + canonical_session?: ProfileCanonicalSession | null + ui_meta_revisions?: Record + ui_meta?: Record | null + has_avatar?: boolean +} +/** Newest human-facing session of a profile (``_latest_profile_session_rows``). */ +export interface ProfileSessionPreview { + id: string + title?: string + preview?: string + started_at?: number + last_active?: number + message_count?: number +} +/** Newest kanban/tool worker row, so rosters can show a profile as working. */ +export interface ProfileWorkerSession { + id: string + source?: string + title?: string + last_active?: number +} +/** The profile's "Bot Chat" registry row; ``resolved_id`` is the live compression tip. */ +export interface ProfileCanonicalSession { + id: string + resolved_id: string + root_title?: string + title?: string + preview?: string + started_at?: number + last_active?: number + message_count?: number +} +/** ``clone_from`` omitted = fresh profile + bundled skills; ``mirror_credentials`` defaults on so a headless bot has a provider. */ +export interface ProfilesCreateParams { + profile?: string | null + name: string + description?: string | null + clone_from?: string | null + clone_all?: boolean | string | null + clone_channels?: boolean | string | null + no_skills?: boolean | string | null + no_alias?: boolean | string | null + soul?: string | null + model?: string | null + provider?: string | null + share_auth?: boolean | string | null + mirror_credentials?: boolean | string | null +} +export interface ProfilesCreateResult { + ok?: boolean + name: string + path: string + soul_written?: boolean + model_set?: boolean + mirrored: ProfileMirrored +} +/** What was copied from the launch profile; ``auth`` is ``"shared"`` under ``share_auth``. */ +export interface ProfileMirrored { + env?: boolean + auth?: boolean | 'shared' + model_inherited?: boolean + voice?: boolean +} +export interface ProfileNameParams { + profile?: string | null + name?: string | null +} +/** Editor snapshot; ``toolsets_pinned`` says whether ``tools.enabled_toolsets`` is explicit. */ +export interface ProfilesDescribeResult { + name: string + description?: string + soul?: string + model: ProfileModelPin + skills?: CapabilityEntry[] + toolsets?: ToolsetEntry[] + toolsets_pinned?: boolean + mcp_servers?: McpServerEntry[] +} +export interface ProfileModelPin { + provider?: string + default?: string +} +export interface CapabilityEntry { + name: string + enabled?: boolean +} +export interface ToolsetEntry { + name: string + enabled?: boolean + label?: string + description?: string + tool_count?: number +} +export interface McpServerEntry { + name: string + enabled?: boolean + transport?: string +} +/** Sections are independent; ``ui_meta_expected_revisions`` is a per-key compare-and-swap. */ +export interface ProfilesConfigureParams { + profile?: string | null + name?: string | null + ui_meta?: Record | null + ui_meta_expected_revisions?: Record | null + soul?: string | null + description?: string | null + model?: string | null + provider?: string | null + confirm_expensive_model?: boolean | string | null + disabled_skills?: string[] | null + enabled_toolsets?: string[] | null + enabled_mcp_servers?: string[] | null +} +/** ``confirm_required`` mirrors ``config.set``: a guarded model pick wrote nothing yet. */ +export interface ProfilesConfigureResult { + ok: boolean + applied: ProfilesConfigureApplied + confirm_required?: boolean | null + confirm_message?: string | null +} +/** Per-section outcome; only the sections the request carried are present. */ +export interface ProfilesConfigureApplied { + ui_meta?: boolean | null + ui_meta_revisions?: Record | null + ui_meta_conflicts?: Record | null + soul?: boolean | null + description?: boolean | null + model?: boolean | null + skills?: boolean | null + toolsets?: boolean | null + mcp_servers?: boolean | null +} +export interface UiMetaConflict { + expected?: unknown + actual?: number +} +/** ``data`` is a data URL or bare base64 (PNG/JPEG/WebP, sniffed); ``clear`` deletes instead. */ +export interface ProfilesSetAssetParams { + profile?: string | null + name?: string | null + asset?: string | null + data?: string | null + clear?: boolean | string | null +} +export interface ProfilesSetAssetResult { + ok?: boolean + asset: string + size?: number + removed?: number | null +} +export interface ProfilesGetAssetParams { + profile?: string | null + name?: string | null + asset?: string | null +} +/** Absent is ``found: false``, not an error. */ +export interface ProfilesGetAssetResult { + found: boolean + mime?: string | null + size?: number | null + data?: string | null +} +export interface ProfilesRememberOnboardingParams { + profile?: string | null + answers?: OnboardingAnswers | null +} +/** ``tui_gateway/onboarding_personalization.py`` — the facts agreed during onboarding. */ +export interface OnboardingAnswers { + name?: string | null + context?: string | null + theme?: string | null + accent?: string | null + layout?: string | null + focus?: string[] | null + connectors?: string[] | null + [key: string]: unknown +} +export interface ProfilesRememberOnboardingResult { + saved?: boolean + profile?: string + target?: string +} +export interface VaultListResult { + items?: VaultItem[] +} +/** Metadata-only view (``VaultItemMeta.to_dict`` + ``backend``); never a secret. */ +export interface VaultItem { + id: string + kind: string + label: string + origin?: string | null + created_at?: string + identifier?: string | null + identifier_type?: string | null + has_otp?: boolean | null + backend: string +} +export interface VaultSourcesResult { + sources?: VaultSource[] +} +export interface VaultSource { + name: string + display_name: string + enabled: boolean + needs_unlock: boolean + unlocked: boolean + installed: boolean +} +export interface VaultSourceSetParams { + profile?: string | null + name?: string | null + enabled?: boolean | null +} +export interface VaultSourceSetResult { + name: string + enabled: boolean +} +/** The master password is consumed by the manager CLI and never stored or logged. */ +export interface VaultUnlockParams { + profile?: string | null + name?: string | null + password?: string | null +} +export interface VaultUnlockResult { + name: string + unlocked?: boolean +} +export interface VaultLockParams { + profile?: string | null + name?: string | null +} +export interface VaultLockResult { + locked?: boolean +} +/** ``secret`` goes straight into the encrypted store; the result carries only the new id. */ +export interface VaultAddParams { + profile?: string | null + kind?: VaultKind | null + label?: string | null + origin?: string | null + secret?: Record | null +} +export type VaultKind = 'login' | 'payment' | 'address' +export interface VaultAddResult { + id: string +} +export interface VaultRemoveParams { + profile?: string | null + id?: string | null +} +export interface VaultRemoveResult { + removed: boolean +} +export interface SessionForeignListParams { + profile?: string | null + source?: ForeignSource | null + offset?: number | null + limit?: number | null +} +export type ForeignSource = 'claude' | 'codex' +/** ``unreadable`` counts logs on this page that failed to parse. */ +export interface SessionForeignListResult { + sessions?: ForeignSessionRow[] + next_offset?: number | null + host: string + unreadable?: number +} +/** ``hermes_cli/foreign_sessions_browser.py::list_foreign_sessions`` — ``id`` is an opaque handle, never a path. */ +export interface ForeignSessionRow { + id: string + source: ForeignSource + label: string + title?: string + cwd?: string | null + mtime: number + turn_count?: number + excerpt?: string +} +export interface SessionForeignIdParams { + profile?: string | null + id?: string | null +} +/** Bounded to the last 40 turns / 8000 chars each; ``already_imported`` is the local id. */ +export interface SessionForeignPreviewResult { + messages?: ForeignTurn[] + total?: number + truncated?: boolean + already_imported?: string | null + cwd?: string | null +} +export interface ForeignTurn { + role: string + content: string +} +export interface SessionForeignImportResult { + session_id: string + already_imported?: boolean +} +/** ``delegations`` is reserved for async delegation records and is currently always empty. */ +export interface SubagentListResult { + subagents?: SubagentSnapshot[] + delegations?: Record[] +} +/** ``methods_subagents._SUBAGENT_SNAPSHOT_FIELDS`` projection of one live child record. */ +export interface SubagentSnapshot { + subagent_id: string + parent_id?: string | null + depth?: number | null + goal?: string | null + delegation_id?: string | null + model?: string | null + started_at?: number | null + status?: SubagentStatus | null + tool_count?: number | null + last_tool?: string | null + accepting_steer?: boolean | null +} +/** Lifecycle of one delegated child (``tools/delegate_tool_child_run.py``); ``failed`` / ``error`` / ``timeout`` / ``interrupted`` / ``completed`` are terminal. */ +export type SubagentStatus = 'queued' | 'running' | 'completed' | 'failed' | 'error' | 'timeout' | 'interrupted' +export interface SubagentIdParams { + session_id: string + profile?: string | null + subagent_id: string +} +export interface SubagentInterruptResult { + found: boolean + subagent_id: string +} +/** ``available`` is false while the child has no live transcript yet (or it was cleaned up). */ +export interface SubagentTailResult { + subagent_id: string + available?: boolean + text?: string + truncated?: boolean +} +/** ``methods_projects._projects_payload``: every project (archived included) + the active id. */ +export interface ProjectsPayload { + projects: ProjectInfo[] + active_id?: string | null +} +/** ``hermes_cli/projects_db.py::Project.to_dict`` — one stored project with its folders. */ +export interface ProjectInfo { + id: string + slug: string + name: string + description?: string | null + icon?: string | null + color?: string | null + board_slug?: string | null + primary_path?: string | null + archived?: boolean + created_at: number + folders?: ProjectFolder[] +} +/** ``hermes_cli/projects_db.py::ProjectFolder.to_dict``. */ +export interface ProjectFolder { + path: string + label?: string | null + is_primary?: boolean + added_at?: number | null +} +/** Any method addressed at one stored project (``5062`` when the id resolves to nothing). */ +export interface ProjectIdParams { + profile?: string | null + id: string +} +export interface ProjectResult { + project: ProjectInfo +} +/** ``use`` also activates the new project. */ +export interface ProjectsCreateParams { + profile?: string | null + name: string + folders?: string[] | null + slug?: string | null + primary_path?: string | null + description?: string | null + icon?: string | null + color?: string | null + board_slug?: string | null + use?: boolean +} +export interface OptionalProjectResult { + project?: ProjectInfo | null +} +/** Absent keys are left untouched; ``''`` clears ``color`` / ``icon``. */ +export interface ProjectsUpdateParams { + profile?: string | null + id: string + name?: string | null + description?: string | null + icon?: string | null + color?: string | null + board_slug?: string | null +} +export interface ProjectsAddFolderParams { + profile?: string | null + id: string + path: string + label?: string | null + is_primary?: boolean +} +export interface ProjectFolderParams { + profile?: string | null + id: string + path: string +} +export interface ProjectsArchiveParams { + profile?: string | null + id: string + restore?: boolean +} +/** No ``id`` (or null) clears the active project. */ +export interface ProjectsSetActiveParams { + profile?: string | null + id?: string | null +} +export interface ActiveIdResult { + active_id?: string | null +} +/** Absent ``cwd`` resolves the gateway's default completion cwd. */ +export interface ProjectsForCwdParams { + profile?: string | null + cwd?: string | null +} +export interface ProjectsForCwdResult { + project?: ProjectInfo | null + cwd: string + branch?: string +} +/** ``scan`` asks the host to walk the policy roots itself (remote-gateway desktop). */ +export interface ProjectsDiscoverReposParams { + profile?: string | null + scan?: boolean +} +export interface ProjectsDiscoverReposResult { + repos: DiscoveredRepo[] + discovery_policy?: RepoDiscoveryPolicy | null +} +/** ``methods_projects._discover_repos_payload`` row: a git root with session totals. */ +export interface DiscoveredRepo { + root: string + label?: string + sessions?: number + last_active?: number +} +/** ``methods_projects._repo_discovery_policy`` — the effective ``desktop.repo_scan_*`` config. */ +export interface RepoDiscoveryPolicy { + enabled: boolean + roots: string[] + exclude_paths: string[] +} +/** Repos as ``{root, label}`` objects or bare root strings; entries without a root are skipped. */ +export interface ProjectsRecordReposParams { + profile?: string | null + repos?: (RecordRepoItem | string)[] | null + discovery_policy?: RepoDiscoveryPolicyParams | null +} +export interface RecordRepoItem { + root: string + label?: string | null +} +/** The policy the desktop scanned under (short or ``repo_scan_*`` long keys both accepted). */ +export interface RepoDiscoveryPolicyParams { + enabled?: boolean | null + roots?: string[] | null + exclude_paths?: string[] | null + repo_scan_enabled?: boolean | null + repo_scan_roots?: string[] | null + repo_scan_exclude_paths?: string[] | null +} +export interface ProjectsRecordReposResult { + repos: DiscoveredRepo[] + discovery_policy?: RepoDiscoveryPolicy | null + accepted: boolean +} +export interface ProjectsTreeParams { + profile?: string | null + preview_limit?: number | null + session_limit?: number | null +} +export interface ProjectsTreeResult { + projects: ProjectTreeNode[] + active_id?: string | null + scoped_session_ids?: string[] +} +/** ``project_tree._project_node`` — explicit, auto (git root) or the synthetic Home bucket. */ +export interface ProjectTreeNode { + id: string + label: string + path?: string | null + color?: string | null + icon?: string | null + isAuto?: boolean + isNoProject?: boolean + sessionCount?: number + lastActive?: number + totalTokens?: number + totalCostUsd?: number + repos?: ProjectTreeRepo[] + previewSessions?: ProjectTreeSession[] +} +export interface ProjectTreeRepo { + id: string + label: string + path?: string | null + groups?: ProjectTreeLane[] + sessionCount?: number +} +/** One branch / worktree / kanban lane inside a repo; ``sessions`` is empty unless hydrated. */ +export interface ProjectTreeLane { + id: string + label: string + path?: string | null + isMain?: boolean + isKanban?: boolean + sessions?: ProjectTreeSession[] +} +/** ``methods_projects._project_tree_row`` + ``project_tree.stamp_profile``: the minimal row the sidebar renders, stamped with the profile it belongs to. */ +export interface ProjectTreeSession { + id: string + title?: string | null + preview?: string | null + source?: string | null + model?: string | null + started_at?: number | null + ended_at?: number | null + last_active?: number | null + message_count?: number + tool_call_count?: number + input_tokens?: number + output_tokens?: number + is_active?: boolean + cwd?: string | null + git_branch?: string | null + git_repo_root?: string | null + parent_session_id?: string | null + pinned?: boolean | null + unread?: boolean | null + archived?: boolean | null + actual_cost_usd?: number | null + estimated_cost_usd?: number | null + handoff_platform?: string | null + handoff_state?: string | null + _lineage_root_id?: string | null + _lineage_ids?: string[] | null + profile?: string | null + [key: string]: unknown +} +export interface ProjectsProjectSessionsParams { + profile?: string | null + project_id: string + session_limit?: number | null +} +export interface ProjectsProjectSessionsResult { + project?: ProjectTreeNode | null +} +/** ``knownRevision``: the spritesheet revision the caller already holds (send-once bytes). */ +export interface PetInfoParams { + profile?: string | null + knownRevision?: string | null +} +/** ``server._pet_sprite_payload`` behind ``enabled``; every sprite field is absent when the pet display is off, ``spritesheetBase64`` is elided when ``spritesheetUnchanged``. */ +export interface PetInfoResult { + enabled: boolean + slug?: string | null + displayName?: string | null + mime?: string | null + spritesheetBase64?: string | null + spritesheetRevision?: string | null + spritesheetUnchanged?: boolean | null + frameW?: number | null + frameH?: number | null + framesPerState?: number | null + framesByState?: Record | null + framesByRow?: Record | null + loopMs?: number | null + scale?: number | null + stateRows?: string[] | null + [key: string]: unknown +} +export interface PetInfoMetaResult { + enabled: boolean + slug?: string | null + displayName?: string | null + scale?: number | null + spritesheetRevision?: string | null +} +/** ``graphics`` opts into the kitty payload when the TTY speaks it; ``cols`` overrides the width. */ +export interface PetCellsParams { + profile?: string | null + state?: string | null + cols?: number | null + graphics?: boolean +} +/** Unicode: ``frames`` is frame → row → cell ``[tr,tg,tb,ta, br,bg,bb,ba]``; kitty (``graphics`` set): ``frames`` are transmit escapes and ``placeholder`` the text grid. */ +export interface PetCellsResult { + enabled: boolean + slug?: string | null + displayName?: string | null + state?: string | null + cols?: number | null + frameMs?: number | null + frames?: number[][][][] | string[] | null + scale?: number | null + graphics?: string | null + imageId?: number | null + color?: string | null + rows?: number | null + placeholder?: string[] | null +} +export interface PetGalleryParams { + profile?: string | null + localOnly?: boolean +} +export interface PetGalleryResult { + enabled: boolean + active?: string + pets?: PetGalleryEntry[] +} +export interface PetGalleryEntry { + slug: string + displayName: string + installed: boolean + spritesheetUrl?: string + curated?: boolean | null + generated?: boolean +} +export interface PetSlugParams { + profile?: string | null + slug: string +} +export interface PetSlugResult { + ok: boolean + slug: string + displayName?: string | null +} +export interface PetRenameParams { + profile?: string | null + slug: string + name: string +} +export interface PetExportResult { + ok: boolean + filename: string + zipBase64: string +} +/** ``url``: spritesheet source for a not-yet-installed pet. */ +export interface PetThumbParams { + profile?: string | null + slug: string + url?: string | null +} +export interface PetThumbResult { + ok: boolean + slug: string + dataUri?: string | null +} +export interface PetScaleParams { + profile?: string | null + scale?: unknown +} +export interface PetScaleResult { + ok: boolean + scale: number +} +/** ``text`` is normally a string; the relay / hosted paths may hand a structured (parts list) payload, and the busy path renders it. Truncation (rewind / edit / regenerate) needs explicit consent: ``confirm_truncate`` plus one durable target (``truncate_before_row_id`` preferred, ``truncate_before_message_id``, or the legacy ``truncate_before_user_ordinal``). */ +export interface PromptSubmitParams { + session_id: string + profile?: string | null + text?: unknown + display_kind?: string | null + interrupted?: boolean | null + queued?: boolean | null + surface?: string | null + voice_context?: string | null + truncate_before_user_ordinal?: number | null + truncate_before_row_id?: number | null + truncate_before_message_id?: string | null + confirm_truncate?: boolean | null + confirm_empty_truncate?: boolean | null + rebind_survivor_row_ids?: number[] | null +} +/** ``status`` is absent only on the typed-stop-phrase reply (``voice_stopped``). After a truncation the survivor row ids let the client rebind its cached ``rowId``s (``None`` map entries: drop the cached id). ``turn_isolation`` marks a compute-host dispatch. */ +export interface PromptSubmitResult { + status?: PromptSubmitStatus | null + voice_stopped?: boolean | null + survivor_user_row_ids?: (number | null)[] | null + survivor_row_id_map?: Record | null + turn_isolation?: boolean | null +} +export type PromptSubmitStatus = 'streaming' | 'queued' | 'steered' | 'redirected' +export interface ClipboardPasteParams { + session_id: string + profile?: string | null +} +/** ``methods_prompt.py::_attached_image_result``: the image is queued for the next turn. */ +export interface AttachedImageResult { + name?: string | null + width?: number | null + height?: number | null + token_estimate?: number | null + attached: boolean + path?: string | null + count?: number | null + remainder?: string | null + text?: string | null + bytes?: number | null + message?: string | null +} +export interface ImageAttachParams { + session_id: string + profile?: string | null + path: string +} +/** ``content_base64`` (or the ``data`` alias) carries the bytes; ``filename`` / ``ext`` only hint the extension — magic bytes decide. */ +export interface ImageAttachBytesParams { + session_id: string + profile?: string | null + content_base64?: string | null + data?: string | null + filename?: string | null + ext?: string | null +} +/** Host ``path`` or base64 ``content_base64`` / ``data``; ``first_page`` / ``last_page`` bound the render (per-call page cap enforced server-side). */ +export interface PdfAttachParams { + session_id: string + profile?: string | null + path?: string | null + content_base64?: string | null + data?: string | null + filename?: string | null + first_page?: number | null + last_page?: number | null +} +export interface PdfAttachResult { + attached: boolean + filename: string + pages_attached: number + pages: PdfPage[] + count: number + text: string +} +export interface PdfPage { + name?: string | null + width?: number | null + height?: number | null + token_estimate?: number | null + path: string + page: number +} +/** ``path`` when the file is gateway-visible, else ``data_url`` carries the bytes; ``name`` labels an uploaded file. */ +export interface FileAttachParams { + session_id: string + profile?: string | null + path?: string | null + data_url?: string | null + name?: string | null +} +export interface FileAttachResult { + attached: boolean + name: string + path: string + ref_path: string + ref_text: string + uploaded: boolean +} +export interface ImageDetachParams { + session_id: string + profile?: string | null + path: string +} +export interface ImageDetachResult { + detached: boolean + count: number +} +export interface InputDetectDropParams { + session_id: string + profile?: string | null + text?: string | null +} +/** ``matched: false`` alone when the text is not a drop; an image drop is queued immediately (``is_image`` + ``count``), a file drop only yields the ``text`` to insert. */ +export interface InputDetectDropResult { + name?: string | null + width?: number | null + height?: number | null + token_estimate?: number | null + matched: boolean + is_image?: boolean | null + path?: string | null + count?: number | null + text?: string | null +} +export interface SideAgentParams { + session_id: string + profile?: string | null + text: string +} +/** The side agent runs detached; its answer lands on the parent session as an event carrying this ``task_id``. */ +export interface TaskIdResult { + task_id: string +} +export interface PreviewRestartParams { + session_id: string + profile?: string | null + url: string + cwd?: string | null + context?: string | null +} +export interface ClarifyLockParams { + request_id: string + question_id: string + answer?: unknown + profile?: string | null +} +/** ``remaining`` lists the qids still unanswered; the lock that empties it resolves the request. ``expired``: the wait already ended (timeout / cancel) — not an error. */ +export interface ClarifyLockResult { + status: ClarifyLockStatus + remaining?: string[] | null +} +export type ClarifyLockStatus = 'ok' | 'expired' +export interface RequestAnswerParams { + id: string + result: Record + profile?: string | null +} +export interface RequestAnswerResult { + status: ClarifyLockStatus +} +export interface ApprovalPendingParams { + session_id: string + profile?: string | null +} +export interface ApprovalPendingResult { + approvals: tui_gateway_contracts_prompt_voice_PendingApproval[] +} +/** One unresolved ``tools/approval.py`` gateway queue entry (snapshot of its ``data``); the key set is owned by the approval tool, so it stays open. */ +export interface tui_gateway_contracts_prompt_voice_PendingApproval { + request_id?: string | null + command?: string | null + description?: string | null + pattern_key?: string | null + pattern_keys?: string[] | null + allow_permanent?: boolean | null + allow_session?: boolean | null + smart_denied?: boolean | null + choices?: string[] | null + tool_name?: string | null + [key: string]: unknown +} +export interface ApprovalReceivedParams { + session_id: string + profile?: string | null + request_id: string +} +export interface ApprovalReceivedResult { + acknowledged: boolean +} +/** ``choice`` is one of the offered ``approval`` choices (once / session / always / deny); ``all`` resolves every pending approval, ``request_id`` a specific one, neither the oldest. */ +export interface ApprovalRespondParams { + session_id: string + profile?: string | null + choice?: string | null + all?: boolean | null + request_id?: string | null +} +export interface ApprovalRespondResult { + resolved: number +} +export interface VoiceToggleParams { + action?: VoiceToggleAction + profile?: string | null +} +export type VoiceToggleAction = 'status' | 'on' | 'off' | 'tts' +/** ``methods_voice.py::_voice_status_payload`` (+ the requirements probe on ``status``, the spoken stop hint on ``on``). */ +export interface VoiceToggleResult { + enabled: boolean + record_key: string + tts: boolean + stop_hint?: string | null + available?: boolean | null + audio_available?: boolean | null + stt_available?: boolean | null + details?: string | null +} +export interface VoiceRecordParams { + action?: VoiceRecordAction + session_id?: string | null + profile?: string | null +} +export type VoiceRecordAction = 'start' | 'stop' +export interface VoiceRecordResult { + status: VoiceRecordStatus + reason?: string | null +} +export type VoiceRecordStatus = 'recording' | 'stopped' | 'busy' +export interface VoiceTtsParams { + text: string + profile?: string | null +} +export interface VoiceTtsResult { + status: string +} +/** ``surface`` names the caller ("tui" | "gui"); ``persist`` is the explicit gesture that also flips ``wake_word.enabled`` on; ``client_capture`` asks for PCM streamed via wake.feed. */ +export interface WakeStartParams { + surface?: string | null + persist?: boolean | null + client_capture?: boolean | null + session_id?: string | null + profile?: string | null +} +/** ``started: false`` carries ``reason`` (unavailable / disabled / disabled_for_surface / owned); ``sample_rate`` / ``frame_length`` describe the PCM frames the armed detector expects. */ +export interface WakeStartResult { + started: boolean + reason?: string | null + hint?: string | null + phrase?: string | null + provider?: string | null + owner_surface?: string | null + enabled_persisted?: boolean | null + capture?: string | null + sample_rate?: number | null + frame_length?: number | null +} +export interface WakeStopParams { + persist?: boolean | null + profile?: string | null +} +export interface WakeStopResult { + reason?: string | null + stopped: boolean + disabled_persisted: boolean +} +export interface WakeControlParams { + profile?: string | null +} +export interface WakePauseResult { + reason?: string | null + paused: boolean +} +export interface WakeResumeResult { + reason?: string | null + resumed: boolean +} +export interface WakeStatusParams { + surface?: string | null + client_capture?: boolean | null + profile?: string | null +} +/** ``enabled`` is config truth; ``listening`` is this caller's armed detector; ``audio_silent`` means armed but deaf (see ``hint``). */ +export interface WakeStatusResult { + listening: boolean + owned_by_caller: boolean + owner_surface?: string | null + phrase: string + provider: string + configured_surface: string + input_device: WakeInputDevice + available: boolean + hint: string + enabled: boolean + audio_silent: boolean + capture: string + local_input_available: boolean + sample_rate: number + frame_length: number +} +/** ``tools/wake_word.py::_describe_input_device`` — PortAudio diagnostics for the configured mic. */ +export interface WakeInputDevice { + selector?: number | string | null + name?: string | null + error?: string | null + max_input_channels?: number | null + default_samplerate?: number | null + hostapi_index?: number | null + hostapi?: string | null + [key: string]: unknown +} +/** ``pcm`` (or the ``pcm_b64`` alias): base64 int16 mono little-endian, 16 kHz only. */ +export interface WakeFeedParams { + pcm?: string | null + pcm_b64?: string | null + sample_rate?: number | null + profile?: string | null +} +export interface WakeFeedResult { + reason?: string | null + fed: boolean +} +export interface SessionCreateParams { + profile?: string | null + cols?: number | null + source?: string | null + cwd?: string | null + messages?: SeedMessage[] | null + parent_session_id?: string | null + title?: string | null + model?: string | null + provider?: string | null + reasoning_effort?: string | null + fast?: boolean | null + close_on_disconnect?: boolean + hidden?: boolean + room_plumbing?: boolean + follow_profile_config?: boolean +} +/** One create-time transcript row (``session_history._coerce_seed_history``); ``text`` is the legacy alias of ``content``; only ``display_kind: "hidden"`` is accepted from the wire. */ +export interface SeedMessage { + role: string + content?: string | null + text?: string | null + display_kind?: string | null +} +export interface SessionCreateResult { + session_id: string + stored_session_id: string + message_count: number + messages: TranscriptMessage[] + info: SessionLiveInfo +} +/** One stored transcript row as ``session.history`` / resume ``messages`` deliver it. */ +export interface TranscriptMessage { + role: string + content?: unknown + timestamp?: number | null + tool_calls?: Record[] | null + tool_call_id?: string | null + name?: string | null + display_kind?: string | null + row_id?: number | null + reasoning?: string | null + [key: string]: unknown +} +/** ``session_id`` is the STORED id (or an exact title); the reply's ``session_id`` is the runtime id. */ +export interface SessionResumeParams { + session_id: string + profile?: string | null + cols?: number | null + source?: string | null + lazy?: boolean + defer_history?: boolean + omit_messages?: boolean + eager_build?: boolean + close_on_disconnect?: boolean +} +export interface SessionResumeResult { + session_id: string + message_count: number + messages: TranscriptMessage[] + info: SessionLiveInfo + stored_session_id?: string | null + resumed?: string | null + session_key?: string | null + messages_omitted?: boolean | null + hydrating?: boolean | null + running?: boolean | null + turn_started_at?: number | null + started_at?: number | null + status?: string | null + inflight?: InflightTurn | null + queued?: QueuedPrompt | null + pending_approval?: tui_gateway_contracts_sessions_PendingApproval | null + open_requests?: OpenRequestEntry[] | null + todo_state?: TodoState | null + auto_continue?: AutoContinue | null +} +/** ``session_auto_continue._inflight_snapshot``: the live (or retained failed) turn a reconnecting client rebuilds its bubbles from. */ +export interface InflightTurn { + assistant?: string + streaming?: boolean + user?: string + corrections?: string[] | null + correction_offsets?: number[] | null + error?: string | null + status?: string | null + recoverable?: boolean | null + error_surface?: Record | null +} +export interface QueuedPrompt { + user: string +} +/** ``server._approval_request_payload`` for the oldest unresolved approval (command redacted). */ +export interface tui_gateway_contracts_sessions_PendingApproval { + request_id?: string | null + command?: string | null + description?: string | null + choices?: string[] | null + allow_permanent?: boolean | null + allow_session?: boolean | null + smart_denied?: boolean | null + tool_name?: string | null + [key: string]: unknown +} +/** 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 +} +/** ``tool_progress._normalize_todo_state``: the authoritative todo snapshot. */ +export interface TodoState { + todos: Record[] + revision: number +} +/** A crash-interrupted turn was scheduled to continue right after this resume. */ +export interface AutoContinue { + attempt: number + interrupted_at: number +} +export interface SessionActivateParams { + session_id: string + profile?: string | null + cols?: number | null + omit_messages?: boolean +} +export interface SessionActivateResult { + session_id: string + message_count: number + messages: TranscriptMessage[] + info: SessionLiveInfo + stored_session_id?: string | null + resumed?: string | null + session_key?: string | null + messages_omitted?: boolean | null + hydrating?: boolean | null + running?: boolean | null + turn_started_at?: number | null + started_at?: number | null + status?: string | null + inflight?: InflightTurn | null + queued?: QueuedPrompt | null + pending_approval?: tui_gateway_contracts_sessions_PendingApproval | null + open_requests?: OpenRequestEntry[] | null + todo_state?: TodoState | null + auto_continue?: AutoContinue | null +} +export interface SessionListParams { + profile?: string | null + title?: string | null + limit?: number | null + include_hidden?: boolean +} +export interface SessionListResult { + sessions: SessionListRow[] +} +/** ``methods_session._session_row_summary``; ``resolved_id`` only on a title lookup that followed a compression lineage to its tip. */ +export interface SessionListRow { + id: string + resolved_id?: string | null + title?: string + preview?: string + started_at?: number + message_count?: number + source?: string +} +export interface SessionMostRecentParams { + profile?: string | null +} +export interface SessionMostRecentResult { + session_id: string | null + title?: string | null + started_at?: number | null + source?: string | null +} +export interface SessionActiveListParams { + profile?: string | null + current_session_id?: string | null +} +export interface SessionActiveListResult { + sessions: SessionActiveItem[] +} +/** ``server._session_live_item``. */ +export interface SessionActiveItem { + current: boolean + id: string + last_active: number + message_count: number + model: string + preview: string + session_key: string + started_at: number + status: LiveSessionStatus + title: string +} +export type LiveSessionStatus = 'idle' | 'starting' | 'waiting' | 'working' | 'streaming' | 'resuming' +/** ``session_id`` is the STORED id. */ +export interface SessionDeleteParams { + session_id: string + profile?: string | null +} +export interface SessionDeleteResult { + deleted: string +} +export interface SessionTitleParams { + session_id: string + profile?: string | null + title?: string | null +} +export interface SessionTitleResult { + title: string + session_key?: string | null + pending?: boolean | null +} +/** ``session_id`` is a live runtime id first, else a stored id / key / title. */ +export interface SessionSetHiddenParams { + session_id: string + hidden?: boolean + profile?: string | null +} +export interface SessionSetHiddenResult { + hidden: boolean + session_key: string +} +export interface SessionWorkspaceMoveParams { + profile?: string | null + session_key: string + cwd: string +} +export interface SessionWorkspaceMoveResult { + cwd: string + branch?: string | null + git_repo_root?: string | null +} +export interface SessionCwdSetParams { + session_id: string + profile?: string | null + cwd: string +} +/** The refreshed ``session.info`` view (full agent view, or the lazy shape). */ +export interface SessionCwdSetResult { + model?: string + provider?: string + reasoning_effort?: string + service_tier?: string + fast?: boolean + yolo?: boolean + approval_mode?: string + tools?: Record + skills?: Record + cwd?: string + branch?: string | null + project?: ProjectRef | null + terminal_backend?: string + personality?: string + running?: boolean + turn_started_at?: number | null + title?: string + stored_session_id?: string + desktop_contract?: number | string | null + version?: string + release_date?: string + update_behind?: unknown | null + update_command?: string + usage?: Usage | null + profile_name?: string | null + mcp_servers?: McpServerStatus[] + system_prompt?: string | null + credential_warning?: string | null + lazy?: boolean | null + [key: string]: unknown +} +export interface SessionCloseParams { + session_id: string + profile?: string | null +} +export interface SessionCloseResult { + closed: boolean +} +export interface SessionBranchParams { + session_id: string + profile?: string | null + name?: string | null + count?: number | null +} +export interface SessionBranchResult { + session_id: string + stored_session_id: string + title: string + parent: string + message_count: number + messages: TranscriptMessage[] + info: SessionLiveInfo +} +export interface SessionUndoParams { + session_id: string + profile?: string | null +} +export interface SessionUndoResult { + removed: number +} +export interface SessionSaveParams { + session_id: string + profile?: string | null +} +/** Under turn isolation the compute host's result passes through verbatim. */ +export interface SessionSaveResult { + file?: string | null + [key: string]: unknown +} +export interface SessionStatusParams { + session_id: string + profile?: string | null +} +export interface SessionStatusResult { + output: string +} +export interface SessionHistoryParams { + session_id: string + profile?: string | null +} +export interface SessionHistoryResult { + count: number + messages: TranscriptMessage[] +} +export interface SessionUsageParams { + session_id: string + profile?: string | null +} +export interface SessionUsageResult { + model?: string + input?: number + output?: number + reasoning?: number + prompt?: number + completion?: number + total?: number + calls?: number + compressions?: number | null + context_used?: number | null + context_max?: number | null + context_percent?: number | null + context_source?: string | null + context_estimated?: boolean | null + cache_hit_pct?: number | null + cache_read?: number | null + cache_write?: number | null + avg_latency_s?: number | null + avg_tps?: number | null + active_subagents?: number | null + dev_credits_spent_micros?: number | null + cost_usd?: number | null + cost_status?: string | null + credits_lines?: string[] | null + [key: string]: unknown +} +export interface SessionContextBreakdownParams { + session_id: string + profile?: string | null +} +/** ``agent.context_breakdown.compute_session_context_breakdown`` (empty categories before the agent builds). */ +export interface SessionContextBreakdownResult { + categories: ContextCategory[] + context_max: number + context_percent: number + context_used: number + estimated_total: number + context_estimated: boolean + context_source: string + model: string +} +export interface ContextCategory { + color: string + id: string + label: string + tokens: number +} +export interface SessionCompressParams { + session_id: string + profile?: string | null + focus_topic?: string | null +} +/** In-process: the before/after summary + replacement transcript. Compute host: its result passes through (hence open) with ``turn_isolation``; a lock held elsewhere answers ``compressed: false``. */ +export interface SessionCompressResult { + status?: string | null + removed?: number | null + before_messages?: number | null + after_messages?: number | null + before_tokens?: number | null + after_tokens?: number | null + summary?: CompressionSummary | null + usage?: Usage | null + info?: SessionLiveInfo | null + messages?: TranscriptMessage[] | null + compressed?: boolean | null + lock_held?: boolean | null + message?: string | null + turn_isolation?: boolean | null + host_ack?: Record | null + [key: string]: unknown +} +/** ``agent.manual_compression_feedback.summarize_manual_compression``. */ +export interface CompressionSummary { + noop?: boolean + aborted?: boolean + refused_would_grow?: boolean | null + fallback_used?: boolean | null + headline?: string + token_line?: string + note?: string | null + [key: string]: unknown +} +export interface SessionInterruptParams { + session_id: string + profile?: string | null + expected_hosted_task_id?: string | null +} +export interface SessionInterruptResult { + status: InterruptStatus + interrupted?: boolean | null + turn_isolation?: boolean | null +} +export type InterruptStatus = 'interrupted' | 'not_interrupted' +export interface SessionCorrectionParams { + session_id: string + profile?: string | null + text: string +} +export interface SessionCorrectionResult { + status: CorrectionStatus + text: string +} +export type CorrectionStatus = 'queued' | 'redirected' | 'rejected' +export interface SpawnTreeSaveParams { + profile?: string | null + subagents: Record[] + session_id?: string | null + started_at?: number | null + finished_at?: number | null + label?: string | null +} +export interface SpawnTreeSaveResult { + path: string + session_id: string +} +export interface SpawnTreeListParams { + profile?: string | null + session_id?: string | null + cross_session?: boolean + limit?: number | null +} +export interface SpawnTreeListResult { + entries: SpawnTreeEntry[] +} +/** Index row (``server._append_spawn_tree_index``) or a legacy file scan. */ +export interface SpawnTreeEntry { + path: string + session_id?: string | null + started_at?: number | null + finished_at?: number | null + label?: string + count?: number + [key: string]: unknown +} +export interface SpawnTreeLoadParams { + profile?: string | null + path: string +} +/** The snapshot file as written by ``spawn_tree.save`` (open: the file is the contract). */ +export interface SpawnTreeLoadResult { + session_id?: string | null + started_at?: number | null + finished_at?: number | null + label?: string | null + subagents?: Record[] + [key: string]: unknown +} +export interface TerminalResizeParams { + session_id: string + profile?: string | null + cols?: number | null +} +export interface TerminalResizeResult { + cols: number +} +export interface SessionEventsSinceParams { + session_id: string + profile?: string | null + last_seen?: number | null +} +export interface SessionEventsSinceResult { + events: Record[] + latest_seq: number + truncated: boolean + count: number + epoch: string + open_requests: OpenRequestEntry[] +} +export interface SessionEventsStatsParams { + profile?: string | null +} +/** ``event_replay.replay_stats``. */ +export interface SessionEventsStatsResult { + sessions: number + events: number + bytes: number + max_per_session: number + max_bytes_per_session: number + max_bytes_process: number +} +/** Needs a ``template`` or ``instructions`` / ``input``; a live ``session_id`` lends its model. */ +export interface LlmOneshotParams { + profile?: string | null + template?: string | null + instructions?: string | null + input?: string | null + variables?: Record | null + task?: string | null + temperature?: number | null + max_tokens?: number | null + session_id?: string | null +} +export interface LlmOneshotResult { + text: string +} +export interface SystemBatteryParams { + profile?: string | null +} +export interface SystemBatteryResult { + available: boolean + percent?: number | null + plugged?: boolean | null + category?: BatteryCategory +} +/** ``agent/battery.py::battery_category`` colour bucket. */ +export type BatteryCategory = 'good' | 'warn' | 'bad' | 'critical' | 'dim' +export interface ProcessStopParams { + session_id?: string | null + profile?: string | null +} +export interface ProcessStopResult { + killed: number +} +export interface AgentsListParams { + profile?: string | null +} +export interface AgentsListResult { + processes?: AgentProcessRow[] +} +export interface AgentProcessRow { + session_id: string + command: string + status: string + uptime: number +} +export interface ProcessListParams { + session_id: string + profile?: string | null +} +export interface ProcessListResult { + processes?: ProcessEntry[] +} +/** ``tools/process_registry.py::list_sessions`` row plus the gateway's ``output_tail``. */ +export interface ProcessEntry { + session_id: string + command?: string + cwd?: string | null + pid?: number | null + owner_task_id?: string | null + started_at?: string | null + uptime_seconds?: number | null + status?: string + output_preview?: string + output_tail?: string | null + session_scoped?: boolean | null + watch_patterns?: string[] | null + watch_hit?: boolean | null + notify_on_complete?: boolean | null + exit_code?: number | null + detached?: boolean | null + [key: string]: unknown +} +export interface ProcessKillParams { + session_id: string + process_id: string + profile?: string | null +} +/** ``tools/process_registry.py::kill_process`` snapshot; ``error`` rides on the failure statuses. */ +export interface ProcessKillResult { + status: ProcessKillStatus + session_id?: string | null + command?: string | null + exit_code?: number | null + completion_reason?: string | null + termination_source?: string | null + output?: string | null + error?: string | null + [key: string]: unknown +} +export type ProcessKillStatus = 'killed' | 'already_exited' | 'not_found' | 'error' +export interface ShellExecParams { + command: string + profile?: string | null +} +export interface ShellExecResult { + stdout: string + stderr: string + code: number +} +export interface CliExecParams { + argv: string[] + timeout?: number | null + profile?: string | null +} +export interface CliExecResult { + blocked: boolean + code: number + output: string + hint?: string | null +} +export interface CommandsCatalogParams { + session_id?: string | null + profile?: string | null +} +export interface CommandsCatalogResult { + pairs?: string[][] + sub?: Record + canon?: Record + commands?: Record + categories?: CommandCategory[] + skills?: Record + skill_count?: number + warning?: string +} +export interface CommandCatalogMeta { + argument_mode?: ArgumentMode | null + desktop?: string | null +} +export type ArgumentMode = 'options' | 'text' | 'mixed' +export interface CommandCategory { + name: string + pairs?: string[][] +} +export interface SkillCatalogEntry { + usage?: number + origin?: string +} +export interface CommandResolveParams { + name?: string | null + profile?: string | null +} +export interface CommandResolveResult { + canonical: string + description: string + category: string +} +export interface CommandDispatchParams { + name: string + arg?: string | null + session_id?: string | null + profile?: string | null +} +/** One structured directive: ``exec``/``plugin`` carry ``output``; ``alias`` a ``target``; ``send``/``prefill``/``skill`` a ``message`` (UIs render ``display``, never ``message``). */ +export interface CommandDispatchResult { + type: DispatchType + output?: string | null + target?: string | null + message?: string | null + notice?: string | null + display?: string | null + name?: string | null + status?: string | null +} +/** ``apps/shared/src/slash.ts::parseCommandDispatch`` branches on this. */ +export type DispatchType = 'exec' | 'alias' | 'plugin' | 'send' | 'skill' | 'prefill' +export interface SlashExecParams { + session_id: string + command: string + profile?: string | null +} +/** Plain worker/plugin text in ``output`` (+ ``warning``), or — when the command was rerouted to ``command.dispatch`` — that method's directive fields with ``type`` set. */ +export interface SlashExecResult { + output?: string | null + warning?: string | null + type?: DispatchType | null + target?: string | null + message?: string | null + notice?: string | null + display?: string | null + name?: string | null + status?: string | null +} +export interface InsightsGetParams { + days?: number | null + profile?: string | null +} +export interface InsightsGetResult { + days: number + sessions: number + messages: number +} +export interface ConfigShowParams { + profile?: string | null +} +export interface ConfigShowResult { + sections?: ConfigSection[] + [key: string]: unknown +} +export interface ConfigSection { + title: string + rows?: string[][] +} +export interface RollbackListParams { + session_id: string + profile?: string | null +} +export interface RollbackListResult { + enabled: boolean + checkpoints?: RollbackCheckpoint[] +} +export interface RollbackCheckpoint { + hash?: string + timestamp?: string + message?: string +} +export interface RollbackRestoreParams { + session_id: string + hash: string + file_path?: string | null + profile?: string | null +} +/** ``tools/checkpoint_manager.py::restore`` outcome; ``history_removed`` is added for a full (non-file) restore that also rewound the live transcript. */ +export interface RollbackRestoreResult { + success: boolean + restored_to?: string | null + reason?: string | null + directory?: string | null + file?: string | null + restored_files?: string[] | null + skipped_user_edits?: string[] | null + skipped_oversize?: string[] | null + failed_deletes?: string[] | null + history_removed?: number | null + error?: string | null + debug?: unknown | null + [key: string]: unknown +} +export interface RollbackDiffParams { + session_id: string + hash: string + profile?: string | null +} +export interface RollbackDiffResult { + stat?: string + diff?: string + rendered?: string | null +} +export interface CronManageParams { + action?: CronAction + name?: string | null + include_disabled?: boolean | string | null + schedule?: string | null + prompt?: string | null + repeat?: number | string | null + continuity?: boolean | string | null + deliver?: string | null + profile?: string | null +} +export type CronAction = 'list' | 'add' | 'remove' | 'pause' | 'resume' +/** Pass-through of ``tools/cronjob_tools.py::cronjob`` JSON: ``list`` → ``jobs``/``count`` (+ ``scoped`` when profile-scoped); ``add`` → the created job's summary + ``job``; ``remove`` → ``removed_job``; ``pause``/``resume`` → ``job``. A tool-level failure lands in ``error``. */ +export interface CronManageResult { + success?: boolean | null + error?: string | null + count?: number | null + jobs?: CronJobRow[] | null + scoped?: string | null + gateway_running?: boolean | null + warning?: string | null + job_id?: string | null + name?: string | null + skill?: string | null + skills?: string[] | null + schedule?: string | null + repeat?: number | string | null + deliver?: string | null + next_run_at?: string | null + job?: CronJobRow | null + message?: string | null + guidance?: unknown | null + removed_job?: CronRemovedJob | null + [key: string]: unknown +} +/** ``tools/cronjob_job_args.py::_format_job``. */ +export interface CronJobRow { + job_id: string + name?: string + skill?: string | null + skills?: string[] + prompt_preview?: string + model?: string | null + provider?: string | null + base_url?: string | null + schedule?: string + repeat?: number | string | null + deliver?: string | null + next_run_at?: string | null + last_run_at?: string | null + last_status?: string | null + last_delivery_error?: string | null + last_delivery_unverified?: boolean | null + last_fire_error?: string | null + last_error?: string | null + enabled?: boolean + state?: string | null + paused_at?: string | null + paused_reason?: string | null + workdir?: string | null + script?: string | null + reasoning_effort?: string | null + monitor_script?: string | null + monitor_url?: string | null + monitor_state?: unknown | null + no_agent?: boolean | null + enabled_toolsets?: string[] | null + continuity?: boolean | null + context_from?: string[] | null + attach_to_session?: boolean | null + [key: string]: unknown +} +export interface CronRemovedJob { + id: string + name?: string + schedule?: string | null +} +export interface BrowserManageParams { + action?: BrowserAction + url?: string | null + session_id?: string | null + profile?: string | null +} +export type BrowserAction = 'status' | 'connect' | 'disconnect' +export interface BrowserManageResult { + connected: boolean + url?: string | null + messages?: string[] | null +} +/** Handlers that look a live session up with ``_sessions.get(params.get("session_id"))``: an absent / unknown id falls back to the launch profile's config, so it is never required. */ +export interface _SessionScoped { + session_id?: string | null +} +export interface ToolsetsListResult { + toolsets: ToolsetRow[] +} +/** One row of ``methods_tools._toolset_rows``; ``tools`` only when the caller asked for them (``tools.list``). */ +export interface ToolsetRow { + name: string + description: string + tool_count: number + enabled: boolean + tools?: string[] | null +} +export interface ToolsShowResult { + sections: ToolShowSection[] + total: number +} +export interface ToolShowSection { + name: string + tools: ToolShowRow[] +} +export interface ToolShowRow { + name: string + description: string +} +/** ``names`` are toolset keys or ``server:tool`` MCP targets; with ``session_id`` the live session's profile is authoritative and its agent is rebuilt. */ +export interface ToolsConfigureParams { + action: ToolsAction + names: string[] + session_id?: string | null + profile?: string | null +} +export type ToolsAction = 'enable' | 'disable' +export interface ToolsConfigureResult { + changed: string[] + enabled_toolsets: string[] + info?: SessionLiveInfo | null + missing_servers: string[] + reset: boolean + unknown: string[] +} +export type ReloadEnvParams = Record +export interface ReloadEnvResult { + updated: number +} +/** Without ``confirm`` the handler may answer ``confirm_required`` (per ``approvals.mcp_reload_confirm``); ``always`` persists the opt-out; ``rev`` is the config revision the caller wants loaded (coalescing). */ +export interface ReloadMcpParams { + session_id?: string | null + confirm?: boolean + always?: boolean + rev?: string | null +} +export interface ReloadMcpResult { + status: ReloadMcpStatus + message?: string | null + loaded_rev?: string | null + coalesced?: boolean | null + turn_isolation?: boolean | null + host_ack?: unknown | null +} +export type ReloadMcpStatus = 'confirm_required' | 'reloaded' +/** ``query`` is the search text / hub identifier / browse page (digits); ``page`` / ``page_size`` apply to ``browse``. */ +export interface SkillsManageParams { + profile?: string | null + action?: SkillsAction + query?: string | null + page?: number | null + page_size?: number | null +} +export type SkillsAction = 'list' | 'search' | 'install' | 'browse' | 'inspect' +/** Shape follows the action: ``list`` → ``skills`` (category → names); ``search`` → ``results``; ``install`` → ``installed`` + ``name``; ``browse`` → ``items`` + paging; ``inspect`` → ``info``. */ +export interface SkillsManageResult { + skills?: Record | null + results?: SkillHubHit[] | null + installed?: boolean | null + name?: string | null + items?: SkillBrowseItem[] | null + page?: number | null + total_pages?: number | null + total?: number | null + info?: SkillInspectInfo | null +} +export interface SkillHubHit { + name: string + description: string +} +/** ``hermes_cli.skills_hub.browse_skills`` row. */ +export interface SkillBrowseItem { + name?: string + description?: string + source?: string + trust?: string | null + identifier?: string | null + [key: string]: unknown +} +/** ``hermes_cli.skills_hub.inspect_skill``; ``{}`` when the identifier resolves nowhere. */ +export interface SkillInspectInfo { + name?: string | null + description?: string | null + source?: string | null + identifier?: string | null + tags?: string[] | null + skill_md_preview?: string | null + [key: string]: unknown +} +export type SkillsReloadParams = Record +export interface SkillsReloadResult { + output: string + result: SkillsReloadDiff +} +/** ``agent.skill_commands.reload_skills``. */ +export interface SkillsReloadDiff { + added?: SkillCommandRef[] + removed?: SkillCommandRef[] + unchanged?: string[] + total?: number + commands?: number + [key: string]: unknown +} +export interface SkillCommandRef { + name: string + description?: string +} +export interface LearningFramesParams { + cols?: number | null + rows?: number | null + frames?: number | null +} +export interface LearningFramesResult { + frames: LearningFrame[] + legend: LearningLegendItem[] + categories: LearningLegendItem[] + buckets: LearningBucketRow[] + summary: string[] + axis: LearningAxis + count: number + cols: number + rows: number +} +/** ``agent.learning_graph_render.render_graph`` projection; ``grid`` rows are lists of ``[text, styleKey, alpha?, hexOverride?]`` runs. */ +export interface LearningFrame { + reveal: number + date: string + visible: number + grid: unknown[][] + labels?: Record[] +} +export interface LearningLegendItem { + glyph: string + label: string + style?: string | null + color?: string | null +} +export interface LearningBucketRow { + index: number + label: string + date: string + skills: number + memories: number + total: number + category?: string | null + color?: string | null + nodes: LearningNodeRow[] +} +export interface LearningNodeRow { + id: string + glyph: string + label: string + fullLabel: string + meta: string + body: string + style: string +} +export interface LearningAxis { + start: string + end: string +} +export interface LearningNodeParams { + id?: string | null +} +export interface LearningDetailResult { + ok: boolean + message?: string | null + kind?: string | null + id?: string | null + label?: string | null + content?: string | null +} +/** ``agent.learning_mutations`` — ``ok: false`` carries the reason in ``message``. */ +export interface LearningMutationResult { + ok: boolean + message?: string | null +} +export interface LearningEditParams { + id?: string | null + content?: string | null +} +export interface McpCatalogResult { + servers: McpCatalogEntry[] +} +export interface McpCatalogEntry { + name: string + description: string + installed: boolean + enabled: boolean + requires: string[] + transport: string +} +export interface McpServersListResult { + servers: McpServerSummary[] +} +/** ``tui_gateway/mcp_rpc_helpers.summarize_server`` — a server's config without secret values. */ +export interface McpServerSummary { + name: string + transport: string + url?: string | null + command?: string | null + args: string[] + env: string[] + auth?: string | null + oauth_tokens_present?: boolean | null + enabled: boolean + tools?: unknown | null +} +export interface McpServersStatusResult { + servers: McpServerRuntimeRow[] + checked_at: number +} +/** Safe projection of ``tools.mcp_tool_discovery.get_mcp_status`` rows. */ +export interface McpServerRuntimeRow { + name: string + transport: string + tools: number + connected: boolean + disabled: boolean + status: McpRuntimeStatus +} +export type McpRuntimeStatus = 'connected' | 'disabled' | 'connecting' | 'failed' | 'configured' +/** ``preset`` (catalog id) and/or ``config`` (url/command/args/env/headers/auth/tools); a ``bearer_token`` is written to the profile's .env, only the header template persists. */ +export interface McpServersAddParams { + profile?: string | null + name: string + preset?: string | null + config?: Record | null + bearer_token?: string | null +} +export interface McpServersAddResult { + ok: boolean + name: string + server: McpServerSummary +} +export interface McpServersSetApiKeyParams { + profile?: string | null + name: string + value: string + env_var?: string | null +} +export interface McpServersSetApiKeyResult { + ok: boolean + name: string + env_var: string + server: McpServerSummary +} +export interface McpServerNameParams { + profile?: string | null + name: string +} +/** ``ok: false`` carries ``error``; ``prompts`` / ``resources`` are only counted on success. */ +export interface McpServersTestResult { + ok: boolean + tools: McpProbeTool[] + error?: string | null + prompts?: number | null + resources?: number | null + oauth_needed: boolean + oauth_tokens_present?: boolean | null +} +export interface McpProbeTool { + name: string + description: string +} +export interface McpServersRemoveResult { + ok: boolean + removed: boolean +} +/** With ``client_redirect_uri`` the CLIENT hosts the loopback and relays the code via ``mcp.servers.oauth.callback``. */ +export interface McpOauthStartParams { + profile?: string | null + name: string + client_redirect_uri?: string | null +} +export interface McpOauthStartResult { + ok: boolean + session_id: string + auth_url: string + flow: string +} +/** ``session_id`` is the OAuth flow id returned by ``oauth.start`` (not a gateway session). */ +export interface McpOauthFlowParams { + profile?: string | null + name: string + session_id: string +} +export interface McpOauthPollResult { + ok: boolean + status: McpOauthPollStatus + session_id?: string | null + error_message?: string | null + auth_url?: string | null + tools?: McpProbeTool[] | null +} +export type McpOauthPollStatus = 'pending' | 'approved' | 'error' +export interface McpOauthCancelResult { + ok: boolean + status?: string | null + error_message?: string | null +} +export interface McpOauthCallbackParams { + profile?: string | null + name: string + session_id: string + code?: string | null + state?: string | null + error?: string | null +} +export interface McpOauthCallbackResult { + ok: boolean + session_id?: string | null + error_message?: string | null +} +export type PluginsListParams = Record +export interface PluginsListResult { + plugins: LegacyPluginRow[] +} +export interface LegacyPluginRow { + name: string + version: string + enabled: boolean +} +/** ``toggle``: ``key``/``name`` + ``enable``; ``install``: ``identifier``/``repo`` or ``catalog_name`` (+ ``force``, ``enable``, ``ref``); ``update``: ``name``. */ +export interface PluginsManageParams { + profile?: string | null + action?: PluginsAction + key?: string | null + name?: string | null + enable?: boolean | null + identifier?: string | null + repo?: string | null + catalog_name?: string | null + force?: boolean | null + ref?: string | null +} +export type PluginsAction = 'list' | 'toggle' | 'install' | 'update' +/** ``list`` → ``plugins`` + counts; ``toggle`` → ``ok``/``unchanged``/``name``/``plugin``; ``install`` → ``hermes_cli.plugins_cmd.dashboard_install_plugin``'s ok payload; ``update`` → ``ok``/``unchanged``/``sha``. */ +export interface PluginsManageResult { + plugins?: AgentPluginRow[] | null + user_count?: number | null + bundled_count?: number | null + ok?: boolean | null + unchanged?: boolean | null + name?: string | null + plugin?: AgentPluginRow | null + plugin_name?: string | null + warnings?: string[] | null + missing_env?: string[] | null + after_install_path?: string | null + enabled?: boolean | null + sha?: string | null +} +/** ``methods_tools._plugin_rows`` + ``plugins_cmd_catalog.catalog_row_fields`` provenance. */ +export interface AgentPluginRow { + name: string + key: string + version: string + description: string + source: string + status: string + portable: boolean + install_dir: string + has_desktop_half: boolean + catalog_name?: string | null + catalog_tier?: string | null + installed_sha?: string | null + catalog_sha?: string | null + update_available?: boolean | null + pinned_sha?: string | null +} +/** Single question: ``question`` / ``choices`` (/ ``multi_select``); batch: ``questions``. ``answers`` rides only on a reconnect replay (locks the server already accepted). */ +export interface ClarifyRequestParams { + session_id: string + question?: string | null + choices?: string[] | null + multi_select?: boolean | null + questions?: ClarifyQuestion[] | null + answers?: Record | null +} +export interface ClarifyQuestion { + qid: string + question: string + choices?: string[] | null + multi_select?: boolean +} +/** Single: ``{answer}`` ('' = skip). Batch: ``{answers}`` for the whole set (early locks go through the ``clarify.lock`` RPC); a response with neither is cancel-all. */ +export interface ClarifyResult { + answer?: string | null + answers?: Record | null +} +/** ``tui_gateway/server.py::_approval_request_payload`` — the command is redacted server-side. */ +export interface ApprovalRequestParams { + session_id: string + request_id: string + command?: string + description?: string + choices?: tui_gateway_contracts_server_requests_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 type tui_gateway_contracts_server_requests_ApprovalChoice = 'once' | 'session' | 'always' | 'deny' +export interface ApprovalResult { + choice: tui_gateway_contracts_server_requests_ApprovalChoice + all?: boolean | null +} +export interface EmptyRequestParams { + session_id: string +} +/** The answer to any one-string prompt (sudo, secret, vault prompts, desktop bridges, mcp.setup): ``''`` means skipped / declined. */ +export interface ValueResult { + value: string +} +export interface SecretRequestParams { + session_id: string + env_var: string + prompt: string + metadata?: Record | null +} +export interface VaultUnlockRequestParams { + session_id: string + backend: string + display_name: string +} +export interface VaultSaveLoginRequestParams { + session_id: string + origin: string + site: string +} +export interface VaultCodeRequestParams { + session_id: string + site?: string | null + hint?: string | null +} +export interface McpSetupRequestParams { + session_id: string + server?: string | null + action?: string | null + reason?: string | null +} +export interface ReadRangeRequestParams { + session_id: string + start?: number | null + count?: number | null +} +/** ``tools/drive_preview_tool.py`` and ``tools/annotate_preview_tool.py`` field sets. */ +export interface PreviewActRequestParams { + session_id: string + action: string + ref?: string | null + selector?: string | null + text?: string | null + key?: string | null + submit?: boolean | null + full?: boolean | null + to?: string | null + amount?: number | null + max?: number | null +} +/** ``tools/tour_tool.py`` field set. */ +export interface TourRequestParams { + session_id: string + action: string + surface?: string | null + selector?: string | null + title?: string | null + text?: string | null + side?: string | null + steps?: TourStep[] | null + step_index?: number | null +} +export interface TourStep { + selector?: string | null + title?: string | null + text?: string | null + side?: string | null + [key: string]: unknown +} +/** ``tui_gateway/entry.py`` (stdio) / ``tui_gateway/ws.py`` (WebSocket) first frame. */ +export interface GatewayReadyPayload { + skin: SkinPayload + change_events: boolean + replay_epoch: string + heartbeat?: boolean | null +} +/** ``tui_gateway/change_watcher.py::resolve_skin`` — the resolved active skin (``HermesSkin``). ``{}`` when the skin engine failed to load. Colour maps are token → colour string. */ +export interface SkinPayload { + name?: string | null + colors?: Record | null + light_colors?: Record | null + dark_colors?: Record | null + branding?: Record | null + banner_logo?: string | null + banner_hero?: string | null + tool_prefix?: string | null + help_header?: string | null + [key: string]: unknown +} +/** ``hermes_cli/free_tier_bootstrap.py::SetupRecord.as_payload``. */ +export interface SetupReadyPayload { + provider_configured: boolean + inference_provider: string + free_tier: boolean + has_identity: boolean + other_providers: boolean + error?: string + finished_at: number + [key: string]: unknown +} +/** Every ``_emit("error", …)`` site sets exactly ``message``. */ +export interface ErrorPayload { + message: string +} +/** ``tui_gateway/model_switch.py`` capability-refresh notice. */ +export interface NoticePayload { + message: string +} +/** ``prompt_turn._invoke_agent._stream`` (message.delta: ``text`` + optional ``rendered``), ``agent_callbacks._agent_cbs`` (reasoning.delta / thinking.delta), ``tool_progress._progress_reasoning`` (reasoning.available). ``verbose`` rides only when the session's verbose reasoning mode is on. */ +export interface StreamDeltaPayload { + text: string + rendered?: string | null + verbose?: boolean | null +} +/** ``prompt_turn._interim_assistant_cb`` / ``agent_callbacks`` interim_assistant_callback. */ +export interface MessageInterimPayload { + text: string + already_streamed: boolean +} +/** ``prompt_turn._complete_turn_payload`` / ``session_auto_continue._emit_terminal_turn_error`` / ``agent_callbacks._mirror_subagent_to_child`` (child watch mirror: ``text`` only) / ``compute_host_bridge`` (``text`` + ``status``). */ +export interface MessageCompletePayload { + text?: string | unknown + usage?: Usage | null + status?: TurnStatus | null + reasoning?: string | null + warning?: string | null + response_previewed?: boolean | null + billing?: BillingBlock | null + failure_reason?: string | null + rendered?: string | null + error?: string | null + recoverable?: boolean | null + error_surface?: ErrorSurface | null + partial?: boolean | null +} +/** ``prompt_turn._result_status``. */ +export type TurnStatus = 'complete' | 'error' | 'interrupted' +/** ``agent/billing_links.py::BillingBlock.to_dict`` (+ ``unverified`` from conversation_loop). */ +export interface BillingBlock { + provider: string + provider_label: string + model: string + billing_url?: string | null + is_nous: boolean + message: string + unverified?: boolean | null +} +/** ``agent/error_surface.py::_surface`` — advisory {layer, code, retryable} (+ identity, + auth hint). */ +export interface ErrorSurface { + layer: string + code: string + retryable: boolean + provider?: string | null + model?: string | null + [key: string]: unknown +} +/** ``server._status_update`` and the direct emitters (goal / loop / heartbeat / process). */ +export interface StatusUpdatePayload { + kind: string + text: string +} +/** ``server._start_usage_ticker``. */ +export interface SessionUsagePayload { + usage: Usage +} +/** ``prompt_turn._invoke_agent`` ``_on_session_title`` hook. */ +export interface SessionTitlePayload { + session_id: string + title: string +} +/** ``agent_callbacks`` reaction_callback. */ +export interface ReactionPayload { + kind: string +} +/** ``server`` background_review_callback. */ +export interface ReviewSummaryPayload { + text: string +} +/** ``tool_progress._on_tool_start`` (+ ``agent_callbacks._mirror_subagent_to_child`` rows with ``preview`` and empty ``args``). ``todos``/``revision`` are NOT set by the emitter; kept optional because tool.start rows may pass through connector redaction unchanged. */ +export interface ToolStartPayload { + tool_id: string + name: string + context?: string | null + args?: Record | null + args_text?: string | null + preview?: string | null +} +/** ``tool_progress._on_tool_complete``; ``todos``/``revision`` merged in for the todo tools. */ +export interface ToolCompletePayload { + tool_id: string + name: string + args: Record + duration_s?: number | null + result?: unknown + summary?: string | null + result_text?: string | null + inline_diff?: string | null + todos?: unknown[] | null + revision?: number | null +} +/** ``agent_callbacks`` tool_gen_callback. */ +export interface ToolGeneratingPayload { + name: string +} +/** ``tool_progress._progress_output_risk``. */ +export interface ToolOutputRiskPayload { + tool_id: string + name: string + risk: string + findings: string[] + redacted: boolean +} +/** ``tool_progress._normalize_todo_state`` — full task snapshot. */ +export interface TodoUpdatedPayload { + todos: unknown[] + revision: number +} +/** ``agent/credits_tracker.py::AgentNotice`` via notice_callback, and ``server._await_agent_ready``'s slow-build notice. ``level``: info | warn | error | success; ``kind``: sticky | ttl | agent. */ +export interface NotificationShowPayload { + text: string + level: string + kind: string + ttl_ms?: number | null + key?: string | null + id?: string | null +} +export interface NotificationClearPayload { + key: string +} +/** ``tools/tip_tool.py``. */ +export interface TipShowPayload { + selector: string + text: string + title?: string | null + side?: string | null +} +/** ``server._hydrate_resume_history``. */ +export interface SessionResumeProgressPayload { + phase: string + status: ResumePhaseStatus + message_count?: number | null + message?: string | null +} +export type ResumePhaseStatus = 'loading' | 'complete' | 'failed' +/** ``session_lifecycle._announce_session_reclaimed`` (broadcast). */ +export interface SessionReclaimedPayload { + session_id: string + stored_session_id: string + reason: string +} +export interface SessionControlUpdatePayload { + control: tui_gateway_contracts_events_SessionControlSnapshot +} +/** ``methods_session_control._snapshot_control``; goal / loop / heartbeat sub-objects are the allow-listed state-file projections (owned by hermes_cli.goals / loops / heartbeat). */ +export interface tui_gateway_contracts_events_SessionControlSnapshot { + goal?: Record | null + loop?: Record | null + heartbeat?: Record | null + revision?: string + updated_at?: number + [key: string]: unknown +} +/** ``methods_session`` billing.step_up on_verification. */ +export interface BillingStepUpVerificationPayload { + verification_url: string + user_code: string +} +/** ``methods_prompt._spawn_side_agent``: ``{task_id, **extra, text}``; btw adds ``question``. */ +export interface SideAgentCompletePayload { + task_id: string + text: string + question?: string | null +} +/** ``methods_prompt`` restart body + ``agent_callbacks._preview_restart_callbacks``. */ +export interface PreviewRestartProgressPayload { + task_id: string + text: string + level?: string | null +} +/** ``tool_progress._progress_subagent`` — every ``subagent.*`` frame; identity fields are optional because older emitters omit them and the TUI spawn tree falls back to flat rendering. */ +export interface SubagentEventPayload { + goal: string + task_count: number + task_index: number + subagent_id?: string | null + parent_id?: string | null + child_session_id?: string | null + delegation_id?: string | null + depth?: number | null + model?: string | null + tool_count?: number | null + toolsets?: string[] | null + input_tokens?: number | null + output_tokens?: number | null + reasoning_tokens?: number | null + api_calls?: number | null + files_read?: string[] | null + files_written?: string[] | null + output_tail?: SubagentOutputTailEntry[] | null + tool_name?: string | null + text?: string | null + status?: SubagentStatus | null + summary?: string | null + duration_seconds?: number | null + tool_preview?: string | null +} +/** ``tools/delegate_tool_results.py::_extract_output_tail`` row. */ +export interface SubagentOutputTailEntry { + tool: string + preview: string + is_error: boolean +} +/** ``tool_progress._progress_moa_reference``. */ +export interface MoaReferencePayload { + label: string + text: string + index?: number | null + count?: number | null +} +export interface MoaAggregatingPayload { + aggregator: string +} +export interface MoaProgressPayload { + label: string + refs_done: number + refs_total: number +} +export interface MoaPhasePayload { + phase: string + refs_done?: number | null + refs_total?: number | null + aggregator?: string | null +} +/** ``tools/open_preview_tool.py``. */ +export interface PreviewOpenPayload { + url: string + label?: string +} +/** ``tools/preview_tool.py`` / ``tools/close_preview_tool.py``; ``url`` '' closes every tab. */ +export interface PreviewClosePayload { + url?: string +} +/** ``tools/apply_layout_tool.py``. */ +export interface LayoutApplyPayload { + preset: string + [key: string]: unknown +} +/** ``tools/focus_pane_tool.py``. */ +export interface PaneRevealPayload { + pane: string + [key: string]: unknown +} +/** ``tools/react_to_message_tool.py``. */ +export interface MessageReactionPayload { + row_id: number + reactions: tui_gateway_contracts_events_MessageReaction[] + role: string +} +/** ``hermes_state_messages.set_message_reaction`` row. */ +export interface tui_gateway_contracts_events_MessageReaction { + emoji: string + author: string + at?: number | null + [key: string]: unknown +} +/** ``session_notifications`` process_registry.on_output. */ +export interface TerminalOutputPayload { + process_id: string + chunk: string +} +export interface TerminalClosePayload { + process_id: string +} +/** ``methods_browser`` announce(); ``level``: info | warn | error. */ +export interface BrowserProgressPayload { + message: string + level: string +} +/** ``gateway/browser_control_broker.py`` FRAME_COMMAND params. */ +export interface BrowserControllerCommandPayload { + command_id: string + action: string + arguments: Record + controller_id?: string | null + browser_profile_id?: string | null + tool_call_id?: string | null +} +/** ``gateway/browser_control_broker.py::_cancel_frame``. */ +export interface BrowserControllerCancelPayload { + command_id: string + tool_call_id?: string | null +} +/** ``methods_voice._vr_on_status``; states come from the recorder (idle / listening / transcribing …). */ +export interface VoiceStatusPayload { + state: string +} +/** ``methods_voice._vr_transcript`` / ``_deliver_fd_transcript`` / typed stop phrase in methods_prompt. */ +export interface VoiceTranscriptPayload { + text?: string | null + stop_phrase?: boolean | null + typed?: boolean | null + no_speech_limit?: boolean | null +} +/** ``methods_voice`` wake detector ``_on_detect``. */ +export interface WakeDetectedPayload { + phrase: string + profile?: string | null + start_new_session: boolean +} +/** ``change_watcher._pet_changed_payload`` — ``pet.info.meta``-shaped; ``{enabled: false}`` when off. */ +export interface PetChangedPayload { + enabled: boolean + slug?: string | null + displayName?: string | null + scale?: number | null + spritesheetRevision?: string | null + [key: string]: unknown +} +/** ``methods_session`` pet.generate: token-only init frame, then one per draft. */ +export interface PetGenerateProgressPayload { + token: string + count: number + index?: number | null + dataUri?: string | null + [key: string]: unknown +} +/** ``methods_session`` pet.hatch ``_on_progress``: ``{event, detail}`` or the parsed row form. */ +export interface PetHatchProgressPayload { + event: string + detail?: string | null + state?: string | null + done?: string | null + total?: string | null + [key: string]: unknown +} +/** ``change_watcher._CHANGE_WATCHES`` payload fn — ``{}`` for every watch except pet.changed. */ +export type ChangeSignalPayload = Record +export interface RequestCancelPayload { + id: string + method: string + reason: string +} + +// ── Client→server methods ── +export interface RpcMethods { + /** Registry-wide background process summary for ``/agents``. */ + 'agents.list': { params: AgentsListParams; result: AgentsListResult } + /** Replay the approvals still waiting on this session (reconnect / polling). */ + 'approval.pending': { params: ApprovalPendingParams; result: ApprovalPendingResult } + /** Tell the backend the card is on screen, so its timeout clock starts. */ + 'approval.received': { params: ApprovalReceivedParams; result: ApprovalReceivedResult } + /** Deliver the user's decision on a dangerous command (falls back to durable identity on a stale sid). */ + 'approval.respond': { params: ApprovalRespondParams; result: ApprovalRespondResult } + /** Enable/disable auto top-up with its threshold and reload amount (billing:manage). */ + 'billing.auto_reload': { params: BillingAutoReloadParams; result: BillingMutationResult } + /** Start a one-off top-up charge (billing:manage, idempotent). */ + 'billing.charge': { params: BillingChargeParams; result: BillingChargeResult } + /** Poll one charge by id. */ + 'billing.charge_status': { params: BillingChargeStatusParams; result: BillingChargeStatusResult } + /** Read-only billing view (no scope); the Nous free tier is answered locally without a portal call. */ + 'billing.state': { params: ProfileParams; result: BillingStateResult } + /** Run the billing:manage device flow; the URL/code arrive via billing.step_up.verification. */ + 'billing.step_up': { params: BillingStepUpParams; result: BillingStepUpResult } + /** Deliver a relayed DM into a Bot Chat on this gateway and return the one-turn reply (blocking). */ + 'bot_relay.deliver': { params: BotRelayDeliverParams; result: BotRelayDeliverResult } + /** Atomically claim every pending cross-connection envelope queued on this gateway. */ + 'bot_relay.outbox.drain': { params: BotRelayOutboxDrainParams; result: BotRelayOutboxDrainResult } + /** Write a relayed reply and/or typed error for an envelope so the sender-side waiter resolves. */ + 'bot_relay.reply': { params: BotRelayReplyParams; result: OkResult } + /** Replace this gateway's view of agents on other connections; answers the accepted row count. */ + 'bot_relay.roster.sync': { params: BotRelayRosterSyncParams; result: BotRelayRosterSyncResult } + /** Hard-detach only the controller owned by this authenticated transport. */ + 'browser.controller.detach': { params: BrowserControllerParams; result: BrowserControllerDetachResult } + /** Acknowledge a heartbeat only for this transport's own attached controller. */ + 'browser.controller.heartbeat': { params: BrowserControllerParams; result: OkResult } + /** Attach this connection as the browser controller for one session; fails closed (4403). */ + 'browser.controller.register': { params: BrowserControllerRegisterParams; result: BrowserControllerRegisterResult } + /** Deliver one command result to the broker; accepted is false for unknown or settled command ids. */ + 'browser.controller.result': { params: BrowserControllerResultParams; result: BrowserControllerResultResult } + /** Inspect, attach to, or drop the CDP browser the tools use; ``messages`` narrate a connect. */ + 'browser.manage': { params: BrowserManageParams; result: BrowserManageResult } + /** Lock one answer of a batch clarify request (editable until every question is locked). */ + 'clarify.lock': { params: ClarifyLockParams; result: ClarifyLockResult } + /** Run ``hermes `` non-interactively and capture its output; ``blocked`` explains a refusal. */ + 'cli.exec': { params: CliExecParams; result: CliExecResult } + /** Save the host clipboard image into the session and queue it for the next turn. */ + 'clipboard.paste': { params: ClipboardPasteParams; result: AttachedImageResult } + /** Run a quick/plugin/bundle/skill/built-in slash command and answer a structured directive. */ + 'command.dispatch': { params: CommandDispatchParams; result: CommandDispatchResult } + /** Canonical registry command for a name or alias. */ + 'command.resolve': { params: CommandResolveParams; result: CommandResolveResult } + /** Categorized slash metadata (registry, quick, plugin, skill) for completion menus. */ + 'commands.catalog': { params: CommandsCatalogParams; result: CommandsCatalogResult } + /** Path / @-reference completions for the composer (files, folders, profiles, plugin providers). */ + 'complete.path': { params: CompletePathParams; result: CompletionItemsResult } + /** Ranked slash-command / skill completions for a ``/`` token. */ + 'complete.slash': { params: CompleteSlashParams; result: CompleteSlashResult } + /** Read one normalised config value (or the whole effective config) the way the UIs render it. */ + 'config.get': { params: ConfigGetParams; result: ConfigGetResult } + /** Change one config key (persisted or session-scoped) and read back the normalised value. */ + 'config.set': { params: ConfigSetParams; result: ConfigSetResult } + /** Masked, display-ready config summary (model / agent / environment rows). */ + 'config.show': { params: ConfigShowParams; result: ConfigShowResult } + /** Start (or re-initiate) authorization for named connectors; returns per-connector links/status. */ + 'connectors.connect': { params: ConnectorsConnectParams; result: ConnectorsConnectResult } + /** Connector catalog + connection state for one owned session (``available=False`` when the toolset is off). */ + 'connectors.list': { params: ConnectorsListParams; result: ConnectorsListResult } + /** List/add/remove/pause/resume cron jobs in the (optionally profile-scoped) cron store. */ + 'cron.manage': { params: CronManageParams; result: CronManageResult } + /** Block/unblock NEW spawns globally (active children keep running); returns the new state. */ + 'delegation.pause': { params: DelegationPauseParams; result: DelegationPauseResult } + /** Running subagent tree plus the spawn pause flag and limits. */ + 'delegation.status': { params: ProfileParams; result: DelegationStatusResult } + /** Upload a force-redacted debug bundle to Nous-internal diagnostics storage. */ + 'diagnostics.share_nous': { params: DiagnosticsShareNousParams; result: DiagnosticsShareNousResult } + /** Stage a non-image file into the session workspace and hand back its @file: ref. */ + 'file.attach': { params: FileAttachParams; result: FileAttachResult } + /** Mark the one-time availability notice as shown on the free-tier identity. */ + 'free_tier.ack_notice': { params: ProfileParams; result: FreeTierAckNoticeResult } + /** Explicit retry of the free-tier identity mint when the boot bootstrap could not create it. */ + 'free_tier.provision': { params: ProfileParams; result: FreeTierProvisionResult } + /** Pure read of the focused profile's free-tier identity state (no network, no side effects). */ + 'free_tier.status': { params: ProfileParams; result: FreeTierStatusResult } + /** What THIS build enforces (a client withholds a feature unless advertised). */ + 'gateway.capabilities': { params: PingParams; result: GatewayCapabilitiesResult } + /** Resolve one exact pending approval raised by a local or peer room member. */ + 'groups.approve': { params: GroupsApproveParams; result: GroupsApproveResult } + /** Describe the hosted-room protocol implemented by this gateway. */ + 'groups.capabilities': { params: GroupsCapabilitiesParams; result: GroupsCapabilitiesResult } + /** Create a hosted room idempotently; authority is this gateway's stable install identity. */ + 'groups.create': { params: GroupsCreateParams; result: GroupsCreateResult } + /** Fence this gateway's stale room authority against a proven newer epoch. */ + 'groups.demote': { params: GroupsDemoteParams; result: GroupsDemoteResult } + /** Permanently tombstone a hosted room id after stopping its work and revoking peer routes. */ + 'groups.disband': { params: GroupsDisbandParams; result: GroupsDisbandResult } + /** List rooms hosted by this gateway, most recently changed first. */ + 'groups.list': { params: GroupsListParams; result: GroupsListResult } + /** A monotonic room-log delta after since_seq, bounded by count and page bytes. */ + 'groups.log': { params: GroupsLogParams; result: GroupsLogResult } + /** Mint one target-issued room/profile grant for a prospective room home. */ + 'groups.peer.invite': { params: GroupsPeerInviteParams; result: GroupsPeerInviteResult } + /** Register and probe one scoped peer route on the room home. */ + 'groups.peer.register': { params: GroupsPeerRegisterParams; result: GroupsPeerRegisterResult } + /** Revoke one target-issued grant using its exact profile scope. */ + 'groups.peer.revoke': { params: GroupsPeerRevokeParams; result: GroupsPeerRevokeResult } + /** Continue a replicated room on this gateway at epoch + 1; requires confirm=true. */ + 'groups.promote': { params: GroupsPromoteParams; result: GroupsPromoteResult } + /** Rename one hosted room atomically with its replay event. */ + 'groups.rename': { params: GroupsRenameParams; result: GroupsRenameResult } + /** The local replica's coverage and authority lineage for one room. */ + 'groups.replica_state': { params: GroupsReplicaStateParams; result: GroupsReplicaStateResult } + /** Persist one authority-stamped replay page into the local replica store; idempotent. */ + 'groups.replicate': { params: GroupsReplicateParams; result: GroupsReplicateResult } + /** Retry one indeterminate room task after explicit user confirmation. */ + 'groups.retry': { params: GroupsRetryParams; result: GroupsRetryResult } + /** Append one inert message.user event idempotently; the actor is server-owned. */ + 'groups.send': { params: GroupsSendParams; result: GroupsSendResult } + /** One hosted room's replay cursor and fenced authority state, plus live driver status. */ + 'groups.state': { params: GroupsStateParams; result: GroupsStateResult } + /** Durably cancel queued or running work for one hosted room. */ + 'groups.stop': { params: GroupsStopParams; result: GroupsStopResult } + /** Fail a not-yet-claimed handoff (client poll timeout); CAS against the watcher. */ + 'handoff.fail': { params: HandoffFailParams; result: HandoffFailResult } + /** Queue a handoff to a messaging platform's home channel; the gateway watcher claims it. */ + 'handoff.request': { params: HandoffRequestParams; result: HandoffRequestResult } + /** Poll the handoff row for this session. */ + 'handoff.state': { params: SessionParams; result: HandoffStateResult } + /** Queue a gateway-visible image file for the next turn. */ + 'image.attach': { params: ImageAttachParams; result: AttachedImageResult } + /** Queue an image uploaded as base64 (remote client); reply mirrors image.attach. */ + 'image.attach_bytes': { params: ImageAttachBytesParams; result: AttachedImageResult } + /** Drop a queued image before the turn is sent. */ + 'image.detach': { params: ImageDetachParams; result: ImageDetachResult } + /** Generate an image through the tool's provider dispatcher and hand the renderer a data URL. */ + 'image.generate': { params: ImageGenerateParams; result: ImageGenerateResult } + /** Recognise a terminal file drop pasted into the composer and turn it into an attachment. */ + 'input.detect_drop': { params: InputDetectDropParams; result: InputDetectDropResult } + /** Session/message counts over the last ``days`` for the (optionally scoped) profile store. */ + 'insights.get': { params: InsightsGetParams; result: InsightsGetResult } + /** Archive a skill (restorable via curator) or remove a memory chunk. */ + 'learning.delete': { params: LearningNodeParams; result: LearningMutationResult } + /** Node content (SKILL.md or memory chunk) for an edit prefill. */ + 'learning.detail': { params: LearningNodeParams; result: LearningDetailResult } + /** Rewrite a node's content (SKILL.md or memory chunk). */ + 'learning.edit': { params: LearningEditParams; result: LearningMutationResult } + /** Pre-render the /journey timeline (frames + legend/summary) so the TUI walks it locally. */ + 'learning.frames': { params: LearningFramesParams; result: LearningFramesResult } + /** Stateless one-shot LLM completion (titles, ideas) on the session's or the task backend. */ + 'llm.oneshot': { params: LlmOneshotParams; result: LlmOneshotResult } + /** Curated MCP presets with per-profile installed/enabled state and the env keys each needs. */ + 'mcp.catalog': { params: ProfileParams; result: McpCatalogResult } + /** Add a server to the profile's config from a catalog preset and/or an explicit config. */ + 'mcp.servers.add': { params: McpServersAddParams; result: McpServersAddResult } + /** Configured MCP servers for the (scoped) profile, secrets redacted to env-key names. */ + 'mcp.servers.list': { params: ProfileParams; result: McpServersListResult } + /** Relay a client-captured redirect into a client_redirect_uri flow. */ + 'mcp.servers.oauth.callback': { params: McpOauthCallbackParams; result: McpOauthCallbackResult } + /** Cancel a flow owned by the resolved profile, waking its callback worker. */ + 'mcp.servers.oauth.cancel': { params: McpOauthFlowParams; result: McpOauthCancelResult } + /** Poll a flow; approved persists tokens for the profile and returns the probed tools. */ + 'mcp.servers.oauth.poll': { params: McpOauthFlowParams; result: McpOauthPollResult } + /** Begin a PKCE OAuth flow; the client opens auth_url and polls mcp.servers.oauth.poll. */ + 'mcp.servers.oauth.start': { params: McpOauthStartParams; result: McpOauthStartResult } + /** Drop a server from the profile's config.yaml. */ + 'mcp.servers.remove': { params: McpServerNameParams; result: McpServersRemoveResult } + /** Store a credential in the profile's .env and reference it from the server config (header or env). */ + 'mcp.servers.set_api_key': { params: McpServersSetApiKeyParams; result: McpServersSetApiKeyResult } + /** Cached runtime state per configured server; never connects, probes, or starts auth. */ + 'mcp.servers.status': { params: ProfileParams; result: McpServersStatusResult } + /** Connect, list tools, disconnect — an OAuth server with no token on disk is reported as not ok. */ + 'mcp.servers.test': { params: McpServerNameParams; result: McpServersTestResult } + /** Set/clear one author's emoji reaction on a message; returns the row's full reaction list. */ + 'message.react': { params: MessageReactParams; result: MessageReactResult } + /** Remove every credential (env keys and OAuth state) for a provider. */ + 'model.disconnect': { params: ModelDisconnectParams; result: ModelDisconnectResult } + /** Provider/model inventory for the picker, layered over the session's live provider when given. */ + 'model.options': { params: ModelOptionsParams; result: ModelOptionsResult } + /** Save an API key for a provider and return its refreshed inventory row. */ + 'model.save_key': { params: ModelSaveKeyParams; result: ModelSaveKeyResult } + /** Spill a large paste to a file and hand back the inline placeholder. */ + 'paste.collapse': { params: PasteCollapseParams; result: PasteCollapseResult } + /** Render a PDF's pages to PNG and queue them as images for the next turn. */ + 'pdf.attach': { params: PdfAttachParams; result: PdfAttachResult } + /** Stop an in-flight pet generate/hatch by token (idempotent). */ + 'pet.cancel': { params: PetCancelParams; result: PetCancelResult } + /** Half-block cell frames (or a kitty placement) for one pet state. */ + 'pet.cells': { params: PetCellsParams; result: PetCellsResult } + /** Turn the pet display off from the desktop picker. */ + 'pet.disable': { params: ProfileParams; result: OkResult } + /** Export an installed pet as a re-importable .zip. */ + 'pet.export': { params: PetSlugParams; result: PetExportResult } + /** Petdex gallery + local install state (installed-only offline); localOnly skips the remote manifest. */ + 'pet.gallery': { params: PetGalleryParams; result: PetGalleryResult } + /** Candidate base looks for a new pet (draft step); drafts also stream via pet.generate.progress. */ + 'pet.generate': { params: PetGenerateParams; result: PetGenerateResult } + /** Whether pet generation is possible (a reference-capable image backend) and which providers. */ + 'pet.generate.status': { params: ProfileParams; result: PetGenerateStatusResult } + /** Turn a base draft into a full spritesheet pet; progress streams via pet.hatch.progress. */ + 'pet.hatch': { params: PetHatchParams; result: PetHatchResult } + /** Active pet for sprite renderers: spritesheet (base64) + frame geometry + state-row taxonomy. */ + 'pet.info': { params: PetInfoParams; result: PetInfoResult } + /** Cheap active-pet metadata used to avoid full payload refreshes. */ + 'pet.info.meta': { params: ProfileParams; result: PetInfoMetaResult } + /** Uninstall a pet (delete its directory); if it was active, turn the display off. */ + 'pet.remove': { params: PetSlugParams; result: PetSlugResult } + /** Rename a pet's display name + realign its slug/dir; follows the active slug in config. */ + 'pet.rename': { params: PetRenameParams; result: PetSlugResult } + /** Persist display.pet.scale (clamped to engine bounds) from the desktop slider. */ + 'pet.scale': { params: PetScaleParams; result: PetScaleResult } + /** Adopt a pet: install (if needed) + activate; writes display.pet.* to config. */ + 'pet.select': { params: PetSlugParams; result: PetSlugResult } + /** Idle-frame PNG data URI for the picker (desktop CSP breaks CDN ). */ + 'pet.thumb': { params: PetThumbParams; result: PetThumbResult } + /** Cheapest liveness probe; answered on the WS reader thread even while every agent is mid-turn. */ + ping: { params: PingParams; result: PingResult } + /** Loaded plugin manager entries (legacy flat view); the Plugins Hub uses plugins.manage list. */ + 'plugins.list': { params: PluginsListParams; result: PluginsListResult } + /** Plugins Hub backend: list installed plugins, toggle, git-install or re-pin a catalog install. */ + 'plugins.manage': { params: PluginsManageParams; result: PluginsManageResult } + /** Spawn a hidden agent that brings the desktop preview's dev server back up. */ + 'preview.restart': { params: PreviewRestartParams; result: TaskIdResult } + /** Kill one background process the caller's session owns and return its output snapshot. */ + 'process.kill': { params: ProcessKillParams; result: ProcessKillResult } + /** Background processes owned by the caller's session (desktop status stack poll). */ + 'process.list': { params: ProcessListParams; result: ProcessListResult } + /** Kill every background process in the registry (``/stop``), answering the count killed. */ + 'process.stop': { params: ProcessStopParams; result: ProcessStopResult } + /** Editor Save: apply any subset of a profile's sections and report each one. */ + 'profiles.configure': { params: ProfilesConfigureParams; result: ProfilesConfigureResult } + /** Create a profile (ws twin of POST /api/profiles), mirroring launch credentials by default. */ + 'profiles.create': { params: ProfilesCreateParams; result: ProfilesCreateResult } + /** Everything the profile editor shows: soul, model pin, skills, toolsets, MCP servers. */ + 'profiles.describe': { params: ProfileNameParams; result: ProfilesDescribeResult } + /** A profile asset as a data URL. */ + 'profiles.get_asset': { params: ProfilesGetAssetParams; result: ProfilesGetAssetResult } + /** Roster of profiles with previews so a client paints without N follow-up calls. */ + 'profiles.list': { params: ProfilesListParams; result: ProfilesListResult } + /** Write the onboarding facts into the default profile's user memory and confirm they landed. */ + 'profiles.remember_onboarding': { params: ProfilesRememberOnboardingParams; result: ProfilesRememberOnboardingResult } + /** Store or clear a profile asset (avatar) atomically. */ + 'profiles.set_asset': { params: ProfilesSetAssetParams; result: ProfilesSetAssetResult } + /** Structured project facts for a cwd so UIs don't re-sniff the workspace. */ + 'project.facts': { params: ProjectFactsParams; result: ProjectFactsResult } + /** Attach a folder to a project (optionally as its primary path). */ + 'projects.add_folder': { params: ProjectsAddFolderParams; result: ProjectResult } + /** Archive (or with ``restore`` un-archive) a project; answers the full listing. */ + 'projects.archive': { params: ProjectsArchiveParams; result: ProjectsPayload } + /** Create a project from a name + folders; duplicate primary paths are refused (5063). */ + 'projects.create': { params: ProjectsCreateParams; result: OptionalProjectResult } + /** Delete a project and its folders; answers the full listing. */ + 'projects.delete': { params: ProjectIdParams; result: ProjectsPayload } + /** Repos for the desktop overview: scanned-from-disk (cached) ∪ session-derived. */ + 'projects.discover_repos': { params: ProjectsDiscoverReposParams; result: ProjectsDiscoverReposResult } + /** Which project (if any) owns a directory, plus the resolved cwd and its git branch. */ + 'projects.for_cwd': { params: ProjectsForCwdParams; result: ProjectsForCwdResult } + /** One stored project with its folders. */ + 'projects.get': { params: ProjectIdParams; result: ProjectResult } + /** Every project of the profile (archived included) plus which one is active. */ + 'projects.list': { params: ProfileParams; result: ProjectsPayload } + /** Fully hydrated lanes for one project, from the same grouping as projects.tree. */ + 'projects.project_sessions': { params: ProjectsProjectSessionsParams; result: ProjectsProjectSessionsResult } + /** Persist repo roots found by the client's (desktop-side) scan; return the merged list. */ + 'projects.record_repos': { params: ProjectsRecordReposParams; result: ProjectsRecordReposResult } + /** Detach a folder from a project. */ + 'projects.remove_folder': { params: ProjectFolderParams; result: ProjectResult } + /** Switch (or clear) the active project for the profile. */ + 'projects.set_active': { params: ProjectsSetActiveParams; result: ActiveIdResult } + /** Make one attached folder the project's primary path. */ + 'projects.set_primary': { params: ProjectFolderParams; result: ProjectResult } + /** Project → repo → lane overview with counts and a few preview sessions per project. */ + 'projects.tree': { params: ProjectsTreeParams; result: ProjectsTreeResult } + /** Patch a project's display fields; answers the refreshed project. */ + 'projects.update': { params: ProjectsUpdateParams; result: ProjectResult } + /** Run a task on a fresh agent in the background; the answer arrives as background.complete. */ + 'prompt.background': { params: SideAgentParams; result: TaskIdResult } + /** Side question over a snapshot of the live conversation; the answer arrives as btw.complete. */ + 'prompt.btw': { params: SideAgentParams; result: TaskIdResult } + /** Send a user turn to a live session; busy sessions queue / steer / redirect instead of refusing. */ + 'prompt.submit': { params: PromptSubmitParams; result: PromptSubmitResult } + /** Re-read ~/.hermes/.env (CLI /reload parity); built agents keep their pool until /new. */ + 'reload.env': { params: ReloadEnvParams; result: ReloadEnvResult } + /** Tear down and rediscover MCP servers for every live session (prompt cache is invalidated). */ + 'reload.mcp': { params: ReloadMcpParams; result: ReloadMcpResult } + /** Answer an open server→client request from a client that never received the frame. */ + 'request.answer': { params: RequestAnswerParams; result: RequestAnswerResult } + /** Diff between a checkpoint and the working tree, with an ANSI rendering sized to the TUI. */ + 'rollback.diff': { params: RollbackDiffParams; result: RollbackDiffResult } + /** Checkpoints for the session's cwd; ``enabled: false`` when checkpointing is off. */ + 'rollback.list': { params: RollbackListParams; result: RollbackListResult } + /** Restore the working tree (or one file) to a checkpoint by hash or 1-based index. */ + 'rollback.restore': { params: RollbackRestoreParams; result: RollbackRestoreResult } + /** Attach the frontend to a live session without closing the previously focused one. */ + 'session.activate': { params: SessionActivateParams; result: SessionActivateResult } + /** Live sessions in this process, insertion order (not a DB browser). */ + 'session.active_list': { params: SessionActiveListParams; result: SessionActiveListResult } + /** Fork a live session into a new stored child that shares the parent's history so far. */ + 'session.branch': { params: SessionBranchParams; result: SessionBranchResult } + /** Tear down a live session (its stored row stays resumable). */ + 'session.close': { params: SessionCloseParams; result: SessionCloseResult } + /** Manual /compress of an idle session, optionally focused on a topic. */ + 'session.compress': { params: SessionCompressParams; result: SessionCompressResult } + /** Cursor-style split of the context window by category. */ + 'session.context_breakdown': { params: SessionContextBreakdownParams; result: SessionContextBreakdownResult } + /** Run one allowlisted goal / loop / subgoal / heartbeat action and return the exact resulting snapshot. */ + 'session.control': { params: SessionControlParams; result: SessionControlResult } + /** Stable, allowlisted snapshot of one live session's goal / loop / heartbeat state. */ + 'session.control.read': { params: SessionControlReadParams; result: SessionControlReadResult } + /** Mint a live session (agent builds after the reply); a DB row appears on the first prompt unless seeded. */ + 'session.create': { params: SessionCreateParams; result: SessionCreateResult } + /** Change a live, idle session's working directory. */ + 'session.cwd.set': { params: SessionCwdSetParams; result: SessionCwdSetResult } + /** Delete a stored session + transcripts; refused while it is live here. */ + 'session.delete': { params: SessionDeleteParams; result: SessionDeleteResult } + /** Replay events after a seq watermark on WS reconnect; truncated means refetch state. */ + 'session.events.since': { params: SessionEventsSinceParams; result: SessionEventsSinceResult } + /** Replay-buffer occupancy telemetry (ops/debug). */ + 'session.events.stats': { params: SessionEventsStatsParams; result: SessionEventsStatsResult } + /** Import a foreign session into this profile's history (idempotent per origin). */ + 'session.foreign.import': { params: SessionForeignIdParams; result: SessionForeignImportResult } + /** One page of Claude Code / Codex sessions found on the serving backend. */ + 'session.foreign.list': { params: SessionForeignListParams; result: SessionForeignListResult } + /** Preview a foreign session's tail before importing it. */ + 'session.foreign.preview': { params: SessionForeignIdParams; result: SessionForeignPreviewResult } + /** The durable display transcript (ancestors included, row ids attached). */ + 'session.history': { params: SessionHistoryParams; result: SessionHistoryResult } + /** Stop the running turn (and streaming TTS); retires the crash-recovery marker. */ + 'session.interrupt': { params: SessionInterruptParams; result: SessionInterruptResult } + /** Human-facing stored sessions, most recent first (sub-agent / kanban sources denied). */ + 'session.list': { params: SessionListParams; result: SessionListResult } + /** Most recent human-facing session; errors fold into a null session_id. */ + 'session.most_recent': { params: SessionMostRecentParams; result: SessionMostRecentResult } + /** Redirect the active turn (queued for the next turn while the agent is still building). */ + 'session.redirect': { params: SessionCorrectionParams; result: SessionCorrectionResult } + /** Attach to a stored session: reuse it if live here, else lazy / deferred / cold / eager rebuild. */ + 'session.resume': { params: SessionResumeParams; result: SessionResumeResult } + /** Export the transcript to ~/.hermes/sessions/saved (classic /save). */ + 'session.save': { params: SessionSaveParams; result: SessionSaveResult } + /** Set/clear hidden (out of the default list, still resumable by its owner) on a session + lineage. */ + 'session.set_hidden': { params: SessionSetHiddenParams; result: SessionSetHiddenResult } + /** Rendered /status text for the session. */ + 'session.status': { params: SessionStatusParams; result: SessionStatusResult } + /** Inject text into the next tool result without interrupting the turn. */ + 'session.steer': { params: SessionCorrectionParams; result: SessionCorrectionResult } + /** Read or set a live session's title; a title set before the row exists is queued. */ + 'session.title': { params: SessionTitleParams; result: SessionTitleResult } + /** Drop the last user turn (and everything after it) from an idle session. */ + 'session.undo': { params: SessionUndoParams; result: SessionUndoResult } + /** Token / context / cost counters for the session (+ Nous credit lines when available). */ + 'session.usage': { params: SessionUsageParams; result: SessionUsageResult } + /** Re-home a stored session's workspace; git identity is replaced and a live agent follows. */ + 'session.workspace.move': { params: SessionWorkspaceMoveParams; result: SessionWorkspaceMoveResult } + /** Strict provider check through the same runtime resolution the agent uses on session creation. */ + 'setup.runtime_check': { params: SetupRuntimeCheckParams; result: SetupRuntimeCheckResult } + /** Loose provider check: is ANY provider auth state discoverable for the (launch or named) profile. */ + 'setup.status': { params: ProfileParams; result: SetupStatusResult } + /** Run a safe (non-dangerous) shell command captured for ``!cmd`` / inline substitution. */ + 'shell.exec': { params: ShellExecParams; result: ShellExecResult } + /** Skills hub backend: list the profile's skills or search / browse / inspect / install from the hub. */ + 'skills.manage': { params: SkillsManageParams; result: SkillsManageResult } + /** Re-scan skill dirs; the pre-rendered ``output`` is what /reload-skills prints. */ + 'skills.reload': { params: SkillsReloadParams; result: SkillsReloadResult } + /** Execute a slash command against the session's slash worker (or a live/plugin shortcut). */ + 'slash.exec': { params: SlashExecParams; result: SlashExecResult } + /** Saved spawn-tree snapshots, newest first. */ + 'spawn_tree.list': { params: SpawnTreeListParams; result: SpawnTreeListResult } + /** Read one saved spawn-tree snapshot (path must be under the spawn-trees root). */ + 'spawn_tree.load': { params: SpawnTreeLoadParams; result: SpawnTreeLoadResult } + /** Persist a finished delegation tree snapshot under the session's spawn-trees dir. */ + 'spawn_tree.save': { params: SpawnTreeSaveParams; result: SpawnTreeSaveResult } + /** Hard-interrupt one owned child; ``found`` is false when it already finished. */ + 'subagent.interrupt': { params: SubagentIdParams; result: SubagentInterruptResult } + /** Live children owned by this session (other sessions' children never leak). */ + 'subagent.list': { params: SessionParams; result: SubagentListResult } + /** Queue steering text into a live delegated child owned by this session. */ + 'subagent.steer': { params: SubagentSteerParams; result: SubagentSteerResult } + /** Last 16KB of an owned child's live transcript. */ + 'subagent.tail': { params: SubagentIdParams; result: SubagentTailResult } + /** Schedule a downgrade / same-price change or a period-end cancellation. */ + 'subscription.change': { params: SubscriptionChangeParams; result: BillingPendingChangeResult } + /** Chargeless quote of what a plan change would do (billing:manage). */ + 'subscription.preview': { params: SubscriptionPreviewParams; result: SubscriptionPreviewResult } + /** Clear a scheduled downgrade / cancellation (re-enables recurring spend). */ + 'subscription.resume': { params: ProfileParams; result: BillingPendingChangeResult } + /** Current plan, tier catalog and usage for the picker; fail-open when logged out. */ + 'subscription.state': { params: ProfileParams; result: SubscriptionStateResult } + /** Prorate, charge and flip the plan (billing:manage, idempotent). */ + 'subscription.upgrade': { params: SubscriptionUpgradeParams; result: SubscriptionUpgradeResult } + /** Host battery for the status bar; always resolves, ``available: false`` when unreadable. */ + 'system.battery': { params: SystemBatteryParams; result: SystemBatteryResult } + /** Record the client's column width for server-side rendering. */ + 'terminal.resize': { params: TerminalResizeParams; result: TerminalResizeResult } + /** Persist a toolset / MCP enable-disable change and rebuild the session agent so it takes effect now. */ + 'tools.configure': { params: ToolsConfigureParams; result: ToolsConfigureResult } + /** Every toolset with its resolved tool names, flagged against the session's (or config's) enabled set. */ + 'tools.list': { params: _SessionScoped; result: ToolsetsListResult } + /** The /tools listing grouped by toolset, including tools deferred behind the tool_search bridge. */ + 'tools.show': { params: _SessionScoped; result: ToolsShowResult } + /** Toolset summaries (no tool names) for the desktop Toolsets tab. */ + 'toolsets.list': { params: _SessionScoped; result: ToolsetsListResult } + /** Two-bar dollar usage view shared by /usage, /topup and /subscription; fail-open to unavailable. */ + 'usage.bars': { params: ProfileParams; result: UsageModel } + /** Add a login / payment / address item to the local vault. */ + 'vault.add': { params: VaultAddParams; result: VaultAddResult } + /** Metadata-only listing across the local vault and every unlocked password manager. */ + 'vault.list': { params: ProfileParams; result: VaultListResult } + /** Forget a manager's session token (every manager when no name is given). */ + 'vault.lock': { params: VaultLockParams; result: VaultLockResult } + /** Remove a local vault item by id. */ + 'vault.remove': { params: VaultRemoveParams; result: VaultRemoveResult } + /** Enable or disable an external password manager (disabling also locks it). */ + 'vault.source.set': { params: VaultSourceSetParams; result: VaultSourceSetResult } + /** Status of every login source (local vault + detected password managers). */ + 'vault.sources': { params: ProfileParams; result: VaultSourcesResult } + /** Unlock a password manager for this session with its master password. */ + 'vault.unlock': { params: VaultUnlockParams; result: VaultUnlockResult } + /** Best known verification evidence for a cwd/session; read-only, never runs checks. */ + 'verification.status': { params: VerificationStatusParams; result: VerificationStatusResult } + /** VAD-bounded push-to-talk; the transcript arrives as a voice.transcript event. */ + 'voice.record': { params: VoiceRecordParams; result: VoiceRecordResult } + /** /voice parity: report, flip voice mode on/off, or toggle speech output. */ + 'voice.toggle': { params: VoiceToggleParams; result: VoiceToggleResult } + /** Speak text through the backend TTS engine (barge-in aware). */ + 'voice.tts': { params: VoiceTtsParams; result: VoiceTtsResult } + /** Push client-captured PCM into the armed detector (mic-less remote backends). */ + 'wake.feed': { params: WakeFeedParams; result: WakeFeedResult } + /** Release the mic (e.g. while the desktop's browser captures audio). */ + 'wake.pause': { params: WakeControlParams; result: WakePauseResult } + /** Reclaim the mic after a pause; no-op if the listener isn't armed. */ + 'wake.resume': { params: WakeControlParams; result: WakeResumeResult } + /** Arm the wake-word listener for the calling surface; refusals explain why. */ + 'wake.start': { params: WakeStartParams; result: WakeStartResult } + /** Everything a client needs to draw the wake-word state and decide whether to (re)arm. */ + 'wake.status': { params: WakeStatusParams; result: WakeStatusResult } + /** Stop this surface's listener; persist also writes wake_word.enabled: false. */ + 'wake.stop': { params: WakeStopParams; result: WakeStopResult } +} +export type RpcMethod = keyof RpcMethods +export const RPC_METHODS = [ + 'agents.list', + 'approval.pending', + 'approval.received', + 'approval.respond', + 'billing.auto_reload', + 'billing.charge', + 'billing.charge_status', + 'billing.state', + 'billing.step_up', + 'bot_relay.deliver', + 'bot_relay.outbox.drain', + 'bot_relay.reply', + 'bot_relay.roster.sync', + 'browser.controller.detach', + 'browser.controller.heartbeat', + 'browser.controller.register', + 'browser.controller.result', + 'browser.manage', + 'clarify.lock', + 'cli.exec', + 'clipboard.paste', + 'command.dispatch', + 'command.resolve', + 'commands.catalog', + 'complete.path', + 'complete.slash', + 'config.get', + 'config.set', + 'config.show', + 'connectors.connect', + 'connectors.list', + 'cron.manage', + 'delegation.pause', + 'delegation.status', + 'diagnostics.share_nous', + 'file.attach', + 'free_tier.ack_notice', + 'free_tier.provision', + 'free_tier.status', + 'gateway.capabilities', + 'groups.approve', + 'groups.capabilities', + 'groups.create', + 'groups.demote', + 'groups.disband', + 'groups.list', + 'groups.log', + 'groups.peer.invite', + 'groups.peer.register', + 'groups.peer.revoke', + 'groups.promote', + 'groups.rename', + 'groups.replica_state', + 'groups.replicate', + 'groups.retry', + 'groups.send', + 'groups.state', + 'groups.stop', + 'handoff.fail', + 'handoff.request', + 'handoff.state', + 'image.attach', + 'image.attach_bytes', + 'image.detach', + 'image.generate', + 'input.detect_drop', + 'insights.get', + 'learning.delete', + 'learning.detail', + 'learning.edit', + 'learning.frames', + 'llm.oneshot', + 'mcp.catalog', + 'mcp.servers.add', + 'mcp.servers.list', + 'mcp.servers.oauth.callback', + 'mcp.servers.oauth.cancel', + 'mcp.servers.oauth.poll', + 'mcp.servers.oauth.start', + 'mcp.servers.remove', + 'mcp.servers.set_api_key', + 'mcp.servers.status', + 'mcp.servers.test', + 'message.react', + 'model.disconnect', + 'model.options', + 'model.save_key', + 'paste.collapse', + 'pdf.attach', + 'pet.cancel', + 'pet.cells', + 'pet.disable', + 'pet.export', + 'pet.gallery', + 'pet.generate', + 'pet.generate.status', + 'pet.hatch', + 'pet.info', + 'pet.info.meta', + 'pet.remove', + 'pet.rename', + 'pet.scale', + 'pet.select', + 'pet.thumb', + 'ping', + 'plugins.list', + 'plugins.manage', + 'preview.restart', + 'process.kill', + 'process.list', + 'process.stop', + 'profiles.configure', + 'profiles.create', + 'profiles.describe', + 'profiles.get_asset', + 'profiles.list', + 'profiles.remember_onboarding', + 'profiles.set_asset', + 'project.facts', + 'projects.add_folder', + 'projects.archive', + 'projects.create', + 'projects.delete', + 'projects.discover_repos', + 'projects.for_cwd', + 'projects.get', + 'projects.list', + 'projects.project_sessions', + 'projects.record_repos', + 'projects.remove_folder', + 'projects.set_active', + 'projects.set_primary', + 'projects.tree', + 'projects.update', + 'prompt.background', + 'prompt.btw', + 'prompt.submit', + 'reload.env', + 'reload.mcp', + 'request.answer', + 'rollback.diff', + 'rollback.list', + 'rollback.restore', + 'session.activate', + 'session.active_list', + 'session.branch', + 'session.close', + 'session.compress', + 'session.context_breakdown', + 'session.control', + 'session.control.read', + 'session.create', + 'session.cwd.set', + 'session.delete', + 'session.events.since', + 'session.events.stats', + 'session.foreign.import', + 'session.foreign.list', + 'session.foreign.preview', + 'session.history', + 'session.interrupt', + 'session.list', + 'session.most_recent', + 'session.redirect', + 'session.resume', + 'session.save', + 'session.set_hidden', + 'session.status', + 'session.steer', + 'session.title', + 'session.undo', + 'session.usage', + 'session.workspace.move', + 'setup.runtime_check', + 'setup.status', + 'shell.exec', + 'skills.manage', + 'skills.reload', + 'slash.exec', + 'spawn_tree.list', + 'spawn_tree.load', + 'spawn_tree.save', + 'subagent.interrupt', + 'subagent.list', + 'subagent.steer', + 'subagent.tail', + 'subscription.change', + 'subscription.preview', + 'subscription.resume', + 'subscription.state', + 'subscription.upgrade', + 'system.battery', + 'terminal.resize', + 'tools.configure', + 'tools.list', + 'tools.show', + 'toolsets.list', + 'usage.bars', + 'vault.add', + 'vault.list', + 'vault.lock', + 'vault.remove', + 'vault.source.set', + 'vault.sources', + 'vault.unlock', + 'verification.status', + 'voice.record', + 'voice.toggle', + 'voice.tts', + 'wake.feed', + 'wake.pause', + 'wake.resume', + 'wake.start', + 'wake.status', + 'wake.stop' +] as const satisfies readonly RpcMethod[] + +// ── Server→client requests ── +export interface ServerRequestMap { + /** A dangerous command awaits the user's decision. */ + approval: { params: ApprovalRequestParams; result: ApprovalResult } + /** The clarify tool: ask the user one question or a batch. */ + clarify: { params: ClarifyRequestParams; result: ClarifyResult } + /** Consent card for installing / enabling / authorising an MCP server. */ + 'mcp.setup': { params: McpSetupRequestParams; 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 } + /** Masked sudo password for the terminal tool. */ + sudo: { params: EmptyRequestParams; result: ValueResult } + /** Read the visible in-app terminal buffer (JSON text answer). */ + 'terminal.read': { params: ReadRangeRequestParams; result: ValueResult } + /** Drive a guided tour highlight in the desktop renderer. */ + tour: { params: TourRequestParams; result: ValueResult } + /** A one-time / 2FA code the user reads from their device. */ + 'vault.code': { params: VaultCodeRequestParams; result: ValueResult } + /** Save a login for a site the agent is about to fill; the answer is JSON {identifier, password}. */ + 'vault.save_login': { params: VaultSaveLoginRequestParams; result: ValueResult } + /** Master password to unlock an external password manager for this session. */ + 'vault.unlock_prompt': { params: VaultUnlockRequestParams; result: ValueResult } + /** Enumerate the native window below the app (JSON text answer). */ + 'window.read': { params: EmptyRequestParams; result: ValueResult } +} +export type ServerRequestMethod = keyof ServerRequestMap +export const SERVER_REQUEST_METHODS = [ + 'approval', + 'clarify', + 'mcp.setup', + 'preview.act', + 'preview.read', + 'secret', + 'sudo', + 'terminal.read', + 'tour', + 'vault.code', + 'vault.save_login', + 'vault.unlock_prompt', + 'window.read' +] as const satisfies readonly ServerRequestMethod[] + +// ── Notifications (`event` frames) ── +export interface GatewayEventMap { + /** Output chunk from an agent-owned background process. */ + 'agent.terminal.output': TerminalOutputPayload + /** A /background side agent finished. */ + 'background.complete': SideAgentCompletePayload + /** Device-flow URL + code for the billing scope step-up; the client opens the browser. */ + 'billing.step_up.verification': BillingStepUpVerificationPayload + /** A bot-relay outbox envelope is queued; drain it. */ + 'bot_relay.outbox.pending': ChangeSignalPayload + /** Withdraw a pending controller command. */ + 'browser.controller.cancel': BrowserControllerCancelPayload + /** Dispatch one browser action to the attached controller. */ + 'browser.controller.command': BrowserControllerCommandPayload + /** Browser (CDP) connect / install progress line. */ + 'browser.progress': BrowserProgressPayload + /** A /btw side question was answered. */ + 'btw.complete': SideAgentCompletePayload + /** cron/jobs.json moved; refetch the cron list. */ + 'cron.changed': ChangeSignalPayload + /** A session-level failure outside a turn (agent init, model switch, compression, resume). */ + error: ErrorPayload + /** First frame of a connection: the resolved skin, the change-event capability and the replay epoch. */ + 'gateway.ready': GatewayReadyPayload + /** Apply a named desktop layout preset. */ + 'layout.apply': LayoutApplyPayload + /** The turn ended: final text, usage and outcome. */ + 'message.complete': MessageCompletePayload + /** One streamed chunk of the assistant reply. */ + 'message.delta': StreamDeltaPayload + /** Interim assistant commentary (text beside tool calls) sealed as its own segment. */ + 'message.interim': MessageInterimPayload + /** The agent reacted to a message; paint it live. */ + 'message.reaction': MessageReactionPayload + /** A turn began streaming; no payload. */ + 'message.start': Record + /** The MoA aggregator started. */ + 'moa.aggregating': MoaAggregatingPayload + /** MoA phase transition (currently only ``aggregator``). */ + 'moa.phase': MoaPhasePayload + /** MoA reference fan-out progress (n/total). */ + 'moa.progress': MoaProgressPayload + /** One MoA reference model's output. */ + 'moa.reference': MoaReferencePayload + /** Informational one-liner for the session (capabilities refreshed). */ + notice: NoticePayload + /** Withdraw the notice with this key. */ + 'notification.clear': NotificationClearPayload + /** Show / replace a keyed out-of-band notice (toast or status bar). */ + 'notification.show': NotificationShowPayload + /** Pairing state moved; refetch pairing. */ + 'pairing.changed': ChangeSignalPayload + /** Focus / reveal a named desktop pane. */ + 'pane.reveal': PaneRevealPayload + /** The active pet / its spritesheet changed (watcher). */ + 'pet.changed': PetChangedPayload + /** Pet base-draft generation progress. */ + 'pet.generate.progress': PetGenerateProgressPayload + /** Pet hatch (row drawing) progress. */ + 'pet.hatch.progress': PetHatchProgressPayload + /** gateway_state.json moved; refetch platform status. */ + 'platforms.changed': ChangeSignalPayload + /** Close the preview pane or one tab. */ + 'preview.close': PreviewClosePayload + /** Open a URL / file in the desktop preview pane. */ + 'preview.open': PreviewOpenPayload + /** The hidden preview-restart agent finished. */ + 'preview.restart.complete': SideAgentCompletePayload + /** Progress line from the preview-restart agent. */ + 'preview.restart.progress': PreviewRestartProgressPayload + /** Affection reaction detected in the user's message (hearts etc.). */ + reaction: ReactionPayload + /** A completed reasoning block (non-streaming providers). */ + 'reasoning.available': StreamDeltaPayload + /** One streamed chunk of the model's reasoning. */ + 'reasoning.delta': StreamDeltaPayload + /** The backend withdrew an open server→client request; clear the matching card only. */ + 'request.cancel': RequestCancelPayload + /** Background review of the last turn finished. */ + 'review.summary': ReviewSummaryPayload + /** Persisted goal / loop / heartbeat state changed. */ + 'session.control.update': SessionControlUpdatePayload + /** Live session settings snapshot (``server._session_info``); also the ``info`` of create/resume/activate. */ + 'session.info': SessionLiveInfo + /** The backend reclaimed a live session out from under its clients. */ + 'session.reclaimed': SessionReclaimedPayload + /** Deferred resume hydration progress. */ + 'session.resume_progress': SessionResumeProgressPayload + /** Auto-titling renamed the session (``session_id`` is the stored key). */ + 'session.title': SessionTitlePayload + /** Mid-turn usage tick; message.complete carries the authoritative final usage. */ + 'session.usage': SessionUsagePayload + /** state.db moved; refetch the session list. */ + 'sessions.changed': ChangeSignalPayload + /** The free-tier bootstrap finished (broadcast); the desktop's setup gate reads the record. */ + 'setup.ready': SetupReadyPayload + /** The active skin moved (name switch or live colour edit); repaint from this palette. */ + 'skin.changed': SkinPayload + /** Transient status line (kind: status, lifecycle, compacting, goal, loop, heartbeat, process, …). */ + 'status.update': StatusUpdatePayload + /** A child finished (status + observability rollup). */ + 'subagent.complete': SubagentEventPayload + /** Batched tool-name progress from a child. */ + 'subagent.progress': SubagentEventPayload + /** delegate_task accepted a child goal (before the child starts). */ + 'subagent.spawn_requested': SubagentEventPayload + /** A delegated child started running. */ + 'subagent.start': SubagentEventPayload + /** A child's reasoning chunk. */ + 'subagent.thinking': SubagentEventPayload + /** A child called a tool. */ + 'subagent.tool': SubagentEventPayload + /** An agent-owned background process closed. */ + 'terminal.close': TerminalClosePayload + /** Legacy thinking-text chunk (thinking_callback). */ + 'thinking.delta': StreamDeltaPayload + /** Point at a desktop element with a one-line tip bubble. */ + 'tip.show': TipShowPayload + /** Full todo snapshot after a todo tool ran. */ + 'todo.updated': TodoUpdatedPayload + /** A tool call finished: parsed result, summary, optional diff / todo snapshot. */ + 'tool.complete': ToolCompletePayload + /** The model is emitting a tool call's arguments. */ + 'tool.generating': ToolGeneratingPayload + /** Tool output was classified as risky (prompt-injection / secret findings). */ + 'tool.output_risk': ToolOutputRiskPayload + /** A tool call began (stable id + full args). */ + 'tool.start': ToolStartPayload + /** Barge-in: the spoken interjection interrupted the turn; no payload. */ + 'voice.interrupted': Record + /** Voice recorder state changed. */ + 'voice.status': VoiceStatusPayload + /** A voice capture produced text (or a stop phrase / silence limit). */ + 'voice.transcript': VoiceTranscriptPayload + /** A wake phrase fired. */ + 'wake.detected': WakeDetectedPayload +} +export type GatewayEventType = keyof GatewayEventMap +export const GATEWAY_EVENT_TYPES = [ + 'agent.terminal.output', + 'background.complete', + 'billing.step_up.verification', + 'bot_relay.outbox.pending', + 'browser.controller.cancel', + 'browser.controller.command', + 'browser.progress', + 'btw.complete', + 'cron.changed', + 'error', + 'gateway.ready', + 'layout.apply', + 'message.complete', + 'message.delta', + 'message.interim', + 'message.reaction', + 'message.start', + 'moa.aggregating', + 'moa.phase', + 'moa.progress', + 'moa.reference', + 'notice', + 'notification.clear', + 'notification.show', + 'pairing.changed', + 'pane.reveal', + 'pet.changed', + 'pet.generate.progress', + 'pet.hatch.progress', + 'platforms.changed', + 'preview.close', + 'preview.open', + 'preview.restart.complete', + 'preview.restart.progress', + 'reaction', + 'reasoning.available', + 'reasoning.delta', + 'request.cancel', + 'review.summary', + 'session.control.update', + 'session.info', + 'session.reclaimed', + 'session.resume_progress', + 'session.title', + 'session.usage', + 'sessions.changed', + 'setup.ready', + 'skin.changed', + 'status.update', + 'subagent.complete', + 'subagent.progress', + 'subagent.spawn_requested', + 'subagent.start', + 'subagent.thinking', + 'subagent.tool', + 'terminal.close', + 'thinking.delta', + 'tip.show', + 'todo.updated', + 'tool.complete', + 'tool.generating', + 'tool.output_risk', + 'tool.start', + 'voice.interrupted', + 'voice.status', + 'voice.transcript', + 'wake.detected' +] as const satisfies readonly GatewayEventType[] diff --git a/apps/shared/src/gateway-contract.openrpc.json b/apps/shared/src/gateway-contract.openrpc.json new file mode 100644 index 0000000000..6fac2ed8da --- /dev/null +++ b/apps/shared/src/gateway-contract.openrpc.json @@ -0,0 +1,34201 @@ +{ + "openrpc": "1.3.2", + "info": { + "title": "Hermes TUI/Desktop gateway", + "version": "1", + "description": "Generated from tui_gateway/contracts by scripts/gen_gateway_contracts.py." + }, + "methods": [ + { + "name": "agents.list", + "summary": "Registry-wide background process summary for ``/agents``.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/AgentsListParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/AgentsListResult" + } + } + }, + { + "name": "approval.pending", + "summary": "Replay the approvals still waiting on this session (reconnect / polling).", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/ApprovalPendingParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/ApprovalPendingResult" + } + } + }, + { + "name": "approval.received", + "summary": "Tell the backend the card is on screen, so its timeout clock starts.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/ApprovalReceivedParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/ApprovalReceivedResult" + } + } + }, + { + "name": "approval.respond", + "summary": "Deliver the user's decision on a dangerous command (falls back to durable identity on a stale sid).", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/ApprovalRespondParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/ApprovalRespondResult" + } + } + }, + { + "name": "billing.auto_reload", + "summary": "Enable/disable auto top-up with its threshold and reload amount (billing:manage).", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/BillingAutoReloadParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/BillingMutationResult" + } + } + }, + { + "name": "billing.charge", + "summary": "Start a one-off top-up charge (billing:manage, idempotent).", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/BillingChargeParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/BillingChargeResult" + } + } + }, + { + "name": "billing.charge_status", + "summary": "Poll one charge by id.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/BillingChargeStatusParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/BillingChargeStatusResult" + } + } + }, + { + "name": "billing.state", + "summary": "Read-only billing view (no scope); the Nous free tier is answered locally without a portal call.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/ProfileParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/BillingStateResult" + } + } + }, + { + "name": "billing.step_up", + "summary": "Run the billing:manage device flow; the URL/code arrive via billing.step_up.verification.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/BillingStepUpParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/BillingStepUpResult" + } + } + }, + { + "name": "bot_relay.deliver", + "summary": "Deliver a relayed DM into a Bot Chat on this gateway and return the one-turn reply (blocking).", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/BotRelayDeliverParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/BotRelayDeliverResult" + } + } + }, + { + "name": "bot_relay.outbox.drain", + "summary": "Atomically claim every pending cross-connection envelope queued on this gateway.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/BotRelayOutboxDrainParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/BotRelayOutboxDrainResult" + } + } + }, + { + "name": "bot_relay.reply", + "summary": "Write a relayed reply and/or typed error for an envelope so the sender-side waiter resolves.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/BotRelayReplyParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/OkResult" + } + } + }, + { + "name": "bot_relay.roster.sync", + "summary": "Replace this gateway's view of agents on other connections; answers the accepted row count.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/BotRelayRosterSyncParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/BotRelayRosterSyncResult" + } + } + }, + { + "name": "browser.controller.detach", + "summary": "Hard-detach only the controller owned by this authenticated transport.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/BrowserControllerParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/BrowserControllerDetachResult" + } + } + }, + { + "name": "browser.controller.heartbeat", + "summary": "Acknowledge a heartbeat only for this transport's own attached controller.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/BrowserControllerParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/OkResult" + } + } + }, + { + "name": "browser.controller.register", + "summary": "Attach this connection as the browser controller for one session; fails closed (4403).", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/BrowserControllerRegisterParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/BrowserControllerRegisterResult" + } + } + }, + { + "name": "browser.controller.result", + "summary": "Deliver one command result to the broker; accepted is false for unknown or settled command ids.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/BrowserControllerResultParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/BrowserControllerResultResult" + } + } + }, + { + "name": "browser.manage", + "summary": "Inspect, attach to, or drop the CDP browser the tools use; ``messages`` narrate a connect.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/BrowserManageParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/BrowserManageResult" + } + } + }, + { + "name": "clarify.lock", + "summary": "Lock one answer of a batch clarify request (editable until every question is locked).", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/ClarifyLockParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/ClarifyLockResult" + } + } + }, + { + "name": "cli.exec", + "summary": "Run ``hermes `` non-interactively and capture its output; ``blocked`` explains a refusal.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/CliExecParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/CliExecResult" + } + } + }, + { + "name": "clipboard.paste", + "summary": "Save the host clipboard image into the session and queue it for the next turn.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/ClipboardPasteParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/AttachedImageResult" + } + } + }, + { + "name": "command.dispatch", + "summary": "Run a quick/plugin/bundle/skill/built-in slash command and answer a structured directive.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/CommandDispatchParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/CommandDispatchResult" + } + } + }, + { + "name": "command.resolve", + "summary": "Canonical registry command for a name or alias.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/CommandResolveParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/CommandResolveResult" + } + } + }, + { + "name": "commands.catalog", + "summary": "Categorized slash metadata (registry, quick, plugin, skill) for completion menus.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/CommandsCatalogParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/CommandsCatalogResult" + } + } + }, + { + "name": "complete.path", + "summary": "Path / @-reference completions for the composer (files, folders, profiles, plugin providers).", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/CompletePathParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/CompletionItemsResult" + } + } + }, + { + "name": "complete.slash", + "summary": "Ranked slash-command / skill completions for a ``/`` token.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/CompleteSlashParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/CompleteSlashResult" + } + } + }, + { + "name": "config.get", + "summary": "Read one normalised config value (or the whole effective config) the way the UIs render it.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/ConfigGetParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/ConfigGetResult" + } + } + }, + { + "name": "config.set", + "summary": "Change one config key (persisted or session-scoped) and read back the normalised value.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/ConfigSetParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/ConfigSetResult" + } + } + }, + { + "name": "config.show", + "summary": "Masked, display-ready config summary (model / agent / environment rows).", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/ConfigShowParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/ConfigShowResult" + } + } + }, + { + "name": "connectors.connect", + "summary": "Start (or re-initiate) authorization for named connectors; returns per-connector links/status.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/ConnectorsConnectParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/ConnectorsConnectResult" + } + } + }, + { + "name": "connectors.list", + "summary": "Connector catalog + connection state for one owned session (``available=False`` when the toolset is off).", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/ConnectorsListParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/ConnectorsListResult" + } + } + }, + { + "name": "cron.manage", + "summary": "List/add/remove/pause/resume cron jobs in the (optionally profile-scoped) cron store.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/CronManageParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/CronManageResult" + } + } + }, + { + "name": "delegation.pause", + "summary": "Block/unblock NEW spawns globally (active children keep running); returns the new state.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/DelegationPauseParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/DelegationPauseResult" + } + } + }, + { + "name": "delegation.status", + "summary": "Running subagent tree plus the spawn pause flag and limits.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/ProfileParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/DelegationStatusResult" + } + } + }, + { + "name": "diagnostics.share_nous", + "summary": "Upload a force-redacted debug bundle to Nous-internal diagnostics storage.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/DiagnosticsShareNousParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/DiagnosticsShareNousResult" + } + } + }, + { + "name": "file.attach", + "summary": "Stage a non-image file into the session workspace and hand back its @file: ref.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/FileAttachParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/FileAttachResult" + } + } + }, + { + "name": "free_tier.ack_notice", + "summary": "Mark the one-time availability notice as shown on the free-tier identity.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/ProfileParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/FreeTierAckNoticeResult" + } + } + }, + { + "name": "free_tier.provision", + "summary": "Explicit retry of the free-tier identity mint when the boot bootstrap could not create it.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/ProfileParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/FreeTierProvisionResult" + } + } + }, + { + "name": "free_tier.status", + "summary": "Pure read of the focused profile's free-tier identity state (no network, no side effects).", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/ProfileParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/FreeTierStatusResult" + } + } + }, + { + "name": "gateway.capabilities", + "summary": "What THIS build enforces (a client withholds a feature unless advertised).", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/PingParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/GatewayCapabilitiesResult" + } + } + }, + { + "name": "groups.approve", + "summary": "Resolve one exact pending approval raised by a local or peer room member.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/GroupsApproveParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/GroupsApproveResult" + } + } + }, + { + "name": "groups.capabilities", + "summary": "Describe the hosted-room protocol implemented by this gateway.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/GroupsCapabilitiesParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/GroupsCapabilitiesResult" + } + } + }, + { + "name": "groups.create", + "summary": "Create a hosted room idempotently; authority is this gateway's stable install identity.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/GroupsCreateParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/GroupsCreateResult" + } + } + }, + { + "name": "groups.demote", + "summary": "Fence this gateway's stale room authority against a proven newer epoch.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/GroupsDemoteParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/GroupsDemoteResult" + } + } + }, + { + "name": "groups.disband", + "summary": "Permanently tombstone a hosted room id after stopping its work and revoking peer routes.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/GroupsDisbandParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/GroupsDisbandResult" + } + } + }, + { + "name": "groups.list", + "summary": "List rooms hosted by this gateway, most recently changed first.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/GroupsListParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/GroupsListResult" + } + } + }, + { + "name": "groups.log", + "summary": "A monotonic room-log delta after since_seq, bounded by count and page bytes.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/GroupsLogParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/GroupsLogResult" + } + } + }, + { + "name": "groups.peer.invite", + "summary": "Mint one target-issued room/profile grant for a prospective room home.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/GroupsPeerInviteParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/GroupsPeerInviteResult" + } + } + }, + { + "name": "groups.peer.register", + "summary": "Register and probe one scoped peer route on the room home.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/GroupsPeerRegisterParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/GroupsPeerRegisterResult" + } + } + }, + { + "name": "groups.peer.revoke", + "summary": "Revoke one target-issued grant using its exact profile scope.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/GroupsPeerRevokeParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/GroupsPeerRevokeResult" + } + } + }, + { + "name": "groups.promote", + "summary": "Continue a replicated room on this gateway at epoch + 1; requires confirm=true.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/GroupsPromoteParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/GroupsPromoteResult" + } + } + }, + { + "name": "groups.rename", + "summary": "Rename one hosted room atomically with its replay event.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/GroupsRenameParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/GroupsRenameResult" + } + } + }, + { + "name": "groups.replica_state", + "summary": "The local replica's coverage and authority lineage for one room.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/GroupsReplicaStateParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/GroupsReplicaStateResult" + } + } + }, + { + "name": "groups.replicate", + "summary": "Persist one authority-stamped replay page into the local replica store; idempotent.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/GroupsReplicateParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/GroupsReplicateResult" + } + } + }, + { + "name": "groups.retry", + "summary": "Retry one indeterminate room task after explicit user confirmation.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/GroupsRetryParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/GroupsRetryResult" + } + } + }, + { + "name": "groups.send", + "summary": "Append one inert message.user event idempotently; the actor is server-owned.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/GroupsSendParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/GroupsSendResult" + } + } + }, + { + "name": "groups.state", + "summary": "One hosted room's replay cursor and fenced authority state, plus live driver status.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/GroupsStateParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/GroupsStateResult" + } + } + }, + { + "name": "groups.stop", + "summary": "Durably cancel queued or running work for one hosted room.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/GroupsStopParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/GroupsStopResult" + } + } + }, + { + "name": "handoff.fail", + "summary": "Fail a not-yet-claimed handoff (client poll timeout); CAS against the watcher.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/HandoffFailParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/HandoffFailResult" + } + } + }, + { + "name": "handoff.request", + "summary": "Queue a handoff to a messaging platform's home channel; the gateway watcher claims it.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/HandoffRequestParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/HandoffRequestResult" + } + } + }, + { + "name": "handoff.state", + "summary": "Poll the handoff row for this session.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/SessionParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/HandoffStateResult" + } + } + }, + { + "name": "image.attach", + "summary": "Queue a gateway-visible image file for the next turn.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/ImageAttachParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/AttachedImageResult" + } + } + }, + { + "name": "image.attach_bytes", + "summary": "Queue an image uploaded as base64 (remote client); reply mirrors image.attach.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/ImageAttachBytesParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/AttachedImageResult" + } + } + }, + { + "name": "image.detach", + "summary": "Drop a queued image before the turn is sent.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/ImageDetachParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/ImageDetachResult" + } + } + }, + { + "name": "image.generate", + "summary": "Generate an image through the tool's provider dispatcher and hand the renderer a data URL.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/ImageGenerateParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/ImageGenerateResult" + } + } + }, + { + "name": "input.detect_drop", + "summary": "Recognise a terminal file drop pasted into the composer and turn it into an attachment.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/InputDetectDropParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/InputDetectDropResult" + } + } + }, + { + "name": "insights.get", + "summary": "Session/message counts over the last ``days`` for the (optionally scoped) profile store.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/InsightsGetParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/InsightsGetResult" + } + } + }, + { + "name": "learning.delete", + "summary": "Archive a skill (restorable via curator) or remove a memory chunk.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/LearningNodeParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/LearningMutationResult" + } + } + }, + { + "name": "learning.detail", + "summary": "Node content (SKILL.md or memory chunk) for an edit prefill.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/LearningNodeParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/LearningDetailResult" + } + } + }, + { + "name": "learning.edit", + "summary": "Rewrite a node's content (SKILL.md or memory chunk).", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/LearningEditParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/LearningMutationResult" + } + } + }, + { + "name": "learning.frames", + "summary": "Pre-render the /journey timeline (frames + legend/summary) so the TUI walks it locally.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/LearningFramesParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/LearningFramesResult" + } + } + }, + { + "name": "llm.oneshot", + "summary": "Stateless one-shot LLM completion (titles, ideas) on the session's or the task backend.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/LlmOneshotParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/LlmOneshotResult" + } + } + }, + { + "name": "mcp.catalog", + "summary": "Curated MCP presets with per-profile installed/enabled state and the env keys each needs.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/ProfileParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/McpCatalogResult" + } + } + }, + { + "name": "mcp.servers.add", + "summary": "Add a server to the profile's config from a catalog preset and/or an explicit config.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/McpServersAddParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/McpServersAddResult" + } + } + }, + { + "name": "mcp.servers.list", + "summary": "Configured MCP servers for the (scoped) profile, secrets redacted to env-key names.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/ProfileParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/McpServersListResult" + } + } + }, + { + "name": "mcp.servers.oauth.callback", + "summary": "Relay a client-captured redirect into a client_redirect_uri flow.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/McpOauthCallbackParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/McpOauthCallbackResult" + } + } + }, + { + "name": "mcp.servers.oauth.cancel", + "summary": "Cancel a flow owned by the resolved profile, waking its callback worker.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/McpOauthFlowParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/McpOauthCancelResult" + } + } + }, + { + "name": "mcp.servers.oauth.poll", + "summary": "Poll a flow; approved persists tokens for the profile and returns the probed tools.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/McpOauthFlowParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/McpOauthPollResult" + } + } + }, + { + "name": "mcp.servers.oauth.start", + "summary": "Begin a PKCE OAuth flow; the client opens auth_url and polls mcp.servers.oauth.poll.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/McpOauthStartParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/McpOauthStartResult" + } + } + }, + { + "name": "mcp.servers.remove", + "summary": "Drop a server from the profile's config.yaml.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/McpServerNameParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/McpServersRemoveResult" + } + } + }, + { + "name": "mcp.servers.set_api_key", + "summary": "Store a credential in the profile's .env and reference it from the server config (header or env).", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/McpServersSetApiKeyParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/McpServersSetApiKeyResult" + } + } + }, + { + "name": "mcp.servers.status", + "summary": "Cached runtime state per configured server; never connects, probes, or starts auth.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/ProfileParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/McpServersStatusResult" + } + } + }, + { + "name": "mcp.servers.test", + "summary": "Connect, list tools, disconnect \u2014 an OAuth server with no token on disk is reported as not ok.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/McpServerNameParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/McpServersTestResult" + } + } + }, + { + "name": "message.react", + "summary": "Set/clear one author's emoji reaction on a message; returns the row's full reaction list.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/MessageReactParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/MessageReactResult" + } + } + }, + { + "name": "model.disconnect", + "summary": "Remove every credential (env keys and OAuth state) for a provider.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/ModelDisconnectParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/ModelDisconnectResult" + } + } + }, + { + "name": "model.options", + "summary": "Provider/model inventory for the picker, layered over the session's live provider when given.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/ModelOptionsParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/ModelOptionsResult" + } + } + }, + { + "name": "model.save_key", + "summary": "Save an API key for a provider and return its refreshed inventory row.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/ModelSaveKeyParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/ModelSaveKeyResult" + } + } + }, + { + "name": "paste.collapse", + "summary": "Spill a large paste to a file and hand back the inline placeholder.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/PasteCollapseParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/PasteCollapseResult" + } + } + }, + { + "name": "pdf.attach", + "summary": "Render a PDF's pages to PNG and queue them as images for the next turn.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/PdfAttachParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/PdfAttachResult" + } + } + }, + { + "name": "pet.cancel", + "summary": "Stop an in-flight pet generate/hatch by token (idempotent).", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/PetCancelParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/PetCancelResult" + } + } + }, + { + "name": "pet.cells", + "summary": "Half-block cell frames (or a kitty placement) for one pet state.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/PetCellsParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/PetCellsResult" + } + } + }, + { + "name": "pet.disable", + "summary": "Turn the pet display off from the desktop picker.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/ProfileParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/OkResult" + } + } + }, + { + "name": "pet.export", + "summary": "Export an installed pet as a re-importable .zip.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/PetSlugParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/PetExportResult" + } + } + }, + { + "name": "pet.gallery", + "summary": "Petdex gallery + local install state (installed-only offline); localOnly skips the remote manifest.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/PetGalleryParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/PetGalleryResult" + } + } + }, + { + "name": "pet.generate", + "summary": "Candidate base looks for a new pet (draft step); drafts also stream via pet.generate.progress.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/PetGenerateParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/PetGenerateResult" + } + } + }, + { + "name": "pet.generate.status", + "summary": "Whether pet generation is possible (a reference-capable image backend) and which providers.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/ProfileParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/PetGenerateStatusResult" + } + } + }, + { + "name": "pet.hatch", + "summary": "Turn a base draft into a full spritesheet pet; progress streams via pet.hatch.progress.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/PetHatchParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/PetHatchResult" + } + } + }, + { + "name": "pet.info", + "summary": "Active pet for sprite renderers: spritesheet (base64) + frame geometry + state-row taxonomy.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/PetInfoParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/PetInfoResult" + } + } + }, + { + "name": "pet.info.meta", + "summary": "Cheap active-pet metadata used to avoid full payload refreshes.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/ProfileParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/PetInfoMetaResult" + } + } + }, + { + "name": "pet.remove", + "summary": "Uninstall a pet (delete its directory); if it was active, turn the display off.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/PetSlugParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/PetSlugResult" + } + } + }, + { + "name": "pet.rename", + "summary": "Rename a pet's display name + realign its slug/dir; follows the active slug in config.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/PetRenameParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/PetSlugResult" + } + } + }, + { + "name": "pet.scale", + "summary": "Persist display.pet.scale (clamped to engine bounds) from the desktop slider.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/PetScaleParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/PetScaleResult" + } + } + }, + { + "name": "pet.select", + "summary": "Adopt a pet: install (if needed) + activate; writes display.pet.* to config.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/PetSlugParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/PetSlugResult" + } + } + }, + { + "name": "pet.thumb", + "summary": "Idle-frame PNG data URI for the picker (desktop CSP breaks CDN ).", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/PetThumbParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/PetThumbResult" + } + } + }, + { + "name": "ping", + "summary": "Cheapest liveness probe; answered on the WS reader thread even while every agent is mid-turn.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/PingParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/PingResult" + } + } + }, + { + "name": "plugins.list", + "summary": "Loaded plugin manager entries (legacy flat view); the Plugins Hub uses plugins.manage list.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/PluginsListParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/PluginsListResult" + } + } + }, + { + "name": "plugins.manage", + "summary": "Plugins Hub backend: list installed plugins, toggle, git-install or re-pin a catalog install.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/PluginsManageParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/PluginsManageResult" + } + } + }, + { + "name": "preview.restart", + "summary": "Spawn a hidden agent that brings the desktop preview's dev server back up.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/PreviewRestartParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/TaskIdResult" + } + } + }, + { + "name": "process.kill", + "summary": "Kill one background process the caller's session owns and return its output snapshot.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/ProcessKillParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/ProcessKillResult" + } + } + }, + { + "name": "process.list", + "summary": "Background processes owned by the caller's session (desktop status stack poll).", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/ProcessListParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/ProcessListResult" + } + } + }, + { + "name": "process.stop", + "summary": "Kill every background process in the registry (``/stop``), answering the count killed.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/ProcessStopParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/ProcessStopResult" + } + } + }, + { + "name": "profiles.configure", + "summary": "Editor Save: apply any subset of a profile's sections and report each one.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/ProfilesConfigureParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/ProfilesConfigureResult" + } + } + }, + { + "name": "profiles.create", + "summary": "Create a profile (ws twin of POST /api/profiles), mirroring launch credentials by default.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/ProfilesCreateParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/ProfilesCreateResult" + } + } + }, + { + "name": "profiles.describe", + "summary": "Everything the profile editor shows: soul, model pin, skills, toolsets, MCP servers.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/ProfileNameParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/ProfilesDescribeResult" + } + } + }, + { + "name": "profiles.get_asset", + "summary": "A profile asset as a data URL.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/ProfilesGetAssetParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/ProfilesGetAssetResult" + } + } + }, + { + "name": "profiles.list", + "summary": "Roster of profiles with previews so a client paints without N follow-up calls.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/ProfilesListParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/ProfilesListResult" + } + } + }, + { + "name": "profiles.remember_onboarding", + "summary": "Write the onboarding facts into the default profile's user memory and confirm they landed.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/ProfilesRememberOnboardingParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/ProfilesRememberOnboardingResult" + } + } + }, + { + "name": "profiles.set_asset", + "summary": "Store or clear a profile asset (avatar) atomically.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/ProfilesSetAssetParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/ProfilesSetAssetResult" + } + } + }, + { + "name": "project.facts", + "summary": "Structured project facts for a cwd so UIs don't re-sniff the workspace.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/ProjectFactsParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/ProjectFactsResult" + } + } + }, + { + "name": "projects.add_folder", + "summary": "Attach a folder to a project (optionally as its primary path).", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/ProjectsAddFolderParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/ProjectResult" + } + } + }, + { + "name": "projects.archive", + "summary": "Archive (or with ``restore`` un-archive) a project; answers the full listing.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/ProjectsArchiveParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/ProjectsPayload" + } + } + }, + { + "name": "projects.create", + "summary": "Create a project from a name + folders; duplicate primary paths are refused (5063).", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/ProjectsCreateParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/OptionalProjectResult" + } + } + }, + { + "name": "projects.delete", + "summary": "Delete a project and its folders; answers the full listing.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/ProjectIdParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/ProjectsPayload" + } + } + }, + { + "name": "projects.discover_repos", + "summary": "Repos for the desktop overview: scanned-from-disk (cached) \u222a session-derived.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/ProjectsDiscoverReposParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/ProjectsDiscoverReposResult" + } + } + }, + { + "name": "projects.for_cwd", + "summary": "Which project (if any) owns a directory, plus the resolved cwd and its git branch.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/ProjectsForCwdParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/ProjectsForCwdResult" + } + } + }, + { + "name": "projects.get", + "summary": "One stored project with its folders.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/ProjectIdParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/ProjectResult" + } + } + }, + { + "name": "projects.list", + "summary": "Every project of the profile (archived included) plus which one is active.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/ProfileParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/ProjectsPayload" + } + } + }, + { + "name": "projects.project_sessions", + "summary": "Fully hydrated lanes for one project, from the same grouping as projects.tree.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/ProjectsProjectSessionsParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/ProjectsProjectSessionsResult" + } + } + }, + { + "name": "projects.record_repos", + "summary": "Persist repo roots found by the client's (desktop-side) scan; return the merged list.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/ProjectsRecordReposParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/ProjectsRecordReposResult" + } + } + }, + { + "name": "projects.remove_folder", + "summary": "Detach a folder from a project.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/ProjectFolderParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/ProjectResult" + } + } + }, + { + "name": "projects.set_active", + "summary": "Switch (or clear) the active project for the profile.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/ProjectsSetActiveParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/ActiveIdResult" + } + } + }, + { + "name": "projects.set_primary", + "summary": "Make one attached folder the project's primary path.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/ProjectFolderParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/ProjectResult" + } + } + }, + { + "name": "projects.tree", + "summary": "Project \u2192 repo \u2192 lane overview with counts and a few preview sessions per project.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/ProjectsTreeParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/ProjectsTreeResult" + } + } + }, + { + "name": "projects.update", + "summary": "Patch a project's display fields; answers the refreshed project.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/ProjectsUpdateParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/ProjectResult" + } + } + }, + { + "name": "prompt.background", + "summary": "Run a task on a fresh agent in the background; the answer arrives as background.complete.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/SideAgentParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/TaskIdResult" + } + } + }, + { + "name": "prompt.btw", + "summary": "Side question over a snapshot of the live conversation; the answer arrives as btw.complete.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/SideAgentParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/TaskIdResult" + } + } + }, + { + "name": "prompt.submit", + "summary": "Send a user turn to a live session; busy sessions queue / steer / redirect instead of refusing.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/PromptSubmitParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/PromptSubmitResult" + } + } + }, + { + "name": "reload.env", + "summary": "Re-read ~/.hermes/.env (CLI /reload parity); built agents keep their pool until /new.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/ReloadEnvParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/ReloadEnvResult" + } + } + }, + { + "name": "reload.mcp", + "summary": "Tear down and rediscover MCP servers for every live session (prompt cache is invalidated).", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/ReloadMcpParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/ReloadMcpResult" + } + } + }, + { + "name": "request.answer", + "summary": "Answer an open server\u2192client request from a client that never received the frame.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/RequestAnswerParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/RequestAnswerResult" + } + } + }, + { + "name": "rollback.diff", + "summary": "Diff between a checkpoint and the working tree, with an ANSI rendering sized to the TUI.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/RollbackDiffParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/RollbackDiffResult" + } + } + }, + { + "name": "rollback.list", + "summary": "Checkpoints for the session's cwd; ``enabled: false`` when checkpointing is off.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/RollbackListParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/RollbackListResult" + } + } + }, + { + "name": "rollback.restore", + "summary": "Restore the working tree (or one file) to a checkpoint by hash or 1-based index.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/RollbackRestoreParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/RollbackRestoreResult" + } + } + }, + { + "name": "session.activate", + "summary": "Attach the frontend to a live session without closing the previously focused one.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/SessionActivateParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/SessionActivateResult" + } + } + }, + { + "name": "session.active_list", + "summary": "Live sessions in this process, insertion order (not a DB browser).", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/SessionActiveListParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/SessionActiveListResult" + } + } + }, + { + "name": "session.branch", + "summary": "Fork a live session into a new stored child that shares the parent's history so far.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/SessionBranchParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/SessionBranchResult" + } + } + }, + { + "name": "session.close", + "summary": "Tear down a live session (its stored row stays resumable).", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/SessionCloseParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/SessionCloseResult" + } + } + }, + { + "name": "session.compress", + "summary": "Manual /compress of an idle session, optionally focused on a topic.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/SessionCompressParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/SessionCompressResult" + } + } + }, + { + "name": "session.context_breakdown", + "summary": "Cursor-style split of the context window by category.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/SessionContextBreakdownParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/SessionContextBreakdownResult" + } + } + }, + { + "name": "session.control", + "summary": "Run one allowlisted goal / loop / subgoal / heartbeat action and return the exact resulting snapshot.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/SessionControlParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/SessionControlResult" + } + } + }, + { + "name": "session.control.read", + "summary": "Stable, allowlisted snapshot of one live session's goal / loop / heartbeat state.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/SessionControlReadParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/SessionControlReadResult" + } + } + }, + { + "name": "session.create", + "summary": "Mint a live session (agent builds after the reply); a DB row appears on the first prompt unless seeded.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/SessionCreateParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/SessionCreateResult" + } + } + }, + { + "name": "session.cwd.set", + "summary": "Change a live, idle session's working directory.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/SessionCwdSetParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/SessionCwdSetResult" + } + } + }, + { + "name": "session.delete", + "summary": "Delete a stored session + transcripts; refused while it is live here.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/SessionDeleteParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/SessionDeleteResult" + } + } + }, + { + "name": "session.events.since", + "summary": "Replay events after a seq watermark on WS reconnect; truncated means refetch state.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/SessionEventsSinceParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/SessionEventsSinceResult" + } + } + }, + { + "name": "session.events.stats", + "summary": "Replay-buffer occupancy telemetry (ops/debug).", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/SessionEventsStatsParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/SessionEventsStatsResult" + } + } + }, + { + "name": "session.foreign.import", + "summary": "Import a foreign session into this profile's history (idempotent per origin).", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/SessionForeignIdParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/SessionForeignImportResult" + } + } + }, + { + "name": "session.foreign.list", + "summary": "One page of Claude Code / Codex sessions found on the serving backend.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/SessionForeignListParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/SessionForeignListResult" + } + } + }, + { + "name": "session.foreign.preview", + "summary": "Preview a foreign session's tail before importing it.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/SessionForeignIdParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/SessionForeignPreviewResult" + } + } + }, + { + "name": "session.history", + "summary": "The durable display transcript (ancestors included, row ids attached).", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/SessionHistoryParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/SessionHistoryResult" + } + } + }, + { + "name": "session.interrupt", + "summary": "Stop the running turn (and streaming TTS); retires the crash-recovery marker.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/SessionInterruptParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/SessionInterruptResult" + } + } + }, + { + "name": "session.list", + "summary": "Human-facing stored sessions, most recent first (sub-agent / kanban sources denied).", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/SessionListParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/SessionListResult" + } + } + }, + { + "name": "session.most_recent", + "summary": "Most recent human-facing session; errors fold into a null session_id.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/SessionMostRecentParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/SessionMostRecentResult" + } + } + }, + { + "name": "session.redirect", + "summary": "Redirect the active turn (queued for the next turn while the agent is still building).", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/SessionCorrectionParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/SessionCorrectionResult" + } + } + }, + { + "name": "session.resume", + "summary": "Attach to a stored session: reuse it if live here, else lazy / deferred / cold / eager rebuild.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/SessionResumeParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/SessionResumeResult" + } + } + }, + { + "name": "session.save", + "summary": "Export the transcript to ~/.hermes/sessions/saved (classic /save).", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/SessionSaveParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/SessionSaveResult" + } + } + }, + { + "name": "session.set_hidden", + "summary": "Set/clear hidden (out of the default list, still resumable by its owner) on a session + lineage.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/SessionSetHiddenParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/SessionSetHiddenResult" + } + } + }, + { + "name": "session.status", + "summary": "Rendered /status text for the session.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/SessionStatusParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/SessionStatusResult" + } + } + }, + { + "name": "session.steer", + "summary": "Inject text into the next tool result without interrupting the turn.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/SessionCorrectionParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/SessionCorrectionResult" + } + } + }, + { + "name": "session.title", + "summary": "Read or set a live session's title; a title set before the row exists is queued.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/SessionTitleParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/SessionTitleResult" + } + } + }, + { + "name": "session.undo", + "summary": "Drop the last user turn (and everything after it) from an idle session.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/SessionUndoParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/SessionUndoResult" + } + } + }, + { + "name": "session.usage", + "summary": "Token / context / cost counters for the session (+ Nous credit lines when available).", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/SessionUsageParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/SessionUsageResult" + } + } + }, + { + "name": "session.workspace.move", + "summary": "Re-home a stored session's workspace; git identity is replaced and a live agent follows.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/SessionWorkspaceMoveParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/SessionWorkspaceMoveResult" + } + } + }, + { + "name": "setup.runtime_check", + "summary": "Strict provider check through the same runtime resolution the agent uses on session creation.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/SetupRuntimeCheckParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/SetupRuntimeCheckResult" + } + } + }, + { + "name": "setup.status", + "summary": "Loose provider check: is ANY provider auth state discoverable for the (launch or named) profile.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/ProfileParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/SetupStatusResult" + } + } + }, + { + "name": "shell.exec", + "summary": "Run a safe (non-dangerous) shell command captured for ``!cmd`` / inline substitution.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/ShellExecParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/ShellExecResult" + } + } + }, + { + "name": "skills.manage", + "summary": "Skills hub backend: list the profile's skills or search / browse / inspect / install from the hub.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/SkillsManageParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/SkillsManageResult" + } + } + }, + { + "name": "skills.reload", + "summary": "Re-scan skill dirs; the pre-rendered ``output`` is what /reload-skills prints.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/SkillsReloadParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/SkillsReloadResult" + } + } + }, + { + "name": "slash.exec", + "summary": "Execute a slash command against the session's slash worker (or a live/plugin shortcut).", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/SlashExecParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/SlashExecResult" + } + } + }, + { + "name": "spawn_tree.list", + "summary": "Saved spawn-tree snapshots, newest first.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/SpawnTreeListParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/SpawnTreeListResult" + } + } + }, + { + "name": "spawn_tree.load", + "summary": "Read one saved spawn-tree snapshot (path must be under the spawn-trees root).", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/SpawnTreeLoadParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/SpawnTreeLoadResult" + } + } + }, + { + "name": "spawn_tree.save", + "summary": "Persist a finished delegation tree snapshot under the session's spawn-trees dir.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/SpawnTreeSaveParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/SpawnTreeSaveResult" + } + } + }, + { + "name": "subagent.interrupt", + "summary": "Hard-interrupt one owned child; ``found`` is false when it already finished.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/SubagentIdParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/SubagentInterruptResult" + } + } + }, + { + "name": "subagent.list", + "summary": "Live children owned by this session (other sessions' children never leak).", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/SessionParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/SubagentListResult" + } + } + }, + { + "name": "subagent.steer", + "summary": "Queue steering text into a live delegated child owned by this session.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/SubagentSteerParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/SubagentSteerResult" + } + } + }, + { + "name": "subagent.tail", + "summary": "Last 16KB of an owned child's live transcript.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/SubagentIdParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/SubagentTailResult" + } + } + }, + { + "name": "subscription.change", + "summary": "Schedule a downgrade / same-price change or a period-end cancellation.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/SubscriptionChangeParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/BillingPendingChangeResult" + } + } + }, + { + "name": "subscription.preview", + "summary": "Chargeless quote of what a plan change would do (billing:manage).", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/SubscriptionPreviewParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/SubscriptionPreviewResult" + } + } + }, + { + "name": "subscription.resume", + "summary": "Clear a scheduled downgrade / cancellation (re-enables recurring spend).", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/ProfileParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/BillingPendingChangeResult" + } + } + }, + { + "name": "subscription.state", + "summary": "Current plan, tier catalog and usage for the picker; fail-open when logged out.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/ProfileParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/SubscriptionStateResult" + } + } + }, + { + "name": "subscription.upgrade", + "summary": "Prorate, charge and flip the plan (billing:manage, idempotent).", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/SubscriptionUpgradeParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/SubscriptionUpgradeResult" + } + } + }, + { + "name": "system.battery", + "summary": "Host battery for the status bar; always resolves, ``available: false`` when unreadable.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/SystemBatteryParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/SystemBatteryResult" + } + } + }, + { + "name": "terminal.resize", + "summary": "Record the client's column width for server-side rendering.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/TerminalResizeParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/TerminalResizeResult" + } + } + }, + { + "name": "tools.configure", + "summary": "Persist a toolset / MCP enable-disable change and rebuild the session agent so it takes effect now.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/ToolsConfigureParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/ToolsConfigureResult" + } + } + }, + { + "name": "tools.list", + "summary": "Every toolset with its resolved tool names, flagged against the session's (or config's) enabled set.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/_SessionScoped" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/ToolsetsListResult" + } + } + }, + { + "name": "tools.show", + "summary": "The /tools listing grouped by toolset, including tools deferred behind the tool_search bridge.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/_SessionScoped" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/ToolsShowResult" + } + } + }, + { + "name": "toolsets.list", + "summary": "Toolset summaries (no tool names) for the desktop Toolsets tab.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/_SessionScoped" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/ToolsetsListResult" + } + } + }, + { + "name": "usage.bars", + "summary": "Two-bar dollar usage view shared by /usage, /topup and /subscription; fail-open to unavailable.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/ProfileParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/UsageModel" + } + } + }, + { + "name": "vault.add", + "summary": "Add a login / payment / address item to the local vault.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/VaultAddParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/VaultAddResult" + } + } + }, + { + "name": "vault.list", + "summary": "Metadata-only listing across the local vault and every unlocked password manager.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/ProfileParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/VaultListResult" + } + } + }, + { + "name": "vault.lock", + "summary": "Forget a manager's session token (every manager when no name is given).", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/VaultLockParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/VaultLockResult" + } + } + }, + { + "name": "vault.remove", + "summary": "Remove a local vault item by id.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/VaultRemoveParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/VaultRemoveResult" + } + } + }, + { + "name": "vault.source.set", + "summary": "Enable or disable an external password manager (disabling also locks it).", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/VaultSourceSetParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/VaultSourceSetResult" + } + } + }, + { + "name": "vault.sources", + "summary": "Status of every login source (local vault + detected password managers).", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/ProfileParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/VaultSourcesResult" + } + } + }, + { + "name": "vault.unlock", + "summary": "Unlock a password manager for this session with its master password.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/VaultUnlockParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/VaultUnlockResult" + } + } + }, + { + "name": "verification.status", + "summary": "Best known verification evidence for a cwd/session; read-only, never runs checks.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/VerificationStatusParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/VerificationStatusResult" + } + } + }, + { + "name": "voice.record", + "summary": "VAD-bounded push-to-talk; the transcript arrives as a voice.transcript event.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/VoiceRecordParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/VoiceRecordResult" + } + } + }, + { + "name": "voice.toggle", + "summary": "/voice parity: report, flip voice mode on/off, or toggle speech output.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/VoiceToggleParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/VoiceToggleResult" + } + } + }, + { + "name": "voice.tts", + "summary": "Speak text through the backend TTS engine (barge-in aware).", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/VoiceTtsParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/VoiceTtsResult" + } + } + }, + { + "name": "wake.feed", + "summary": "Push client-captured PCM into the armed detector (mic-less remote backends).", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/WakeFeedParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/WakeFeedResult" + } + } + }, + { + "name": "wake.pause", + "summary": "Release the mic (e.g. while the desktop's browser captures audio).", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/WakeControlParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/WakePauseResult" + } + } + }, + { + "name": "wake.resume", + "summary": "Reclaim the mic after a pause; no-op if the listener isn't armed.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/WakeControlParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/WakeResumeResult" + } + } + }, + { + "name": "wake.start", + "summary": "Arm the wake-word listener for the calling surface; refusals explain why.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/WakeStartParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/WakeStartResult" + } + } + }, + { + "name": "wake.status", + "summary": "Everything a client needs to draw the wake-word state and decide whether to (re)arm.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/WakeStatusParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/WakeStatusResult" + } + } + }, + { + "name": "wake.stop", + "summary": "Stop this surface's listener; persist also writes wake_word.enabled: false.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/WakeStopParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/WakeStopResult" + } + } + } + ], + "components": { + "schemas": { + "ActiveIdResult": { + "additionalProperties": false, + "properties": { + "active_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Active Id" + } + }, + "title": "ActiveIdResult", + "type": "object" + }, + "ActiveSubagent": { + "additionalProperties": true, + "description": "One live child from ``tools/delegate_tool_registry.py::list_active_subagents`` (the record\nis extended by the child runner \u2014 ``missed_steer`` etc. \u2014 so it stays open).", + "properties": { + "subagent_id": { + "title": "Subagent Id", + "type": "string" + }, + "parent_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Parent Id" + }, + "depth": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Depth" + }, + "goal": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Goal" + }, + "delegation_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Delegation Id" + }, + "model": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Model" + }, + "started_at": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Started At" + }, + "status": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Status" + }, + "tool_count": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Tool Count" + }, + "owner_agent_session_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Owner Agent Session Id" + } + }, + "required": [ + "subagent_id" + ], + "title": "ActiveSubagent", + "type": "object" + }, + "AgentPluginRow": { + "additionalProperties": false, + "description": "``methods_tools._plugin_rows`` + ``plugins_cmd_catalog.catalog_row_fields`` provenance.", + "properties": { + "name": { + "title": "Name", + "type": "string" + }, + "key": { + "title": "Key", + "type": "string" + }, + "version": { + "title": "Version", + "type": "string" + }, + "description": { + "title": "Description", + "type": "string" + }, + "source": { + "title": "Source", + "type": "string" + }, + "status": { + "title": "Status", + "type": "string" + }, + "portable": { + "title": "Portable", + "type": "boolean" + }, + "install_dir": { + "title": "Install Dir", + "type": "string" + }, + "has_desktop_half": { + "title": "Has Desktop Half", + "type": "boolean" + }, + "catalog_name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Catalog Name" + }, + "catalog_tier": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Catalog Tier" + }, + "installed_sha": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Installed Sha" + }, + "catalog_sha": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Catalog Sha" + }, + "update_available": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Update Available" + }, + "pinned_sha": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Pinned Sha" + } + }, + "required": [ + "name", + "key", + "version", + "description", + "source", + "status", + "portable", + "install_dir", + "has_desktop_half" + ], + "title": "AgentPluginRow", + "type": "object" + }, + "AgentProcessRow": { + "additionalProperties": false, + "properties": { + "session_id": { + "title": "Session Id", + "type": "string" + }, + "command": { + "title": "Command", + "type": "string" + }, + "status": { + "title": "Status", + "type": "string" + }, + "uptime": { + "title": "Uptime", + "type": "integer" + } + }, + "required": [ + "session_id", + "command", + "status", + "uptime" + ], + "title": "AgentProcessRow", + "type": "object" + }, + "AgentsListParams": { + "additionalProperties": false, + "properties": { + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + } + }, + "title": "AgentsListParams", + "type": "object" + }, + "AgentsListResult": { + "additionalProperties": false, + "properties": { + "processes": { + "items": { + "$ref": "#/components/schemas/AgentProcessRow" + }, + "title": "Processes", + "type": "array" + } + }, + "title": "AgentsListResult", + "type": "object" + }, + "ApprovalPendingParams": { + "additionalProperties": false, + "properties": { + "session_id": { + "title": "Session Id", + "type": "string" + }, + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + } + }, + "required": [ + "session_id" + ], + "title": "ApprovalPendingParams", + "type": "object" + }, + "ApprovalPendingResult": { + "additionalProperties": false, + "properties": { + "approvals": { + "items": { + "$ref": "#/components/schemas/tui_gateway_contracts_prompt_voice_PendingApproval" + }, + "title": "Approvals", + "type": "array" + } + }, + "required": [ + "approvals" + ], + "title": "ApprovalPendingResult", + "type": "object" + }, + "ApprovalReceivedParams": { + "additionalProperties": false, + "properties": { + "session_id": { + "title": "Session Id", + "type": "string" + }, + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + }, + "request_id": { + "title": "Request Id", + "type": "string" + } + }, + "required": [ + "session_id", + "request_id" + ], + "title": "ApprovalReceivedParams", + "type": "object" + }, + "ApprovalReceivedResult": { + "additionalProperties": false, + "properties": { + "acknowledged": { + "title": "Acknowledged", + "type": "boolean" + } + }, + "required": [ + "acknowledged" + ], + "title": "ApprovalReceivedResult", + "type": "object" + }, + "ApprovalRequestParams": { + "additionalProperties": true, + "description": "``tui_gateway/server.py::_approval_request_payload`` \u2014 the command is redacted server-side.", + "properties": { + "session_id": { + "title": "Session Id", + "type": "string" + }, + "request_id": { + "title": "Request Id", + "type": "string" + }, + "command": { + "default": "", + "title": "Command", + "type": "string" + }, + "description": { + "default": "", + "title": "Description", + "type": "string" + }, + "choices": { + "items": { + "$ref": "#/components/schemas/tui_gateway_contracts_server_requests_ApprovalChoice" + }, + "title": "Choices", + "type": "array" + }, + "allow_permanent": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Allow Permanent" + }, + "allow_session": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Allow Session" + }, + "smart_denied": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Smart Denied" + }, + "tool_name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Tool Name" + }, + "gateway_session_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Gateway Session Id" + } + }, + "required": [ + "session_id", + "request_id" + ], + "title": "ApprovalRequestParams", + "type": "object" + }, + "ApprovalRespondParams": { + "additionalProperties": false, + "description": "``choice`` is one of the offered ``approval`` choices (once / session / always / deny); ``all``\nresolves every pending approval, ``request_id`` a specific one, neither the oldest.", + "properties": { + "session_id": { + "title": "Session Id", + "type": "string" + }, + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + }, + "choice": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Choice" + }, + "all": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "All" + }, + "request_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Request Id" + } + }, + "required": [ + "session_id" + ], + "title": "ApprovalRespondParams", + "type": "object" + }, + "ApprovalRespondResult": { + "additionalProperties": false, + "properties": { + "resolved": { + "title": "Resolved", + "type": "integer" + } + }, + "required": [ + "resolved" + ], + "title": "ApprovalRespondResult", + "type": "object" + }, + "ApprovalResult": { + "additionalProperties": false, + "properties": { + "choice": { + "$ref": "#/components/schemas/tui_gateway_contracts_server_requests_ApprovalChoice" + }, + "all": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "All" + } + }, + "required": [ + "choice" + ], + "title": "ApprovalResult", + "type": "object" + }, + "ArgumentMode": { + "enum": [ + "options", + "text", + "mixed" + ], + "title": "ArgumentMode", + "type": "string" + }, + "AttachedImageResult": { + "additionalProperties": false, + "description": "``methods_prompt.py::_attached_image_result``: the image is queued for the next turn.", + "properties": { + "name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Name" + }, + "width": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Width" + }, + "height": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Height" + }, + "token_estimate": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Token Estimate" + }, + "attached": { + "title": "Attached", + "type": "boolean" + }, + "path": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Path" + }, + "count": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Count" + }, + "remainder": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Remainder" + }, + "text": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Text" + }, + "bytes": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Bytes" + }, + "message": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Message" + } + }, + "required": [ + "attached" + ], + "title": "AttachedImageResult", + "type": "object" + }, + "AutoContinue": { + "additionalProperties": false, + "description": "A crash-interrupted turn was scheduled to continue right after this resume.", + "properties": { + "attempt": { + "title": "Attempt", + "type": "integer" + }, + "interrupted_at": { + "title": "Interrupted At", + "type": "number" + } + }, + "required": [ + "attempt", + "interrupted_at" + ], + "title": "AutoContinue", + "type": "object" + }, + "AutoReloadCardKind": { + "enum": [ + "canonical", + "distinct", + "none" + ], + "title": "AutoReloadCardKind", + "type": "string" + }, + "BatteryCategory": { + "description": "``agent/battery.py::battery_category`` colour bucket.", + "enum": [ + "good", + "warn", + "bad", + "critical", + "dim" + ], + "title": "BatteryCategory", + "type": "string" + }, + "BillingAutoReload": { + "additionalProperties": false, + "properties": { + "enabled": { + "title": "Enabled", + "type": "boolean" + }, + "threshold_usd": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Threshold Usd" + }, + "threshold_display": { + "title": "Threshold Display", + "type": "string" + }, + "reload_to_usd": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Reload To Usd" + }, + "reload_to_display": { + "title": "Reload To Display", + "type": "string" + }, + "card": { + "anyOf": [ + { + "$ref": "#/components/schemas/BillingAutoReloadCard" + }, + { + "type": "null" + } + ], + "default": null + } + }, + "required": [ + "enabled", + "threshold_display", + "reload_to_display" + ], + "title": "BillingAutoReload", + "type": "object" + }, + "BillingAutoReloadCard": { + "additionalProperties": false, + "description": "Only ``distinct`` carries the payment-method identity.", + "properties": { + "kind": { + "$ref": "#/components/schemas/AutoReloadCardKind" + }, + "payment_method_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Payment Method Id" + }, + "brand": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Brand" + }, + "last4": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Last4" + } + }, + "required": [ + "kind" + ], + "title": "BillingAutoReloadCard", + "type": "object" + }, + "BillingAutoReloadParams": { + "additionalProperties": false, + "properties": { + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + }, + "enabled": { + "default": false, + "title": "Enabled", + "type": "boolean" + }, + "threshold": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Threshold" + }, + "top_up_amount": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Top Up Amount" + } + }, + "title": "BillingAutoReloadParams", + "type": "object" + }, + "BillingBlock": { + "additionalProperties": false, + "description": "``agent/billing_links.py::BillingBlock.to_dict`` (+ ``unverified`` from conversation_loop).", + "properties": { + "provider": { + "title": "Provider", + "type": "string" + }, + "provider_label": { + "title": "Provider Label", + "type": "string" + }, + "model": { + "title": "Model", + "type": "string" + }, + "billing_url": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Billing Url" + }, + "is_nous": { + "title": "Is Nous", + "type": "boolean" + }, + "message": { + "title": "Message", + "type": "string" + }, + "unverified": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Unverified" + } + }, + "required": [ + "provider", + "provider_label", + "model", + "is_nous", + "message" + ], + "title": "BillingBlock", + "type": "object" + }, + "BillingCardInfo": { + "additionalProperties": false, + "properties": { + "brand": { + "title": "Brand", + "type": "string" + }, + "last4": { + "title": "Last4", + "type": "string" + }, + "masked": { + "title": "Masked", + "type": "string" + }, + "display": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Display" + }, + "resolved_via": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Resolved Via" + } + }, + "required": [ + "brand", + "last4", + "masked" + ], + "title": "BillingCardInfo", + "type": "object" + }, + "BillingChargeParams": { + "additionalProperties": false, + "properties": { + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + }, + "amount_usd": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Amount Usd" + }, + "idempotency_key": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Idempotency Key" + } + }, + "title": "BillingChargeParams", + "type": "object" + }, + "BillingChargeResult": { + "additionalProperties": false, + "description": "``202 {chargeId}`` \u2014 money is not confirmed yet; poll ``billing.charge_status``.", + "properties": { + "ok": { + "title": "Ok", + "type": "boolean" + }, + "error": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Error" + }, + "message": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Message" + }, + "portal_url": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Portal Url" + }, + "retry_after": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "number" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Retry After" + }, + "payload": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Payload" + }, + "actor": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Actor" + }, + "code": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Code" + }, + "recovery": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Recovery" + }, + "charge_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Charge Id" + }, + "idempotency_key": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Idempotency Key" + } + }, + "required": [ + "ok" + ], + "title": "BillingChargeResult", + "type": "object" + }, + "BillingChargeStatusParams": { + "additionalProperties": false, + "properties": { + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + }, + "charge_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Charge Id" + } + }, + "title": "BillingChargeStatusParams", + "type": "object" + }, + "BillingChargeStatusResult": { + "additionalProperties": false, + "description": "Single status read (pending | settled | failed); the caller drives the poll cadence.", + "properties": { + "ok": { + "title": "Ok", + "type": "boolean" + }, + "error": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Error" + }, + "message": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Message" + }, + "portal_url": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Portal Url" + }, + "retry_after": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "number" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Retry After" + }, + "payload": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Payload" + }, + "actor": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Actor" + }, + "code": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Code" + }, + "recovery": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Recovery" + }, + "status": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Status" + }, + "amount_usd": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Amount Usd" + }, + "settled_at": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Settled At" + }, + "reason": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Reason" + } + }, + "required": [ + "ok" + ], + "title": "BillingChargeStatusResult", + "type": "object" + }, + "BillingMonthlyCap": { + "additionalProperties": false, + "properties": { + "limit_usd": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Limit Usd" + }, + "limit_display": { + "title": "Limit Display", + "type": "string" + }, + "spent_this_month_usd": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Spent This Month Usd" + }, + "spent_display": { + "title": "Spent Display", + "type": "string" + }, + "is_default_ceiling": { + "title": "Is Default Ceiling", + "type": "boolean" + } + }, + "required": [ + "limit_display", + "spent_display", + "is_default_ceiling" + ], + "title": "BillingMonthlyCap", + "type": "object" + }, + "BillingMutationResult": { + "additionalProperties": false, + "description": "A write with no success payload beyond ``ok``.", + "properties": { + "ok": { + "title": "Ok", + "type": "boolean" + }, + "error": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Error" + }, + "message": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Message" + }, + "portal_url": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Portal Url" + }, + "retry_after": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "number" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Retry After" + }, + "payload": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Payload" + }, + "actor": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Actor" + }, + "code": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Code" + }, + "recovery": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Recovery" + } + }, + "required": [ + "ok" + ], + "title": "BillingMutationResult", + "type": "object" + }, + "BillingPaymentMethod": { + "additionalProperties": false, + "description": "``_serialize_payment_method``: each kind emits only its own fields (a ``card`` never carries\n``email``; ``unknown`` carries what the server called it in ``raw_kind``).", + "properties": { + "kind": { + "$ref": "#/components/schemas/PaymentMethodKind" + }, + "brand": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Brand" + }, + "last4": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Last4" + }, + "wallet": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Wallet" + }, + "email": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Email" + }, + "raw_kind": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Raw Kind" + }, + "resolved_via": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Resolved Via" + } + }, + "required": [ + "kind" + ], + "title": "BillingPaymentMethod", + "type": "object" + }, + "BillingPendingChangeResult": { + "additionalProperties": false, + "description": "``_billing_pending_change``: ``message`` + the raw NAS body in ``payload`` on success.", + "properties": { + "ok": { + "title": "Ok", + "type": "boolean" + }, + "error": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Error" + }, + "message": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Message" + }, + "portal_url": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Portal Url" + }, + "retry_after": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "number" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Retry After" + }, + "payload": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Payload" + }, + "actor": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Actor" + }, + "code": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Code" + }, + "recovery": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Recovery" + } + }, + "required": [ + "ok" + ], + "title": "BillingPendingChangeResult", + "type": "object" + }, + "BillingStateResult": { + "additionalProperties": false, + "description": "``_serialize_billing_state`` (money as strings); the ``except`` fallback emits only\n``ok / logged_in / free_tier / error``, so everything else is optional.", + "properties": { + "ok": { + "title": "Ok", + "type": "boolean" + }, + "logged_in": { + "title": "Logged In", + "type": "boolean" + }, + "free_tier": { + "default": false, + "title": "Free Tier", + "type": "boolean" + }, + "free_tier_model": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Free Tier Model" + }, + "org_name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Org Name" + }, + "org_slug": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Org Slug" + }, + "role": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Role" + }, + "is_admin": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Is Admin" + }, + "can_change_plan": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Can Change Plan" + }, + "can_charge": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Can Charge" + }, + "balance_usd": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Balance Usd" + }, + "balance_display": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Balance Display" + }, + "cli_billing_enabled": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Cli Billing Enabled" + }, + "charge_presets": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Charge Presets" + }, + "charge_presets_display": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Charge Presets Display" + }, + "min_usd": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Min Usd" + }, + "max_usd": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Max Usd" + }, + "card": { + "anyOf": [ + { + "$ref": "#/components/schemas/BillingCardInfo" + }, + { + "type": "null" + } + ], + "default": null + }, + "payment_method": { + "anyOf": [ + { + "$ref": "#/components/schemas/BillingPaymentMethod" + }, + { + "type": "null" + } + ], + "default": null + }, + "monthly_cap": { + "anyOf": [ + { + "$ref": "#/components/schemas/BillingMonthlyCap" + }, + { + "type": "null" + } + ], + "default": null + }, + "auto_reload": { + "anyOf": [ + { + "$ref": "#/components/schemas/BillingAutoReload" + }, + { + "type": "null" + } + ], + "default": null + }, + "portal_url": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Portal Url" + }, + "error": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Error" + }, + "usage": { + "anyOf": [ + { + "$ref": "#/components/schemas/UsageModel" + }, + { + "type": "null" + } + ], + "default": null + } + }, + "required": [ + "ok", + "logged_in" + ], + "title": "BillingStateResult", + "type": "object" + }, + "BillingStepUpParams": { + "additionalProperties": false, + "properties": { + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + }, + "session_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Session Id" + } + }, + "title": "BillingStepUpParams", + "type": "object" + }, + "BillingStepUpResult": { + "additionalProperties": false, + "description": "``granted`` false when the server downscopes (also on every error envelope).", + "properties": { + "ok": { + "title": "Ok", + "type": "boolean" + }, + "error": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Error" + }, + "message": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Message" + }, + "portal_url": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Portal Url" + }, + "retry_after": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "number" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Retry After" + }, + "payload": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Payload" + }, + "actor": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Actor" + }, + "code": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Code" + }, + "recovery": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Recovery" + }, + "granted": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Granted" + } + }, + "required": [ + "ok" + ], + "title": "BillingStepUpResult", + "type": "object" + }, + "BillingStepUpVerificationPayload": { + "additionalProperties": false, + "description": "``methods_session`` billing.step_up on_verification.", + "properties": { + "verification_url": { + "title": "Verification Url", + "type": "string" + }, + "user_code": { + "title": "User Code", + "type": "string" + } + }, + "required": [ + "verification_url", + "user_code" + ], + "title": "BillingStepUpVerificationPayload", + "type": "object" + }, + "BotRelayDeliverParams": { + "additionalProperties": false, + "description": "``profile`` here is the TARGET profile on this gateway (also what the desktop route wrapper adds).", + "properties": { + "profile": { + "title": "Profile", + "type": "string" + }, + "message": { + "title": "Message", + "type": "string" + }, + "from_profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "From Profile" + }, + "from_handle": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "From Handle" + }, + "from_connection": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "From Connection" + } + }, + "required": [ + "profile", + "message" + ], + "title": "BotRelayDeliverParams", + "type": "object" + }, + "BotRelayDeliverResult": { + "additionalProperties": false, + "properties": { + "reply": { + "title": "Reply", + "type": "string" + } + }, + "required": [ + "reply" + ], + "title": "BotRelayDeliverResult", + "type": "object" + }, + "BotRelayOutboxDrainParams": { + "additionalProperties": false, + "properties": { + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + } + }, + "title": "BotRelayOutboxDrainParams", + "type": "object" + }, + "BotRelayOutboxDrainResult": { + "additionalProperties": false, + "properties": { + "envelopes": { + "items": { + "$ref": "#/components/schemas/RelayEnvelope" + }, + "title": "Envelopes", + "type": "array" + } + }, + "required": [ + "envelopes" + ], + "title": "BotRelayOutboxDrainResult", + "type": "object" + }, + "BotRelayReplyParams": { + "additionalProperties": false, + "properties": { + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + }, + "id": { + "title": "Id", + "type": "string" + }, + "reply": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Reply" + }, + "error": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Error" + }, + "reason": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Reason" + } + }, + "required": [ + "id" + ], + "title": "BotRelayReplyParams", + "type": "object" + }, + "BotRelayRosterSyncParams": { + "additionalProperties": false, + "properties": { + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + }, + "agents": { + "anyOf": [ + { + "items": { + "$ref": "#/components/schemas/RelayAgentRow" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Agents" + } + }, + "title": "BotRelayRosterSyncParams", + "type": "object" + }, + "BotRelayRosterSyncResult": { + "additionalProperties": false, + "properties": { + "count": { + "title": "Count", + "type": "integer" + } + }, + "required": [ + "count" + ], + "title": "BotRelayRosterSyncResult", + "type": "object" + }, + "BrowserAction": { + "enum": [ + "status", + "connect", + "disconnect" + ], + "title": "BrowserAction", + "type": "string" + }, + "BrowserControllerCancelPayload": { + "additionalProperties": false, + "description": "``gateway/browser_control_broker.py::_cancel_frame``.", + "properties": { + "command_id": { + "title": "Command Id", + "type": "string" + }, + "tool_call_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Tool Call Id" + } + }, + "required": [ + "command_id" + ], + "title": "BrowserControllerCancelPayload", + "type": "object" + }, + "BrowserControllerCommandPayload": { + "additionalProperties": false, + "description": "``gateway/browser_control_broker.py`` FRAME_COMMAND params.", + "properties": { + "command_id": { + "title": "Command Id", + "type": "string" + }, + "action": { + "title": "Action", + "type": "string" + }, + "arguments": { + "additionalProperties": true, + "title": "Arguments", + "type": "object" + }, + "controller_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Controller Id" + }, + "browser_profile_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Browser Profile Id" + }, + "tool_call_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Tool Call Id" + } + }, + "required": [ + "command_id", + "action", + "arguments" + ], + "title": "BrowserControllerCommandPayload", + "type": "object" + }, + "BrowserControllerDetachResult": { + "additionalProperties": false, + "properties": { + "detached": { + "default": true, + "title": "Detached", + "type": "boolean" + } + }, + "title": "BrowserControllerDetachResult", + "type": "object" + }, + "BrowserControllerParams": { + "additionalProperties": false, + "description": "Every controller call names the session the controller is attached to.", + "properties": { + "session_id": { + "title": "Session Id", + "type": "string" + } + }, + "required": [ + "session_id" + ], + "title": "BrowserControllerParams", + "type": "object" + }, + "BrowserControllerRegisterParams": { + "additionalProperties": false, + "properties": { + "session_id": { + "title": "Session Id", + "type": "string" + }, + "controller_id": { + "title": "Controller Id", + "type": "string" + }, + "browser_profile_id": { + "title": "Browser Profile Id", + "type": "string" + }, + "capabilities": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Capabilities" + }, + "protocol_version": { + "anyOf": [ + {}, + { + "type": "null" + } + ], + "default": null, + "title": "Protocol Version" + }, + "principal_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Principal Id" + } + }, + "required": [ + "session_id", + "controller_id", + "browser_profile_id" + ], + "title": "BrowserControllerRegisterParams", + "type": "object" + }, + "BrowserControllerRegisterResult": { + "additionalProperties": false, + "properties": { + "scope": { + "$ref": "#/components/schemas/ControllerScope" + } + }, + "required": [ + "scope" + ], + "title": "BrowserControllerRegisterResult", + "type": "object" + }, + "BrowserControllerResultParams": { + "additionalProperties": false, + "properties": { + "session_id": { + "title": "Session Id", + "type": "string" + }, + "command_id": { + "title": "Command Id", + "type": "string" + }, + "ok": { + "anyOf": [ + {}, + { + "type": "null" + } + ], + "default": null, + "title": "Ok" + }, + "result": { + "anyOf": [ + {}, + { + "type": "null" + } + ], + "default": null, + "title": "Result" + }, + "error": { + "anyOf": [ + {}, + { + "type": "null" + } + ], + "default": null, + "title": "Error" + } + }, + "required": [ + "session_id", + "command_id" + ], + "title": "BrowserControllerResultParams", + "type": "object" + }, + "BrowserControllerResultResult": { + "additionalProperties": false, + "properties": { + "accepted": { + "title": "Accepted", + "type": "boolean" + } + }, + "required": [ + "accepted" + ], + "title": "BrowserControllerResultResult", + "type": "object" + }, + "BrowserManageParams": { + "additionalProperties": false, + "properties": { + "action": { + "$ref": "#/components/schemas/BrowserAction", + "default": "status" + }, + "url": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Url" + }, + "session_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Session Id" + }, + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + } + }, + "title": "BrowserManageParams", + "type": "object" + }, + "BrowserManageResult": { + "additionalProperties": false, + "properties": { + "connected": { + "title": "Connected", + "type": "boolean" + }, + "url": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Url" + }, + "messages": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Messages" + } + }, + "required": [ + "connected" + ], + "title": "BrowserManageResult", + "type": "object" + }, + "BrowserProgressPayload": { + "additionalProperties": false, + "description": "``methods_browser`` announce(); ``level``: info | warn | error.", + "properties": { + "message": { + "title": "Message", + "type": "string" + }, + "level": { + "title": "Level", + "type": "string" + } + }, + "required": [ + "message", + "level" + ], + "title": "BrowserProgressPayload", + "type": "object" + }, + "CapabilityEntry": { + "additionalProperties": false, + "properties": { + "name": { + "title": "Name", + "type": "string" + }, + "enabled": { + "default": true, + "title": "Enabled", + "type": "boolean" + } + }, + "required": [ + "name" + ], + "title": "CapabilityEntry", + "type": "object" + }, + "ChangeSignalPayload": { + "additionalProperties": true, + "description": "``change_watcher._CHANGE_WATCHES`` payload fn \u2014 ``{}`` for every watch except pet.changed.", + "properties": {}, + "title": "ChangeSignalPayload", + "type": "object" + }, + "ClarifyLockParams": { + "additionalProperties": false, + "properties": { + "request_id": { + "title": "Request Id", + "type": "string" + }, + "question_id": { + "title": "Question Id", + "type": "string" + }, + "answer": { + "default": "", + "title": "Answer" + }, + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + } + }, + "required": [ + "request_id", + "question_id" + ], + "title": "ClarifyLockParams", + "type": "object" + }, + "ClarifyLockResult": { + "additionalProperties": false, + "description": "``remaining`` lists the qids still unanswered; the lock that empties it resolves the request.\n``expired``: the wait already ended (timeout / cancel) \u2014 not an error.", + "properties": { + "status": { + "$ref": "#/components/schemas/ClarifyLockStatus" + }, + "remaining": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Remaining" + } + }, + "required": [ + "status" + ], + "title": "ClarifyLockResult", + "type": "object" + }, + "ClarifyLockStatus": { + "enum": [ + "ok", + "expired" + ], + "title": "ClarifyLockStatus", + "type": "string" + }, + "ClarifyQuestion": { + "additionalProperties": false, + "properties": { + "qid": { + "title": "Qid", + "type": "string" + }, + "question": { + "title": "Question", + "type": "string" + }, + "choices": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Choices" + }, + "multi_select": { + "default": false, + "title": "Multi Select", + "type": "boolean" + } + }, + "required": [ + "qid", + "question" + ], + "title": "ClarifyQuestion", + "type": "object" + }, + "ClarifyRequestParams": { + "additionalProperties": false, + "description": "Single question: ``question`` / ``choices`` (/ ``multi_select``); batch: ``questions``.\n``answers`` rides only on a reconnect replay (locks the server already accepted).", + "properties": { + "session_id": { + "title": "Session Id", + "type": "string" + }, + "question": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Question" + }, + "choices": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Choices" + }, + "multi_select": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Multi Select" + }, + "questions": { + "anyOf": [ + { + "items": { + "$ref": "#/components/schemas/ClarifyQuestion" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Questions" + }, + "answers": { + "anyOf": [ + { + "additionalProperties": { + "type": "string" + }, + "type": "object" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Answers" + } + }, + "required": [ + "session_id" + ], + "title": "ClarifyRequestParams", + "type": "object" + }, + "ClarifyResult": { + "additionalProperties": false, + "description": "Single: ``{answer}`` ('' = skip). Batch: ``{answers}`` for the whole set (early locks go through\nthe ``clarify.lock`` RPC); a response with neither is cancel-all.", + "properties": { + "answer": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Answer" + }, + "answers": { + "anyOf": [ + { + "additionalProperties": { + "type": "string" + }, + "type": "object" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Answers" + } + }, + "title": "ClarifyResult", + "type": "object" + }, + "CliExecParams": { + "additionalProperties": false, + "properties": { + "argv": { + "items": { + "type": "string" + }, + "title": "Argv", + "type": "array" + }, + "timeout": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Timeout" + }, + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + } + }, + "required": [ + "argv" + ], + "title": "CliExecParams", + "type": "object" + }, + "CliExecResult": { + "additionalProperties": false, + "properties": { + "blocked": { + "title": "Blocked", + "type": "boolean" + }, + "code": { + "title": "Code", + "type": "integer" + }, + "output": { + "title": "Output", + "type": "string" + }, + "hint": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Hint" + } + }, + "required": [ + "blocked", + "code", + "output" + ], + "title": "CliExecResult", + "type": "object" + }, + "ClipboardPasteParams": { + "additionalProperties": false, + "properties": { + "session_id": { + "title": "Session Id", + "type": "string" + }, + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + } + }, + "required": [ + "session_id" + ], + "title": "ClipboardPasteParams", + "type": "object" + }, + "CommandCatalogMeta": { + "additionalProperties": false, + "properties": { + "argument_mode": { + "anyOf": [ + { + "$ref": "#/components/schemas/ArgumentMode" + }, + { + "type": "null" + } + ], + "default": null + }, + "desktop": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Desktop" + } + }, + "title": "CommandCatalogMeta", + "type": "object" + }, + "CommandCategory": { + "additionalProperties": false, + "properties": { + "name": { + "title": "Name", + "type": "string" + }, + "pairs": { + "items": { + "items": { + "type": "string" + }, + "type": "array" + }, + "title": "Pairs", + "type": "array" + } + }, + "required": [ + "name" + ], + "title": "CommandCategory", + "type": "object" + }, + "CommandDispatchParams": { + "additionalProperties": false, + "properties": { + "name": { + "title": "Name", + "type": "string" + }, + "arg": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Arg" + }, + "session_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Session Id" + }, + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + } + }, + "required": [ + "name" + ], + "title": "CommandDispatchParams", + "type": "object" + }, + "CommandDispatchResult": { + "additionalProperties": false, + "description": "One structured directive: ``exec``/``plugin`` carry ``output``; ``alias`` a ``target``;\n``send``/``prefill``/``skill`` a ``message`` (UIs render ``display``, never ``message``).", + "properties": { + "type": { + "$ref": "#/components/schemas/DispatchType" + }, + "output": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Output" + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Target" + }, + "message": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Message" + }, + "notice": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Notice" + }, + "display": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Display" + }, + "name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Name" + }, + "status": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Status" + } + }, + "required": [ + "type" + ], + "title": "CommandDispatchResult", + "type": "object" + }, + "CommandResolveParams": { + "additionalProperties": false, + "properties": { + "name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Name" + }, + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + } + }, + "title": "CommandResolveParams", + "type": "object" + }, + "CommandResolveResult": { + "additionalProperties": false, + "properties": { + "canonical": { + "title": "Canonical", + "type": "string" + }, + "description": { + "title": "Description", + "type": "string" + }, + "category": { + "title": "Category", + "type": "string" + } + }, + "required": [ + "canonical", + "description", + "category" + ], + "title": "CommandResolveResult", + "type": "object" + }, + "CommandsCatalogParams": { + "additionalProperties": false, + "properties": { + "session_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Session Id" + }, + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + } + }, + "title": "CommandsCatalogParams", + "type": "object" + }, + "CommandsCatalogResult": { + "additionalProperties": false, + "properties": { + "pairs": { + "items": { + "items": { + "type": "string" + }, + "type": "array" + }, + "title": "Pairs", + "type": "array" + }, + "sub": { + "additionalProperties": { + "items": { + "type": "string" + }, + "type": "array" + }, + "title": "Sub", + "type": "object" + }, + "canon": { + "additionalProperties": { + "type": "string" + }, + "title": "Canon", + "type": "object" + }, + "commands": { + "additionalProperties": { + "$ref": "#/components/schemas/CommandCatalogMeta" + }, + "title": "Commands", + "type": "object" + }, + "categories": { + "items": { + "$ref": "#/components/schemas/CommandCategory" + }, + "title": "Categories", + "type": "array" + }, + "skills": { + "additionalProperties": { + "$ref": "#/components/schemas/SkillCatalogEntry" + }, + "title": "Skills", + "type": "object" + }, + "skill_count": { + "default": 0, + "title": "Skill Count", + "type": "integer" + }, + "warning": { + "default": "", + "title": "Warning", + "type": "string" + } + }, + "title": "CommandsCatalogResult", + "type": "object" + }, + "CompletePathParams": { + "additionalProperties": false, + "description": "``word`` is the token under the cursor (``@`` prefix = context reference); ``cwd`` /\n``session_id`` pick the directory the listing resolves against.", + "properties": { + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + }, + "word": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Word" + }, + "cwd": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Cwd" + }, + "session_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Session Id" + } + }, + "title": "CompletePathParams", + "type": "object" + }, + "CompleteSlashParams": { + "additionalProperties": false, + "properties": { + "text": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Text" + } + }, + "title": "CompleteSlashParams", + "type": "object" + }, + "CompleteSlashResult": { + "additionalProperties": false, + "description": "``replace_from`` is the column the accepted item replaces from.", + "properties": { + "items": { + "items": { + "$ref": "#/components/schemas/CompletionItem" + }, + "title": "Items", + "type": "array" + }, + "replace_from": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Replace From" + } + }, + "title": "CompleteSlashResult", + "type": "object" + }, + "CompletionItem": { + "additionalProperties": false, + "description": "One popover row; ``kind`` rides only on slash completions (command vs skill).", + "properties": { + "text": { + "title": "Text", + "type": "string" + }, + "display": { + "default": "", + "title": "Display", + "type": "string" + }, + "meta": { + "default": "", + "title": "Meta", + "type": "string" + }, + "kind": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Kind" + } + }, + "required": [ + "text" + ], + "title": "CompletionItem", + "type": "object" + }, + "CompletionItemsResult": { + "additionalProperties": false, + "properties": { + "items": { + "items": { + "$ref": "#/components/schemas/CompletionItem" + }, + "title": "Items", + "type": "array" + } + }, + "title": "CompletionItemsResult", + "type": "object" + }, + "CompressionSummary": { + "additionalProperties": true, + "description": "``agent.manual_compression_feedback.summarize_manual_compression``.", + "properties": { + "noop": { + "default": false, + "title": "Noop", + "type": "boolean" + }, + "aborted": { + "default": false, + "title": "Aborted", + "type": "boolean" + }, + "refused_would_grow": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Refused Would Grow" + }, + "fallback_used": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Fallback Used" + }, + "headline": { + "default": "", + "title": "Headline", + "type": "string" + }, + "token_line": { + "default": "", + "title": "Token Line", + "type": "string" + }, + "note": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Note" + } + }, + "title": "CompressionSummary", + "type": "object" + }, + "ConfigGetParams": { + "additionalProperties": false, + "description": "``key`` selects one getter from ``_CONFIG_GETTERS``; ``cwd`` feeds the ``project`` getter,\n``session_id`` lets ``reasoning`` / ``fast`` answer with the session's live pin.", + "properties": { + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + }, + "key": { + "title": "Key", + "type": "string" + }, + "cwd": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Cwd" + }, + "session_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Session Id" + } + }, + "required": [ + "key" + ], + "title": "ConfigGetParams", + "type": "object" + }, + "ConfigGetResult": { + "additionalProperties": false, + "description": "Union of every getter's payload: ``value`` for the simple words, ``config`` for ``full``,\n``mtime`` / ``mcp_rev`` for the poller, ``model`` / ``provider`` / ``providers`` for ``provider``,\n``home`` / ``display`` for ``profile``, ``cwd`` / ``branch`` for ``project``, ``prompt``.", + "properties": { + "value": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Value" + }, + "display": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Display" + }, + "tool_progress": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Tool Progress" + }, + "model": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Model" + }, + "provider": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Provider" + }, + "providers": { + "anyOf": [ + { + "items": { + "$ref": "#/components/schemas/ConfigProviderRef" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Providers" + }, + "home": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Home" + }, + "cwd": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Cwd" + }, + "branch": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Branch" + }, + "config": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Config" + }, + "prompt": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Prompt" + }, + "mtime": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Mtime" + }, + "mcp_rev": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Mcp Rev" + } + }, + "title": "ConfigGetResult", + "type": "object" + }, + "ConfigProviderRef": { + "additionalProperties": true, + "description": "``hermes_cli/models.py::list_available_providers`` row.", + "properties": { + "id": { + "title": "Id", + "type": "string" + }, + "label": { + "title": "Label", + "type": "string" + }, + "aliases": { + "items": { + "type": "string" + }, + "title": "Aliases", + "type": "array" + }, + "authenticated": { + "default": false, + "title": "Authenticated", + "type": "boolean" + } + }, + "required": [ + "id", + "label" + ], + "title": "ConfigProviderRef", + "type": "object" + }, + "ConfigSection": { + "additionalProperties": false, + "properties": { + "title": { + "title": "Title", + "type": "string" + }, + "rows": { + "items": { + "items": { + "type": "string" + }, + "type": "array" + }, + "title": "Rows", + "type": "array" + } + }, + "required": [ + "title" + ], + "title": "ConfigSection", + "type": "object" + }, + "ConfigSetParams": { + "additionalProperties": false, + "description": "``key`` picks the setter (``_CONFIG_SETTERS``, ``details_mode.
``, display toggles);\n``value`` is the raw word/string the setter normalises (falsy non-strings are reported back in\nthe error). ``scope`` applies to ``yolo`` / ``reasoning``; ``confirm_expensive_model`` to ``model``.", + "properties": { + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + }, + "key": { + "title": "Key", + "type": "string" + }, + "value": { + "default": "", + "title": "Value" + }, + "session_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Session Id" + }, + "scope": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Scope" + }, + "confirm_expensive_model": { + "default": false, + "title": "Confirm Expensive Model", + "type": "boolean" + } + }, + "required": [ + "key" + ], + "title": "ConfigSetParams", + "type": "object" + }, + "ConfigSetResult": { + "additionalProperties": false, + "description": "``{key, value}`` plus the setter's extras: model switches add ``warning`` /\n``confirm_required`` / ``confirm_message`` / ``scope`` / ``deferred``; ``focus`` adds\n``tool_progress``; ``cwd`` adds ``cwd`` / ``branch``; ``personality`` adds ``history_reset`` /\n``info``; ``yolo`` reports its ``scope``. ``value`` is a bool only for the display toggles.", + "properties": { + "key": { + "title": "Key", + "type": "string" + }, + "value": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Value" + }, + "warning": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Warning" + }, + "confirm_required": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Confirm Required" + }, + "confirm_message": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Confirm Message" + }, + "scope": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Scope" + }, + "deferred": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Deferred" + }, + "tool_progress": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Tool Progress" + }, + "cwd": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Cwd" + }, + "branch": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Branch" + }, + "history_reset": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "History Reset" + }, + "info": { + "anyOf": [ + { + "$ref": "#/components/schemas/SessionLiveInfo" + }, + { + "type": "null" + } + ], + "default": null + } + }, + "required": [ + "key" + ], + "title": "ConfigSetResult", + "type": "object" + }, + "ConfigShowParams": { + "additionalProperties": false, + "properties": { + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + } + }, + "title": "ConfigShowParams", + "type": "object" + }, + "ConfigShowResult": { + "additionalProperties": true, + "properties": { + "sections": { + "items": { + "$ref": "#/components/schemas/ConfigSection" + }, + "title": "Sections", + "type": "array" + } + }, + "title": "ConfigShowResult", + "type": "object" + }, + "ConnectorConnectEntry": { + "additionalProperties": true, + "description": "``tools/connections_tool.py`` per-connector authorization outcome.", + "properties": { + "connector": { + "default": "", + "title": "Connector", + "type": "string" + }, + "status": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Status" + }, + "connect_url": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Connect Url" + }, + "note": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Note" + }, + "instruction": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Instruction" + } + }, + "title": "ConnectorConnectEntry", + "type": "object" + }, + "ConnectorRow": { + "additionalProperties": true, + "description": "One ``manage_connections`` status entry after ``connector_ui_payload`` redaction; the\nconnector service owns the closed key set, so unknown metadata passes through.", + "properties": { + "connector": { + "default": "", + "title": "Connector", + "type": "string" + }, + "connected": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Connected" + }, + "enabled": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Enabled" + }, + "connectionStatus": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Connectionstatus" + }, + "name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Name" + }, + "description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Description" + } + }, + "title": "ConnectorRow", + "type": "object" + }, + "ConnectorsConnectParams": { + "additionalProperties": false, + "properties": { + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + }, + "session_id": { + "title": "Session Id", + "type": "string" + }, + "connectors": { + "items": { + "type": "string" + }, + "title": "Connectors", + "type": "array" + }, + "reconnect": { + "default": false, + "title": "Reconnect", + "type": "boolean" + } + }, + "required": [ + "session_id", + "connectors" + ], + "title": "ConnectorsConnectParams", + "type": "object" + }, + "ConnectorsConnectResult": { + "additionalProperties": false, + "properties": { + "results": { + "items": { + "$ref": "#/components/schemas/ConnectorConnectEntry" + }, + "title": "Results", + "type": "array" + }, + "summary": { + "additionalProperties": true, + "title": "Summary", + "type": "object" + } + }, + "required": [ + "results", + "summary" + ], + "title": "ConnectorsConnectResult", + "type": "object" + }, + "ConnectorsListParams": { + "additionalProperties": false, + "properties": { + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + }, + "session_id": { + "title": "Session Id", + "type": "string" + } + }, + "required": [ + "session_id" + ], + "title": "ConnectorsListParams", + "type": "object" + }, + "ConnectorsListResult": { + "additionalProperties": false, + "properties": { + "available": { + "title": "Available", + "type": "boolean" + }, + "connectors": { + "items": { + "$ref": "#/components/schemas/ConnectorRow" + }, + "title": "Connectors", + "type": "array" + } + }, + "required": [ + "available", + "connectors" + ], + "title": "ConnectorsListResult", + "type": "object" + }, + "ContextCategory": { + "additionalProperties": false, + "properties": { + "color": { + "title": "Color", + "type": "string" + }, + "id": { + "title": "Id", + "type": "string" + }, + "label": { + "title": "Label", + "type": "string" + }, + "tokens": { + "title": "Tokens", + "type": "integer" + } + }, + "required": [ + "color", + "id", + "label", + "tokens" + ], + "title": "ContextCategory", + "type": "object" + }, + "ControllerScope": { + "additionalProperties": false, + "properties": { + "principal_id": { + "title": "Principal Id", + "type": "string" + }, + "profile_id": { + "title": "Profile Id", + "type": "string" + }, + "session_id": { + "title": "Session Id", + "type": "string" + }, + "controller_id": { + "title": "Controller Id", + "type": "string" + }, + "browser_profile_id": { + "title": "Browser Profile Id", + "type": "string" + }, + "transport_family": { + "title": "Transport Family", + "type": "string" + }, + "capabilities": { + "items": { + "type": "string" + }, + "title": "Capabilities", + "type": "array" + } + }, + "required": [ + "principal_id", + "profile_id", + "session_id", + "controller_id", + "browser_profile_id", + "transport_family", + "capabilities" + ], + "title": "ControllerScope", + "type": "object" + }, + "CorrectionStatus": { + "enum": [ + "queued", + "redirected", + "rejected" + ], + "title": "CorrectionStatus", + "type": "string" + }, + "CronAction": { + "enum": [ + "list", + "add", + "remove", + "pause", + "resume" + ], + "title": "CronAction", + "type": "string" + }, + "CronJobRow": { + "additionalProperties": true, + "description": "``tools/cronjob_job_args.py::_format_job``.", + "properties": { + "job_id": { + "title": "Job Id", + "type": "string" + }, + "name": { + "default": "", + "title": "Name", + "type": "string" + }, + "skill": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Skill" + }, + "skills": { + "items": { + "type": "string" + }, + "title": "Skills", + "type": "array" + }, + "prompt_preview": { + "default": "", + "title": "Prompt Preview", + "type": "string" + }, + "model": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Model" + }, + "provider": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Provider" + }, + "base_url": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Base Url" + }, + "schedule": { + "default": "?", + "title": "Schedule", + "type": "string" + }, + "repeat": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Repeat" + }, + "deliver": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Deliver" + }, + "next_run_at": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Next Run At" + }, + "last_run_at": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Last Run At" + }, + "last_status": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Last Status" + }, + "last_delivery_error": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Last Delivery Error" + }, + "last_delivery_unverified": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Last Delivery Unverified" + }, + "last_fire_error": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Last Fire Error" + }, + "last_error": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Last Error" + }, + "enabled": { + "default": true, + "title": "Enabled", + "type": "boolean" + }, + "state": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "State" + }, + "paused_at": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Paused At" + }, + "paused_reason": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Paused Reason" + }, + "workdir": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Workdir" + }, + "script": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Script" + }, + "reasoning_effort": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Reasoning Effort" + }, + "monitor_script": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Monitor Script" + }, + "monitor_url": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Monitor Url" + }, + "monitor_state": { + "anyOf": [ + {}, + { + "type": "null" + } + ], + "default": null, + "title": "Monitor State" + }, + "no_agent": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "No Agent" + }, + "enabled_toolsets": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Enabled Toolsets" + }, + "continuity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Continuity" + }, + "context_from": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Context From" + }, + "attach_to_session": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Attach To Session" + } + }, + "required": [ + "job_id" + ], + "title": "CronJobRow", + "type": "object" + }, + "CronManageParams": { + "additionalProperties": false, + "properties": { + "action": { + "$ref": "#/components/schemas/CronAction", + "default": "list" + }, + "name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Name" + }, + "include_disabled": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Include Disabled" + }, + "schedule": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Schedule" + }, + "prompt": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Prompt" + }, + "repeat": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Repeat" + }, + "continuity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Continuity" + }, + "deliver": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Deliver" + }, + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + } + }, + "title": "CronManageParams", + "type": "object" + }, + "CronManageResult": { + "additionalProperties": true, + "description": "Pass-through of ``tools/cronjob_tools.py::cronjob`` JSON: ``list`` \u2192 ``jobs``/``count``\n(+ ``scoped`` when profile-scoped); ``add`` \u2192 the created job's summary + ``job``; ``remove`` \u2192\n``removed_job``; ``pause``/``resume`` \u2192 ``job``. A tool-level failure lands in ``error``.", + "properties": { + "success": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Success" + }, + "error": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Error" + }, + "count": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Count" + }, + "jobs": { + "anyOf": [ + { + "items": { + "$ref": "#/components/schemas/CronJobRow" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Jobs" + }, + "scoped": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Scoped" + }, + "gateway_running": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Gateway Running" + }, + "warning": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Warning" + }, + "job_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Job Id" + }, + "name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Name" + }, + "skill": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Skill" + }, + "skills": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Skills" + }, + "schedule": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Schedule" + }, + "repeat": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Repeat" + }, + "deliver": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Deliver" + }, + "next_run_at": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Next Run At" + }, + "job": { + "anyOf": [ + { + "$ref": "#/components/schemas/CronJobRow" + }, + { + "type": "null" + } + ], + "default": null + }, + "message": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Message" + }, + "guidance": { + "anyOf": [ + {}, + { + "type": "null" + } + ], + "default": null, + "title": "Guidance" + }, + "removed_job": { + "anyOf": [ + { + "$ref": "#/components/schemas/CronRemovedJob" + }, + { + "type": "null" + } + ], + "default": null + } + }, + "title": "CronManageResult", + "type": "object" + }, + "CronRemovedJob": { + "additionalProperties": false, + "properties": { + "id": { + "title": "Id", + "type": "string" + }, + "name": { + "default": "", + "title": "Name", + "type": "string" + }, + "schedule": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Schedule" + } + }, + "required": [ + "id" + ], + "title": "CronRemovedJob", + "type": "object" + }, + "CurrentSubscription": { + "additionalProperties": false, + "properties": { + "tier_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Tier Id" + }, + "tier_name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Tier Name" + }, + "monthly_credits": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Monthly Credits" + }, + "credits_remaining": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Credits Remaining" + }, + "cycle_ends_at": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Cycle Ends At" + }, + "pending_downgrade_tier_name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Pending Downgrade Tier Name" + }, + "pending_downgrade_at": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Pending Downgrade At" + }, + "pending_downgrade_display": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Pending Downgrade Display" + }, + "cancel_at_period_end": { + "title": "Cancel At Period End", + "type": "boolean" + }, + "cancellation_effective_at": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Cancellation Effective At" + }, + "cancellation_effective_display": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Cancellation Effective Display" + } + }, + "required": [ + "cancel_at_period_end" + ], + "title": "CurrentSubscription", + "type": "object" + }, + "DelegationPauseParams": { + "additionalProperties": false, + "properties": { + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + }, + "paused": { + "default": true, + "title": "Paused", + "type": "boolean" + } + }, + "title": "DelegationPauseParams", + "type": "object" + }, + "DelegationPauseResult": { + "additionalProperties": false, + "properties": { + "paused": { + "title": "Paused", + "type": "boolean" + } + }, + "required": [ + "paused" + ], + "title": "DelegationPauseResult", + "type": "object" + }, + "DelegationStatusResult": { + "additionalProperties": false, + "properties": { + "active": { + "items": { + "$ref": "#/components/schemas/ActiveSubagent" + }, + "title": "Active", + "type": "array" + }, + "paused": { + "title": "Paused", + "type": "boolean" + }, + "max_spawn_depth": { + "title": "Max Spawn Depth", + "type": "integer" + }, + "max_concurrent_children": { + "title": "Max Concurrent Children", + "type": "integer" + } + }, + "required": [ + "active", + "paused", + "max_spawn_depth", + "max_concurrent_children" + ], + "title": "DelegationStatusResult", + "type": "object" + }, + "DiagnosticsShareNousParams": { + "additionalProperties": false, + "properties": { + "error_context": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Error Context" + }, + "extra_files": { + "anyOf": [ + { + "additionalProperties": { + "type": "string" + }, + "type": "object" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Extra Files" + }, + "log_lines": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Log Lines" + } + }, + "title": "DiagnosticsShareNousParams", + "type": "object" + }, + "DiagnosticsShareNousResult": { + "additionalProperties": false, + "description": "Structured envelope: ``ok=False`` + ``error`` renders inline instead of failing the RPC.", + "properties": { + "ok": { + "title": "Ok", + "type": "boolean" + }, + "view_url": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "View Url" + }, + "upload_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Upload Id" + }, + "expires_at": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Expires At" + }, + "error": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Error" + } + }, + "required": [ + "ok" + ], + "title": "DiagnosticsShareNousResult", + "type": "object" + }, + "DiscoveredRepo": { + "additionalProperties": false, + "description": "``methods_projects._discover_repos_payload`` row: a git root with session totals.", + "properties": { + "root": { + "title": "Root", + "type": "string" + }, + "label": { + "default": "", + "title": "Label", + "type": "string" + }, + "sessions": { + "default": 0, + "title": "Sessions", + "type": "integer" + }, + "last_active": { + "default": 0.0, + "title": "Last Active", + "type": "number" + } + }, + "required": [ + "root" + ], + "title": "DiscoveredRepo", + "type": "object" + }, + "DispatchType": { + "description": "``apps/shared/src/slash.ts::parseCommandDispatch`` branches on this.", + "enum": [ + "exec", + "alias", + "plugin", + "send", + "skill", + "prefill" + ], + "title": "DispatchType", + "type": "string" + }, + "EmptyRequestParams": { + "additionalProperties": false, + "properties": { + "session_id": { + "title": "Session Id", + "type": "string" + } + }, + "required": [ + "session_id" + ], + "title": "EmptyRequestParams", + "type": "object" + }, + "ErrorPayload": { + "additionalProperties": false, + "description": "Every ``_emit(\"error\", \u2026)`` site sets exactly ``message``.", + "properties": { + "message": { + "title": "Message", + "type": "string" + } + }, + "required": [ + "message" + ], + "title": "ErrorPayload", + "type": "object" + }, + "ErrorSurface": { + "additionalProperties": true, + "description": "``agent/error_surface.py::_surface`` \u2014 advisory {layer, code, retryable} (+ identity, + auth hint).", + "properties": { + "layer": { + "title": "Layer", + "type": "string" + }, + "code": { + "title": "Code", + "type": "string" + }, + "retryable": { + "title": "Retryable", + "type": "boolean" + }, + "provider": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Provider" + }, + "model": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Model" + } + }, + "required": [ + "layer", + "code", + "retryable" + ], + "title": "ErrorSurface", + "type": "object" + }, + "FileAttachParams": { + "additionalProperties": false, + "description": "``path`` when the file is gateway-visible, else ``data_url`` carries the bytes; ``name`` labels\nan uploaded file.", + "properties": { + "session_id": { + "title": "Session Id", + "type": "string" + }, + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + }, + "path": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Path" + }, + "data_url": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Data Url" + }, + "name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Name" + } + }, + "required": [ + "session_id" + ], + "title": "FileAttachParams", + "type": "object" + }, + "FileAttachResult": { + "additionalProperties": false, + "properties": { + "attached": { + "title": "Attached", + "type": "boolean" + }, + "name": { + "title": "Name", + "type": "string" + }, + "path": { + "title": "Path", + "type": "string" + }, + "ref_path": { + "title": "Ref Path", + "type": "string" + }, + "ref_text": { + "title": "Ref Text", + "type": "string" + }, + "uploaded": { + "title": "Uploaded", + "type": "boolean" + } + }, + "required": [ + "attached", + "name", + "path", + "ref_path", + "ref_text", + "uploaded" + ], + "title": "FileAttachResult", + "type": "object" + }, + "ForeignSessionRow": { + "additionalProperties": false, + "description": "``hermes_cli/foreign_sessions_browser.py::list_foreign_sessions`` \u2014 ``id`` is an opaque\nhandle, never a path.", + "properties": { + "id": { + "title": "Id", + "type": "string" + }, + "source": { + "$ref": "#/components/schemas/ForeignSource" + }, + "label": { + "title": "Label", + "type": "string" + }, + "title": { + "default": "", + "title": "Title", + "type": "string" + }, + "cwd": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Cwd" + }, + "mtime": { + "title": "Mtime", + "type": "number" + }, + "turn_count": { + "default": 0, + "title": "Turn Count", + "type": "integer" + }, + "excerpt": { + "default": "", + "title": "Excerpt", + "type": "string" + } + }, + "required": [ + "id", + "source", + "label", + "mtime" + ], + "title": "ForeignSessionRow", + "type": "object" + }, + "ForeignSource": { + "enum": [ + "claude", + "codex" + ], + "title": "ForeignSource", + "type": "string" + }, + "ForeignTurn": { + "additionalProperties": false, + "properties": { + "role": { + "title": "Role", + "type": "string" + }, + "content": { + "title": "Content", + "type": "string" + } + }, + "required": [ + "role", + "content" + ], + "title": "ForeignTurn", + "type": "object" + }, + "FreeTierAckNoticeResult": { + "additionalProperties": false, + "properties": { + "acked": { + "title": "Acked", + "type": "boolean" + } + }, + "required": [ + "acked" + ], + "title": "FreeTierAckNoticeResult", + "type": "object" + }, + "FreeTierProvisionResult": { + "additionalProperties": false, + "properties": { + "has_guest": { + "title": "Has Guest", + "type": "boolean" + }, + "enabled": { + "title": "Enabled", + "type": "boolean" + }, + "error": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Error" + } + }, + "required": [ + "has_guest", + "enabled" + ], + "title": "FreeTierProvisionResult", + "type": "object" + }, + "FreeTierStatusResult": { + "additionalProperties": false, + "description": "``available`` = an identity exists AND the tier is on; whether inference runs on it is\n``setup.runtime_check.free_tier``'s question.", + "properties": { + "has_guest": { + "title": "Has Guest", + "type": "boolean" + }, + "enabled": { + "title": "Enabled", + "type": "boolean" + }, + "available": { + "title": "Available", + "type": "boolean" + }, + "notice_pending": { + "title": "Notice Pending", + "type": "boolean" + }, + "model": { + "title": "Model", + "type": "string" + }, + "label": { + "title": "Label", + "type": "string" + } + }, + "required": [ + "has_guest", + "enabled", + "available", + "notice_pending", + "model", + "label" + ], + "title": "FreeTierStatusResult", + "type": "object" + }, + "GatewayCapabilitiesResult": { + "additionalProperties": false, + "properties": { + "per_session_exclusive_submit": { + "title": "Per Session Exclusive Submit", + "type": "boolean" + } + }, + "required": [ + "per_session_exclusive_submit" + ], + "title": "GatewayCapabilitiesResult", + "type": "object" + }, + "GatewayReadyPayload": { + "additionalProperties": false, + "description": "``tui_gateway/entry.py`` (stdio) / ``tui_gateway/ws.py`` (WebSocket) first frame.", + "properties": { + "skin": { + "$ref": "#/components/schemas/SkinPayload" + }, + "change_events": { + "title": "Change Events", + "type": "boolean" + }, + "replay_epoch": { + "title": "Replay Epoch", + "type": "string" + }, + "heartbeat": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Heartbeat" + } + }, + "required": [ + "skin", + "change_events", + "replay_epoch" + ], + "title": "GatewayReadyPayload", + "type": "object" + }, + "GoalContractSnapshot": { + "additionalProperties": false, + "description": "``hermes_cli/goals.py::GoalContract.to_dict``.", + "properties": { + "outcome": { + "default": "", + "title": "Outcome", + "type": "string" + }, + "verification": { + "default": "", + "title": "Verification", + "type": "string" + }, + "constraints": { + "default": "", + "title": "Constraints", + "type": "string" + }, + "boundaries": { + "default": "", + "title": "Boundaries", + "type": "string" + }, + "stop_when": { + "default": "", + "title": "Stop When", + "type": "string" + } + }, + "title": "GoalContractSnapshot", + "type": "object" + }, + "GoalGateSnapshot": { + "additionalProperties": false, + "properties": { + "command": { + "title": "Command", + "type": "string" + }, + "timeout_seconds": { + "title": "Timeout Seconds", + "type": "integer" + }, + "max_retries": { + "title": "Max Retries", + "type": "integer" + }, + "attempts": { + "title": "Attempts", + "type": "integer" + }, + "last_exit_code": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Last Exit Code" + } + }, + "required": [ + "command", + "timeout_seconds", + "max_retries", + "attempts" + ], + "title": "GoalGateSnapshot", + "type": "object" + }, + "GoalSnapshot": { + "additionalProperties": false, + "description": "``methods_session_control.py::_safe_goal_snapshot`` \u2014 the frontend-safe GoalState subset.", + "properties": { + "title": { + "title": "Title", + "type": "string" + }, + "status": { + "title": "Status", + "type": "string" + }, + "turns_used": { + "title": "Turns Used", + "type": "integer" + }, + "max_turns": { + "title": "Max Turns", + "type": "integer" + }, + "contract": { + "$ref": "#/components/schemas/GoalContractSnapshot" + }, + "subgoals": { + "items": { + "type": "string" + }, + "title": "Subgoals", + "type": "array" + }, + "gates": { + "items": { + "$ref": "#/components/schemas/GoalGateSnapshot" + }, + "title": "Gates", + "type": "array" + }, + "created_at": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Created At" + }, + "updated_at": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Updated At" + }, + "paused_reason": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Paused Reason" + }, + "last_verdict": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Last Verdict" + }, + "last_reason": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Last Reason" + }, + "wait_barrier": { + "anyOf": [ + { + "discriminator": { + "mapping": { + "pid": "#/components/schemas/WaitBarrierTarget", + "session": "#/components/schemas/WaitBarrierTarget", + "until": "#/components/schemas/WaitBarrierUntil" + }, + "propertyName": "type" + }, + "oneOf": [ + { + "$ref": "#/components/schemas/WaitBarrierUntil" + }, + { + "$ref": "#/components/schemas/WaitBarrierTarget" + } + ] + }, + { + "type": "null" + } + ], + "default": null, + "title": "Wait Barrier" + } + }, + "required": [ + "title", + "status", + "turns_used", + "max_turns", + "contract", + "subgoals", + "gates" + ], + "title": "GoalSnapshot", + "type": "object" + }, + "GroupsApproveParams": { + "additionalProperties": false, + "properties": { + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + }, + "room_id": { + "title": "Room Id", + "type": "string" + }, + "member_id": { + "title": "Member Id", + "type": "string" + }, + "task_id": { + "title": "Task Id", + "type": "string" + }, + "execution_generation": { + "title": "Execution Generation", + "type": "integer" + }, + "choice": { + "$ref": "#/components/schemas/tui_gateway_contracts_groups_bot_relay_ApprovalChoice" + }, + "request_id": { + "title": "Request Id", + "type": "string" + } + }, + "required": [ + "room_id", + "member_id", + "task_id", + "execution_generation", + "choice", + "request_id" + ], + "title": "GroupsApproveParams", + "type": "object" + }, + "GroupsApproveResult": { + "additionalProperties": false, + "description": "``result`` is the local ``approval.respond`` answer or the peer's run-action receipt.", + "properties": { + "approved": { + "default": true, + "title": "Approved", + "type": "boolean" + }, + "result": { + "additionalProperties": true, + "title": "Result", + "type": "object" + } + }, + "required": [ + "result" + ], + "title": "GroupsApproveResult", + "type": "object" + }, + "GroupsCapabilitiesParams": { + "additionalProperties": false, + "properties": { + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + } + }, + "title": "GroupsCapabilitiesParams", + "type": "object" + }, + "GroupsCapabilitiesResult": { + "additionalProperties": false, + "properties": { + "protocol_version": { + "title": "Protocol Version", + "type": "integer" + }, + "driver": { + "title": "Driver", + "type": "boolean" + }, + "persistent_process": { + "title": "Persistent Process", + "type": "boolean" + }, + "authority_gateway_id": { + "title": "Authority Gateway Id", + "type": "string" + }, + "room_link": { + "$ref": "#/components/schemas/RoomLinkStatus" + }, + "features": { + "items": { + "type": "string" + }, + "title": "Features", + "type": "array" + }, + "methods": { + "items": { + "type": "string" + }, + "title": "Methods", + "type": "array" + }, + "max_log_limit": { + "title": "Max Log Limit", + "type": "integer" + } + }, + "required": [ + "protocol_version", + "driver", + "persistent_process", + "authority_gateway_id", + "room_link", + "features", + "methods", + "max_log_limit" + ], + "title": "GroupsCapabilitiesResult", + "type": "object" + }, + "GroupsCreateParams": { + "additionalProperties": false, + "properties": { + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + }, + "room_id": { + "title": "Room Id", + "type": "string" + }, + "name": { + "title": "Name", + "type": "string" + }, + "members": { + "items": { + "$ref": "#/components/schemas/RoomMemberInput" + }, + "title": "Members", + "type": "array" + }, + "authority_gateway_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Authority Gateway Id" + } + }, + "required": [ + "room_id", + "name", + "members" + ], + "title": "GroupsCreateParams", + "type": "object" + }, + "GroupsCreateResult": { + "additionalProperties": false, + "properties": { + "room": { + "$ref": "#/components/schemas/Room" + } + }, + "required": [ + "room" + ], + "title": "GroupsCreateResult", + "type": "object" + }, + "GroupsDemoteParams": { + "additionalProperties": false, + "properties": { + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + }, + "room_id": { + "title": "Room Id", + "type": "string" + }, + "observed_gateway_id": { + "title": "Observed Gateway Id", + "type": "string" + }, + "observed_epoch": { + "title": "Observed Epoch", + "type": "integer" + } + }, + "required": [ + "room_id", + "observed_gateway_id", + "observed_epoch" + ], + "title": "GroupsDemoteParams", + "type": "object" + }, + "GroupsDemoteResult": { + "additionalProperties": false, + "properties": { + "room_id": { + "title": "Room Id", + "type": "string" + }, + "authority_gateway_id": { + "title": "Authority Gateway Id", + "type": "string" + }, + "authority_epoch": { + "title": "Authority Epoch", + "type": "integer" + }, + "idempotent": { + "title": "Idempotent", + "type": "boolean" + } + }, + "required": [ + "room_id", + "authority_gateway_id", + "authority_epoch", + "idempotent" + ], + "title": "GroupsDemoteResult", + "type": "object" + }, + "GroupsDisbandParams": { + "additionalProperties": false, + "properties": { + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + }, + "room_id": { + "title": "Room Id", + "type": "string" + }, + "cancel_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Cancel Id" + } + }, + "required": [ + "room_id" + ], + "title": "GroupsDisbandParams", + "type": "object" + }, + "GroupsDisbandResult": { + "additionalProperties": false, + "properties": { + "tombstone": { + "$ref": "#/components/schemas/RoomTombstone" + } + }, + "required": [ + "tombstone" + ], + "title": "GroupsDisbandResult", + "type": "object" + }, + "GroupsListParams": { + "additionalProperties": false, + "properties": { + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + }, + "include_disbanded": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Include Disbanded" + }, + "limit": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Limit" + }, + "offset": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Offset" + } + }, + "title": "GroupsListParams", + "type": "object" + }, + "GroupsListResult": { + "additionalProperties": false, + "properties": { + "rooms": { + "items": { + "$ref": "#/components/schemas/Room" + }, + "title": "Rooms", + "type": "array" + }, + "next_offset": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Next Offset" + } + }, + "required": [ + "rooms" + ], + "title": "GroupsListResult", + "type": "object" + }, + "GroupsLogParams": { + "additionalProperties": false, + "properties": { + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + }, + "room_id": { + "title": "Room Id", + "type": "string" + }, + "since_seq": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Since Seq" + }, + "limit": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Limit" + }, + "include_disbanded": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Include Disbanded" + } + }, + "required": [ + "room_id" + ], + "title": "GroupsLogParams", + "type": "object" + }, + "GroupsLogResult": { + "additionalProperties": false, + "description": "``gateway/hosted_rooms.py::read_events`` page \u2014 also the ``page`` ``groups.replicate`` ingests.", + "properties": { + "events": { + "items": { + "$ref": "#/components/schemas/RoomEvent" + }, + "title": "Events", + "type": "array" + }, + "cursor": { + "title": "Cursor", + "type": "integer" + }, + "latest_seq": { + "title": "Latest Seq", + "type": "integer" + }, + "has_more": { + "title": "Has More", + "type": "boolean" + }, + "authority": { + "$ref": "#/components/schemas/RoomAuthority" + } + }, + "required": [ + "events", + "cursor", + "latest_seq", + "has_more", + "authority" + ], + "title": "GroupsLogResult", + "type": "object" + }, + "GroupsPeerInviteParams": { + "additionalProperties": false, + "properties": { + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + }, + "room_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Room Id" + }, + "home_install_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Home Install Id" + }, + "authority_gateway_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Authority Gateway Id" + }, + "authority_epoch": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Authority Epoch" + }, + "member_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Member Id" + }, + "grant_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Grant Id" + }, + "ttl_seconds": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Ttl Seconds" + } + }, + "title": "GroupsPeerInviteParams", + "type": "object" + }, + "GroupsPeerInviteResult": { + "additionalProperties": false, + "properties": { + "grant": { + "title": "Grant", + "type": "string" + }, + "target_profile": { + "title": "Target Profile", + "type": "string" + }, + "catalog": { + "$ref": "#/components/schemas/RoomLinkCatalog" + }, + "endpoint": { + "$ref": "#/components/schemas/RoomLinkEndpoint" + } + }, + "required": [ + "grant", + "target_profile", + "catalog", + "endpoint" + ], + "title": "GroupsPeerInviteResult", + "type": "object" + }, + "GroupsPeerRegisterParams": { + "additionalProperties": false, + "properties": { + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + }, + "room_id": { + "title": "Room Id", + "type": "string" + }, + "member_id": { + "title": "Member Id", + "type": "string" + }, + "target_url": { + "title": "Target Url", + "type": "string" + }, + "target_profile": { + "title": "Target Profile", + "type": "string" + }, + "grant": { + "title": "Grant", + "type": "string" + }, + "catalog": { + "additionalProperties": true, + "title": "Catalog", + "type": "object" + }, + "cancellation_scope_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Cancellation Scope Id" + }, + "trace_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Trace Id" + } + }, + "required": [ + "room_id", + "member_id", + "target_url", + "target_profile", + "grant", + "catalog" + ], + "title": "GroupsPeerRegisterParams", + "type": "object" + }, + "GroupsPeerRegisterResult": { + "additionalProperties": false, + "properties": { + "registered": { + "default": true, + "title": "Registered", + "type": "boolean" + }, + "mode": { + "title": "Mode", + "type": "string" + }, + "transport_security": { + "title": "Transport Security", + "type": "string" + }, + "target_install_id": { + "title": "Target Install Id", + "type": "string" + }, + "target_profile": { + "title": "Target Profile", + "type": "string" + } + }, + "required": [ + "mode", + "transport_security", + "target_install_id", + "target_profile" + ], + "title": "GroupsPeerRegisterResult", + "type": "object" + }, + "GroupsPeerRevokeParams": { + "additionalProperties": false, + "properties": { + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + }, + "grant": { + "title": "Grant", + "type": "string" + } + }, + "required": [ + "grant" + ], + "title": "GroupsPeerRevokeParams", + "type": "object" + }, + "GroupsPeerRevokeResult": { + "additionalProperties": false, + "properties": { + "revoked": { + "default": true, + "title": "Revoked", + "type": "boolean" + } + }, + "title": "GroupsPeerRevokeResult", + "type": "object" + }, + "GroupsPromoteParams": { + "additionalProperties": false, + "properties": { + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + }, + "room_id": { + "title": "Room Id", + "type": "string" + }, + "confirm": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Confirm" + }, + "reason": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Reason" + } + }, + "required": [ + "room_id" + ], + "title": "GroupsPromoteParams", + "type": "object" + }, + "GroupsPromoteResult": { + "additionalProperties": false, + "properties": { + "room_id": { + "title": "Room Id", + "type": "string" + }, + "authority_gateway_id": { + "title": "Authority Gateway Id", + "type": "string" + }, + "authority_epoch": { + "title": "Authority Epoch", + "type": "integer" + }, + "previous_gateway_id": { + "title": "Previous Gateway Id", + "type": "string" + }, + "previous_epoch": { + "title": "Previous Epoch", + "type": "integer" + }, + "claim_seq": { + "title": "Claim Seq", + "type": "integer" + }, + "latest_seq": { + "title": "Latest Seq", + "type": "integer" + } + }, + "required": [ + "room_id", + "authority_gateway_id", + "authority_epoch", + "previous_gateway_id", + "previous_epoch", + "claim_seq", + "latest_seq" + ], + "title": "GroupsPromoteResult", + "type": "object" + }, + "GroupsRenameParams": { + "additionalProperties": false, + "properties": { + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + }, + "room_id": { + "title": "Room Id", + "type": "string" + }, + "event_id": { + "title": "Event Id", + "type": "string" + }, + "name": { + "title": "Name", + "type": "string" + } + }, + "required": [ + "room_id", + "event_id", + "name" + ], + "title": "GroupsRenameParams", + "type": "object" + }, + "GroupsRenameResult": { + "additionalProperties": false, + "properties": { + "room": { + "$ref": "#/components/schemas/Room" + } + }, + "required": [ + "room" + ], + "title": "GroupsRenameResult", + "type": "object" + }, + "GroupsReplicaStateParams": { + "additionalProperties": false, + "properties": { + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + }, + "room_id": { + "title": "Room Id", + "type": "string" + } + }, + "required": [ + "room_id" + ], + "title": "GroupsReplicaStateParams", + "type": "object" + }, + "GroupsReplicaStateResult": { + "additionalProperties": false, + "properties": { + "room_id": { + "title": "Room Id", + "type": "string" + }, + "name": { + "title": "Name", + "type": "string" + }, + "members": { + "items": { + "$ref": "#/components/schemas/RoomMember" + }, + "title": "Members", + "type": "array" + }, + "authority": { + "$ref": "#/components/schemas/RoomAuthority" + }, + "last_seq": { + "title": "Last Seq", + "type": "integer" + }, + "latest_seq": { + "title": "Latest Seq", + "type": "integer" + }, + "event_bytes": { + "title": "Event Bytes", + "type": "integer" + }, + "created_at": { + "title": "Created At", + "type": "number" + }, + "updated_at": { + "title": "Updated At", + "type": "number" + } + }, + "required": [ + "room_id", + "name", + "members", + "authority", + "last_seq", + "latest_seq", + "event_bytes", + "created_at", + "updated_at" + ], + "title": "GroupsReplicaStateResult", + "type": "object" + }, + "GroupsReplicateParams": { + "additionalProperties": false, + "properties": { + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + }, + "room_id": { + "title": "Room Id", + "type": "string" + }, + "room_name": { + "title": "Room Name", + "type": "string" + }, + "members": { + "items": { + "$ref": "#/components/schemas/RoomMemberInput" + }, + "title": "Members", + "type": "array" + }, + "page": { + "additionalProperties": true, + "title": "Page", + "type": "object" + } + }, + "required": [ + "room_id", + "room_name", + "members", + "page" + ], + "title": "GroupsReplicateParams", + "type": "object" + }, + "GroupsReplicateResult": { + "additionalProperties": false, + "properties": { + "room_id": { + "title": "Room Id", + "type": "string" + }, + "stored_seq": { + "title": "Stored Seq", + "type": "integer" + }, + "ingested": { + "title": "Ingested", + "type": "integer" + }, + "authority": { + "$ref": "#/components/schemas/RoomAuthority" + }, + "caught_up": { + "title": "Caught Up", + "type": "boolean" + } + }, + "required": [ + "room_id", + "stored_seq", + "ingested", + "authority", + "caught_up" + ], + "title": "GroupsReplicateResult", + "type": "object" + }, + "GroupsRetryParams": { + "additionalProperties": false, + "properties": { + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + }, + "room_id": { + "title": "Room Id", + "type": "string" + }, + "task_id": { + "title": "Task Id", + "type": "string" + } + }, + "required": [ + "room_id", + "task_id" + ], + "title": "GroupsRetryParams", + "type": "object" + }, + "GroupsRetryResult": { + "additionalProperties": false, + "properties": { + "retried": { + "default": true, + "title": "Retried", + "type": "boolean" + }, + "task": { + "$ref": "#/components/schemas/RoomTaskReceipt" + } + }, + "required": [ + "task" + ], + "title": "GroupsRetryResult", + "type": "object" + }, + "GroupsSendParams": { + "additionalProperties": false, + "properties": { + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + }, + "room_id": { + "title": "Room Id", + "type": "string" + }, + "event_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Event Id" + }, + "payload": { + "additionalProperties": true, + "title": "Payload", + "type": "object" + } + }, + "required": [ + "room_id", + "payload" + ], + "title": "GroupsSendParams", + "type": "object" + }, + "GroupsSendResult": { + "additionalProperties": false, + "properties": { + "event": { + "$ref": "#/components/schemas/RoomEvent" + }, + "client_event_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Client Event Id" + }, + "accepted": { + "default": true, + "title": "Accepted", + "type": "boolean" + }, + "driver_started": { + "default": true, + "title": "Driver Started", + "type": "boolean" + } + }, + "required": [ + "event" + ], + "title": "GroupsSendResult", + "type": "object" + }, + "GroupsStateParams": { + "additionalProperties": false, + "properties": { + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + }, + "room_id": { + "title": "Room Id", + "type": "string" + }, + "include_disbanded": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Include Disbanded" + } + }, + "required": [ + "room_id" + ], + "title": "GroupsStateParams", + "type": "object" + }, + "GroupsStateResult": { + "additionalProperties": false, + "properties": { + "room": { + "$ref": "#/components/schemas/Room" + }, + "driver_status": { + "anyOf": [ + { + "$ref": "#/components/schemas/RoomDriverStatus" + }, + { + "type": "null" + } + ], + "default": null + } + }, + "required": [ + "room" + ], + "title": "GroupsStateResult", + "type": "object" + }, + "GroupsStopParams": { + "additionalProperties": false, + "properties": { + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + }, + "room_id": { + "title": "Room Id", + "type": "string" + }, + "cancel_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Cancel Id" + } + }, + "required": [ + "room_id" + ], + "title": "GroupsStopParams", + "type": "object" + }, + "GroupsStopResult": { + "additionalProperties": false, + "properties": { + "cancelled": { + "title": "Cancelled", + "type": "integer" + } + }, + "required": [ + "cancelled" + ], + "title": "GroupsStopResult", + "type": "object" + }, + "HandoffFailParams": { + "additionalProperties": false, + "properties": { + "session_id": { + "title": "Session Id", + "type": "string" + }, + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + }, + "error": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Error" + } + }, + "required": [ + "session_id" + ], + "title": "HandoffFailParams", + "type": "object" + }, + "HandoffFailResult": { + "additionalProperties": false, + "description": "``failed`` false when the watcher already claimed the row; ``state`` is what it is now.", + "properties": { + "failed": { + "title": "Failed", + "type": "boolean" + }, + "state": { + "title": "State", + "type": "string" + } + }, + "required": [ + "failed", + "state" + ], + "title": "HandoffFailResult", + "type": "object" + }, + "HandoffRequestParams": { + "additionalProperties": false, + "properties": { + "session_id": { + "title": "Session Id", + "type": "string" + }, + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + }, + "platform": { + "title": "Platform", + "type": "string" + } + }, + "required": [ + "session_id", + "platform" + ], + "title": "HandoffRequestParams", + "type": "object" + }, + "HandoffRequestResult": { + "additionalProperties": false, + "properties": { + "queued": { + "title": "Queued", + "type": "boolean" + }, + "session_key": { + "title": "Session Key", + "type": "string" + }, + "platform": { + "title": "Platform", + "type": "string" + }, + "home_name": { + "title": "Home Name", + "type": "string" + } + }, + "required": [ + "queued", + "session_key", + "platform", + "home_name" + ], + "title": "HandoffRequestResult", + "type": "object" + }, + "HandoffStateResult": { + "additionalProperties": false, + "description": "``state`` is pending | running | completed | failed, or '' when nothing was requested.", + "properties": { + "state": { + "title": "State", + "type": "string" + }, + "platform": { + "title": "Platform", + "type": "string" + }, + "error": { + "title": "Error", + "type": "string" + } + }, + "required": [ + "state", + "platform", + "error" + ], + "title": "HandoffStateResult", + "type": "object" + }, + "HeartbeatSnapshot": { + "additionalProperties": false, + "properties": { + "prompt": { + "title": "Prompt", + "type": "string" + }, + "status": { + "title": "Status", + "type": "string" + }, + "interval_seconds": { + "title": "Interval Seconds", + "type": "integer" + }, + "created_at": { + "title": "Created At", + "type": "number" + }, + "last_fired_at": { + "title": "Last Fired At", + "type": "number" + }, + "fire_count": { + "title": "Fire Count", + "type": "integer" + } + }, + "required": [ + "prompt", + "status", + "interval_seconds", + "created_at", + "last_fired_at", + "fire_count" + ], + "title": "HeartbeatSnapshot", + "type": "object" + }, + "ImageAttachBytesParams": { + "additionalProperties": false, + "description": "``content_base64`` (or the ``data`` alias) carries the bytes; ``filename`` / ``ext`` only hint\nthe extension \u2014 magic bytes decide.", + "properties": { + "session_id": { + "title": "Session Id", + "type": "string" + }, + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + }, + "content_base64": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Content Base64" + }, + "data": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Data" + }, + "filename": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Filename" + }, + "ext": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Ext" + } + }, + "required": [ + "session_id" + ], + "title": "ImageAttachBytesParams", + "type": "object" + }, + "ImageAttachParams": { + "additionalProperties": false, + "properties": { + "session_id": { + "title": "Session Id", + "type": "string" + }, + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + }, + "path": { + "title": "Path", + "type": "string" + } + }, + "required": [ + "session_id", + "path" + ], + "title": "ImageAttachParams", + "type": "object" + }, + "ImageDetachParams": { + "additionalProperties": false, + "properties": { + "session_id": { + "title": "Session Id", + "type": "string" + }, + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + }, + "path": { + "title": "Path", + "type": "string" + } + }, + "required": [ + "session_id", + "path" + ], + "title": "ImageDetachParams", + "type": "object" + }, + "ImageDetachResult": { + "additionalProperties": false, + "properties": { + "detached": { + "title": "Detached", + "type": "boolean" + }, + "count": { + "title": "Count", + "type": "integer" + } + }, + "required": [ + "detached", + "count" + ], + "title": "ImageDetachResult", + "type": "object" + }, + "ImageGenerateParams": { + "additionalProperties": false, + "properties": { + "prompt": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Prompt" + }, + "aspect_ratio": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Aspect Ratio" + }, + "probe": { + "anyOf": [ + {}, + { + "type": "null" + } + ], + "default": null, + "title": "Probe" + }, + "max_bytes": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Max Bytes" + } + }, + "title": "ImageGenerateParams", + "type": "object" + }, + "ImageGenerateResult": { + "additionalProperties": false, + "description": "``probe`` answers ``{available}`` alone; ``image_data`` (data URL) is omitted when the\ndownload failed or exceeded ``max_bytes`` so callers fall back to ``image``.", + "properties": { + "available": { + "title": "Available", + "type": "boolean" + }, + "success": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Success" + }, + "image": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Image" + }, + "image_data": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Image Data" + }, + "error": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Error" + } + }, + "required": [ + "available" + ], + "title": "ImageGenerateResult", + "type": "object" + }, + "InflightTurn": { + "additionalProperties": false, + "description": "``session_auto_continue._inflight_snapshot``: the live (or retained failed) turn a reconnecting\nclient rebuilds its bubbles from.", + "properties": { + "assistant": { + "default": "", + "title": "Assistant", + "type": "string" + }, + "streaming": { + "default": false, + "title": "Streaming", + "type": "boolean" + }, + "user": { + "default": "", + "title": "User", + "type": "string" + }, + "corrections": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Corrections" + }, + "correction_offsets": { + "anyOf": [ + { + "items": { + "type": "integer" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Correction Offsets" + }, + "error": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Error" + }, + "status": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Status" + }, + "recoverable": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Recoverable" + }, + "error_surface": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Error Surface" + } + }, + "title": "InflightTurn", + "type": "object" + }, + "InputDetectDropParams": { + "additionalProperties": false, + "properties": { + "session_id": { + "title": "Session Id", + "type": "string" + }, + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + }, + "text": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Text" + } + }, + "required": [ + "session_id" + ], + "title": "InputDetectDropParams", + "type": "object" + }, + "InputDetectDropResult": { + "additionalProperties": false, + "description": "``matched: false`` alone when the text is not a drop; an image drop is queued immediately\n(``is_image`` + ``count``), a file drop only yields the ``text`` to insert.", + "properties": { + "name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Name" + }, + "width": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Width" + }, + "height": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Height" + }, + "token_estimate": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Token Estimate" + }, + "matched": { + "title": "Matched", + "type": "boolean" + }, + "is_image": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Is Image" + }, + "path": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Path" + }, + "count": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Count" + }, + "text": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Text" + } + }, + "required": [ + "matched" + ], + "title": "InputDetectDropResult", + "type": "object" + }, + "InsightsGetParams": { + "additionalProperties": false, + "properties": { + "days": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Days" + }, + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + } + }, + "title": "InsightsGetParams", + "type": "object" + }, + "InsightsGetResult": { + "additionalProperties": false, + "properties": { + "days": { + "title": "Days", + "type": "integer" + }, + "sessions": { + "title": "Sessions", + "type": "integer" + }, + "messages": { + "title": "Messages", + "type": "integer" + } + }, + "required": [ + "days", + "sessions", + "messages" + ], + "title": "InsightsGetResult", + "type": "object" + }, + "InterruptStatus": { + "enum": [ + "interrupted", + "not_interrupted" + ], + "title": "InterruptStatus", + "type": "string" + }, + "LayoutApplyPayload": { + "additionalProperties": true, + "description": "``tools/apply_layout_tool.py``.", + "properties": { + "preset": { + "title": "Preset", + "type": "string" + } + }, + "required": [ + "preset" + ], + "title": "LayoutApplyPayload", + "type": "object" + }, + "LearningAxis": { + "additionalProperties": false, + "properties": { + "start": { + "title": "Start", + "type": "string" + }, + "end": { + "title": "End", + "type": "string" + } + }, + "required": [ + "start", + "end" + ], + "title": "LearningAxis", + "type": "object" + }, + "LearningBucketRow": { + "additionalProperties": false, + "properties": { + "index": { + "title": "Index", + "type": "integer" + }, + "label": { + "title": "Label", + "type": "string" + }, + "date": { + "title": "Date", + "type": "string" + }, + "skills": { + "title": "Skills", + "type": "integer" + }, + "memories": { + "title": "Memories", + "type": "integer" + }, + "total": { + "title": "Total", + "type": "integer" + }, + "category": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Category" + }, + "color": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Color" + }, + "nodes": { + "items": { + "$ref": "#/components/schemas/LearningNodeRow" + }, + "title": "Nodes", + "type": "array" + } + }, + "required": [ + "index", + "label", + "date", + "skills", + "memories", + "total", + "nodes" + ], + "title": "LearningBucketRow", + "type": "object" + }, + "LearningDetailResult": { + "additionalProperties": false, + "properties": { + "ok": { + "title": "Ok", + "type": "boolean" + }, + "message": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Message" + }, + "kind": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Kind" + }, + "id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Id" + }, + "label": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Label" + }, + "content": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Content" + } + }, + "required": [ + "ok" + ], + "title": "LearningDetailResult", + "type": "object" + }, + "LearningEditParams": { + "additionalProperties": false, + "properties": { + "id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Id" + }, + "content": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Content" + } + }, + "title": "LearningEditParams", + "type": "object" + }, + "LearningFrame": { + "additionalProperties": false, + "description": "``agent.learning_graph_render.render_graph`` projection; ``grid`` rows are lists of\n``[text, styleKey, alpha?, hexOverride?]`` runs.", + "properties": { + "reveal": { + "title": "Reveal", + "type": "number" + }, + "date": { + "title": "Date", + "type": "string" + }, + "visible": { + "title": "Visible", + "type": "integer" + }, + "grid": { + "items": { + "items": {}, + "type": "array" + }, + "title": "Grid", + "type": "array" + }, + "labels": { + "items": { + "additionalProperties": true, + "type": "object" + }, + "title": "Labels", + "type": "array" + } + }, + "required": [ + "reveal", + "date", + "visible", + "grid" + ], + "title": "LearningFrame", + "type": "object" + }, + "LearningFramesParams": { + "additionalProperties": false, + "properties": { + "cols": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Cols" + }, + "rows": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Rows" + }, + "frames": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Frames" + } + }, + "title": "LearningFramesParams", + "type": "object" + }, + "LearningFramesResult": { + "additionalProperties": false, + "properties": { + "frames": { + "items": { + "$ref": "#/components/schemas/LearningFrame" + }, + "title": "Frames", + "type": "array" + }, + "legend": { + "items": { + "$ref": "#/components/schemas/LearningLegendItem" + }, + "title": "Legend", + "type": "array" + }, + "categories": { + "items": { + "$ref": "#/components/schemas/LearningLegendItem" + }, + "title": "Categories", + "type": "array" + }, + "buckets": { + "items": { + "$ref": "#/components/schemas/LearningBucketRow" + }, + "title": "Buckets", + "type": "array" + }, + "summary": { + "items": { + "type": "string" + }, + "title": "Summary", + "type": "array" + }, + "axis": { + "$ref": "#/components/schemas/LearningAxis" + }, + "count": { + "title": "Count", + "type": "integer" + }, + "cols": { + "title": "Cols", + "type": "integer" + }, + "rows": { + "title": "Rows", + "type": "integer" + } + }, + "required": [ + "frames", + "legend", + "categories", + "buckets", + "summary", + "axis", + "count", + "cols", + "rows" + ], + "title": "LearningFramesResult", + "type": "object" + }, + "LearningLegendItem": { + "additionalProperties": false, + "properties": { + "glyph": { + "title": "Glyph", + "type": "string" + }, + "label": { + "title": "Label", + "type": "string" + }, + "style": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Style" + }, + "color": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Color" + } + }, + "required": [ + "glyph", + "label" + ], + "title": "LearningLegendItem", + "type": "object" + }, + "LearningMutationResult": { + "additionalProperties": false, + "description": "``agent.learning_mutations`` \u2014 ``ok: false`` carries the reason in ``message``.", + "properties": { + "ok": { + "title": "Ok", + "type": "boolean" + }, + "message": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Message" + } + }, + "required": [ + "ok" + ], + "title": "LearningMutationResult", + "type": "object" + }, + "LearningNodeParams": { + "additionalProperties": false, + "properties": { + "id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Id" + } + }, + "title": "LearningNodeParams", + "type": "object" + }, + "LearningNodeRow": { + "additionalProperties": false, + "properties": { + "id": { + "title": "Id", + "type": "string" + }, + "glyph": { + "title": "Glyph", + "type": "string" + }, + "label": { + "title": "Label", + "type": "string" + }, + "fullLabel": { + "title": "Fulllabel", + "type": "string" + }, + "meta": { + "title": "Meta", + "type": "string" + }, + "body": { + "title": "Body", + "type": "string" + }, + "style": { + "title": "Style", + "type": "string" + } + }, + "required": [ + "id", + "glyph", + "label", + "fullLabel", + "meta", + "body", + "style" + ], + "title": "LearningNodeRow", + "type": "object" + }, + "LegacyPluginRow": { + "additionalProperties": false, + "properties": { + "name": { + "title": "Name", + "type": "string" + }, + "version": { + "title": "Version", + "type": "string" + }, + "enabled": { + "title": "Enabled", + "type": "boolean" + } + }, + "required": [ + "name", + "version", + "enabled" + ], + "title": "LegacyPluginRow", + "type": "object" + }, + "LiveSessionStatus": { + "enum": [ + "idle", + "starting", + "waiting", + "working", + "streaming", + "resuming" + ], + "title": "LiveSessionStatus", + "type": "string" + }, + "LlmOneshotParams": { + "additionalProperties": false, + "description": "Needs a ``template`` or ``instructions`` / ``input``; a live ``session_id`` lends its model.", + "properties": { + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + }, + "template": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Template" + }, + "instructions": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Instructions" + }, + "input": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Input" + }, + "variables": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Variables" + }, + "task": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Task" + }, + "temperature": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Temperature" + }, + "max_tokens": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Max Tokens" + }, + "session_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Session Id" + } + }, + "title": "LlmOneshotParams", + "type": "object" + }, + "LlmOneshotResult": { + "additionalProperties": false, + "properties": { + "text": { + "title": "Text", + "type": "string" + } + }, + "required": [ + "text" + ], + "title": "LlmOneshotResult", + "type": "object" + }, + "LoopSnapshot": { + "additionalProperties": false, + "description": "``_safe_loop_snapshot`` \u2014 persisted LoopState fields, never its route.", + "properties": { + "prompt": { + "title": "Prompt", + "type": "string" + }, + "status": { + "title": "Status", + "type": "string" + }, + "mode": { + "title": "Mode", + "type": "string" + }, + "interval_seconds": { + "title": "Interval Seconds", + "type": "number" + }, + "current_delay": { + "title": "Current Delay", + "type": "number" + }, + "times": { + "title": "Times", + "type": "integer" + }, + "until": { + "title": "Until", + "type": "string" + }, + "max_ticks": { + "title": "Max Ticks", + "type": "integer" + }, + "ticks_fired": { + "title": "Ticks Fired", + "type": "integer" + }, + "created_at": { + "title": "Created At", + "type": "number" + }, + "last_fired_at": { + "title": "Last Fired At", + "type": "number" + }, + "next_due_at": { + "title": "Next Due At", + "type": "number" + }, + "awaiting_response": { + "title": "Awaiting Response", + "type": "boolean" + }, + "deferred_by_goal": { + "title": "Deferred By Goal", + "type": "boolean" + }, + "paused_reason": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Paused Reason" + }, + "last_stop_reason": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Last Stop Reason" + } + }, + "required": [ + "prompt", + "status", + "mode", + "interval_seconds", + "current_delay", + "times", + "until", + "max_ticks", + "ticks_fired", + "created_at", + "last_fired_at", + "next_due_at", + "awaiting_response", + "deferred_by_goal" + ], + "title": "LoopSnapshot", + "type": "object" + }, + "McpCatalogEntry": { + "additionalProperties": false, + "properties": { + "name": { + "title": "Name", + "type": "string" + }, + "description": { + "title": "Description", + "type": "string" + }, + "installed": { + "title": "Installed", + "type": "boolean" + }, + "enabled": { + "title": "Enabled", + "type": "boolean" + }, + "requires": { + "items": { + "type": "string" + }, + "title": "Requires", + "type": "array" + }, + "transport": { + "title": "Transport", + "type": "string" + } + }, + "required": [ + "name", + "description", + "installed", + "enabled", + "requires", + "transport" + ], + "title": "McpCatalogEntry", + "type": "object" + }, + "McpCatalogResult": { + "additionalProperties": false, + "properties": { + "servers": { + "items": { + "$ref": "#/components/schemas/McpCatalogEntry" + }, + "title": "Servers", + "type": "array" + } + }, + "required": [ + "servers" + ], + "title": "McpCatalogResult", + "type": "object" + }, + "McpOauthCallbackParams": { + "additionalProperties": false, + "properties": { + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + }, + "name": { + "title": "Name", + "type": "string" + }, + "session_id": { + "title": "Session Id", + "type": "string" + }, + "code": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Code" + }, + "state": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "State" + }, + "error": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Error" + } + }, + "required": [ + "name", + "session_id" + ], + "title": "McpOauthCallbackParams", + "type": "object" + }, + "McpOauthCallbackResult": { + "additionalProperties": false, + "properties": { + "ok": { + "title": "Ok", + "type": "boolean" + }, + "session_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Session Id" + }, + "error_message": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Error Message" + } + }, + "required": [ + "ok" + ], + "title": "McpOauthCallbackResult", + "type": "object" + }, + "McpOauthCancelResult": { + "additionalProperties": false, + "properties": { + "ok": { + "title": "Ok", + "type": "boolean" + }, + "status": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Status" + }, + "error_message": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Error Message" + } + }, + "required": [ + "ok" + ], + "title": "McpOauthCancelResult", + "type": "object" + }, + "McpOauthFlowParams": { + "additionalProperties": false, + "description": "``session_id`` is the OAuth flow id returned by ``oauth.start`` (not a gateway session).", + "properties": { + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + }, + "name": { + "title": "Name", + "type": "string" + }, + "session_id": { + "title": "Session Id", + "type": "string" + } + }, + "required": [ + "name", + "session_id" + ], + "title": "McpOauthFlowParams", + "type": "object" + }, + "McpOauthPollResult": { + "additionalProperties": false, + "properties": { + "ok": { + "title": "Ok", + "type": "boolean" + }, + "status": { + "$ref": "#/components/schemas/McpOauthPollStatus" + }, + "session_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Session Id" + }, + "error_message": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Error Message" + }, + "auth_url": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Auth Url" + }, + "tools": { + "anyOf": [ + { + "items": { + "$ref": "#/components/schemas/McpProbeTool" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Tools" + } + }, + "required": [ + "ok", + "status" + ], + "title": "McpOauthPollResult", + "type": "object" + }, + "McpOauthPollStatus": { + "enum": [ + "pending", + "approved", + "error" + ], + "title": "McpOauthPollStatus", + "type": "string" + }, + "McpOauthStartParams": { + "additionalProperties": false, + "description": "With ``client_redirect_uri`` the CLIENT hosts the loopback and relays the code via\n``mcp.servers.oauth.callback``.", + "properties": { + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + }, + "name": { + "title": "Name", + "type": "string" + }, + "client_redirect_uri": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Client Redirect Uri" + } + }, + "required": [ + "name" + ], + "title": "McpOauthStartParams", + "type": "object" + }, + "McpOauthStartResult": { + "additionalProperties": false, + "properties": { + "ok": { + "title": "Ok", + "type": "boolean" + }, + "session_id": { + "title": "Session Id", + "type": "string" + }, + "auth_url": { + "title": "Auth Url", + "type": "string" + }, + "flow": { + "title": "Flow", + "type": "string" + } + }, + "required": [ + "ok", + "session_id", + "auth_url", + "flow" + ], + "title": "McpOauthStartResult", + "type": "object" + }, + "McpProbeTool": { + "additionalProperties": false, + "properties": { + "name": { + "title": "Name", + "type": "string" + }, + "description": { + "title": "Description", + "type": "string" + } + }, + "required": [ + "name", + "description" + ], + "title": "McpProbeTool", + "type": "object" + }, + "McpRuntimeStatus": { + "enum": [ + "connected", + "disabled", + "connecting", + "failed", + "configured" + ], + "title": "McpRuntimeStatus", + "type": "string" + }, + "McpServerEntry": { + "additionalProperties": false, + "properties": { + "name": { + "title": "Name", + "type": "string" + }, + "enabled": { + "default": true, + "title": "Enabled", + "type": "boolean" + }, + "transport": { + "default": "stdio", + "title": "Transport", + "type": "string" + } + }, + "required": [ + "name" + ], + "title": "McpServerEntry", + "type": "object" + }, + "McpServerNameParams": { + "additionalProperties": false, + "properties": { + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + }, + "name": { + "title": "Name", + "type": "string" + } + }, + "required": [ + "name" + ], + "title": "McpServerNameParams", + "type": "object" + }, + "McpServerRuntimeRow": { + "additionalProperties": false, + "description": "Safe projection of ``tools.mcp_tool_discovery.get_mcp_status`` rows.", + "properties": { + "name": { + "title": "Name", + "type": "string" + }, + "transport": { + "title": "Transport", + "type": "string" + }, + "tools": { + "title": "Tools", + "type": "integer" + }, + "connected": { + "title": "Connected", + "type": "boolean" + }, + "disabled": { + "title": "Disabled", + "type": "boolean" + }, + "status": { + "$ref": "#/components/schemas/McpRuntimeStatus" + } + }, + "required": [ + "name", + "transport", + "tools", + "connected", + "disabled", + "status" + ], + "title": "McpServerRuntimeRow", + "type": "object" + }, + "McpServerStatus": { + "additionalProperties": true, + "properties": { + "name": { + "default": "", + "title": "Name", + "type": "string" + }, + "status": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Status" + }, + "tool_count": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Tool Count" + }, + "error": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Error" + } + }, + "title": "McpServerStatus", + "type": "object" + }, + "McpServerSummary": { + "additionalProperties": false, + "description": "``tui_gateway/mcp_rpc_helpers.summarize_server`` \u2014 a server's config without secret values.", + "properties": { + "name": { + "title": "Name", + "type": "string" + }, + "transport": { + "title": "Transport", + "type": "string" + }, + "url": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Url" + }, + "command": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Command" + }, + "args": { + "items": { + "type": "string" + }, + "title": "Args", + "type": "array" + }, + "env": { + "items": { + "type": "string" + }, + "title": "Env", + "type": "array" + }, + "auth": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Auth" + }, + "oauth_tokens_present": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Oauth Tokens Present" + }, + "enabled": { + "title": "Enabled", + "type": "boolean" + }, + "tools": { + "anyOf": [ + {}, + { + "type": "null" + } + ], + "default": null, + "title": "Tools" + } + }, + "required": [ + "name", + "transport", + "args", + "env", + "enabled" + ], + "title": "McpServerSummary", + "type": "object" + }, + "McpServersAddParams": { + "additionalProperties": false, + "description": "``preset`` (catalog id) and/or ``config`` (url/command/args/env/headers/auth/tools); a\n``bearer_token`` is written to the profile's .env, only the header template persists.", + "properties": { + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + }, + "name": { + "title": "Name", + "type": "string" + }, + "preset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Preset" + }, + "config": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Config" + }, + "bearer_token": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Bearer Token" + } + }, + "required": [ + "name" + ], + "title": "McpServersAddParams", + "type": "object" + }, + "McpServersAddResult": { + "additionalProperties": false, + "properties": { + "ok": { + "title": "Ok", + "type": "boolean" + }, + "name": { + "title": "Name", + "type": "string" + }, + "server": { + "$ref": "#/components/schemas/McpServerSummary" + } + }, + "required": [ + "ok", + "name", + "server" + ], + "title": "McpServersAddResult", + "type": "object" + }, + "McpServersListResult": { + "additionalProperties": false, + "properties": { + "servers": { + "items": { + "$ref": "#/components/schemas/McpServerSummary" + }, + "title": "Servers", + "type": "array" + } + }, + "required": [ + "servers" + ], + "title": "McpServersListResult", + "type": "object" + }, + "McpServersRemoveResult": { + "additionalProperties": false, + "properties": { + "ok": { + "title": "Ok", + "type": "boolean" + }, + "removed": { + "title": "Removed", + "type": "boolean" + } + }, + "required": [ + "ok", + "removed" + ], + "title": "McpServersRemoveResult", + "type": "object" + }, + "McpServersSetApiKeyParams": { + "additionalProperties": false, + "properties": { + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + }, + "name": { + "title": "Name", + "type": "string" + }, + "value": { + "title": "Value", + "type": "string" + }, + "env_var": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Env Var" + } + }, + "required": [ + "name", + "value" + ], + "title": "McpServersSetApiKeyParams", + "type": "object" + }, + "McpServersSetApiKeyResult": { + "additionalProperties": false, + "properties": { + "ok": { + "title": "Ok", + "type": "boolean" + }, + "name": { + "title": "Name", + "type": "string" + }, + "env_var": { + "title": "Env Var", + "type": "string" + }, + "server": { + "$ref": "#/components/schemas/McpServerSummary" + } + }, + "required": [ + "ok", + "name", + "env_var", + "server" + ], + "title": "McpServersSetApiKeyResult", + "type": "object" + }, + "McpServersStatusResult": { + "additionalProperties": false, + "properties": { + "servers": { + "items": { + "$ref": "#/components/schemas/McpServerRuntimeRow" + }, + "title": "Servers", + "type": "array" + }, + "checked_at": { + "title": "Checked At", + "type": "integer" + } + }, + "required": [ + "servers", + "checked_at" + ], + "title": "McpServersStatusResult", + "type": "object" + }, + "McpServersTestResult": { + "additionalProperties": false, + "description": "``ok: false`` carries ``error``; ``prompts`` / ``resources`` are only counted on success.", + "properties": { + "ok": { + "title": "Ok", + "type": "boolean" + }, + "tools": { + "items": { + "$ref": "#/components/schemas/McpProbeTool" + }, + "title": "Tools", + "type": "array" + }, + "error": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Error" + }, + "prompts": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Prompts" + }, + "resources": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Resources" + }, + "oauth_needed": { + "title": "Oauth Needed", + "type": "boolean" + }, + "oauth_tokens_present": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Oauth Tokens Present" + } + }, + "required": [ + "ok", + "tools", + "oauth_needed" + ], + "title": "McpServersTestResult", + "type": "object" + }, + "McpSetupRequestParams": { + "additionalProperties": false, + "properties": { + "session_id": { + "title": "Session Id", + "type": "string" + }, + "server": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Server" + }, + "action": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Action" + }, + "reason": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Reason" + } + }, + "required": [ + "session_id" + ], + "title": "McpSetupRequestParams", + "type": "object" + }, + "MessageCompletePayload": { + "additionalProperties": false, + "description": "``prompt_turn._complete_turn_payload`` / ``session_auto_continue._emit_terminal_turn_error`` /\n``agent_callbacks._mirror_subagent_to_child`` (child watch mirror: ``text`` only) /\n``compute_host_bridge`` (``text`` + ``status``).", + "properties": { + "text": { + "anyOf": [ + { + "type": "string" + }, + {} + ], + "default": "", + "title": "Text" + }, + "usage": { + "anyOf": [ + { + "$ref": "#/components/schemas/Usage" + }, + { + "type": "null" + } + ], + "default": null + }, + "status": { + "anyOf": [ + { + "$ref": "#/components/schemas/TurnStatus" + }, + { + "type": "null" + } + ], + "default": null + }, + "reasoning": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Reasoning" + }, + "warning": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Warning" + }, + "response_previewed": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Response Previewed" + }, + "billing": { + "anyOf": [ + { + "$ref": "#/components/schemas/BillingBlock" + }, + { + "type": "null" + } + ], + "default": null + }, + "failure_reason": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Failure Reason" + }, + "rendered": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Rendered" + }, + "error": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Error" + }, + "recoverable": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Recoverable" + }, + "error_surface": { + "anyOf": [ + { + "$ref": "#/components/schemas/ErrorSurface" + }, + { + "type": "null" + } + ], + "default": null + }, + "partial": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Partial" + } + }, + "title": "MessageCompletePayload", + "type": "object" + }, + "MessageInterimPayload": { + "additionalProperties": false, + "description": "``prompt_turn._interim_assistant_cb`` / ``agent_callbacks`` interim_assistant_callback.", + "properties": { + "text": { + "title": "Text", + "type": "string" + }, + "already_streamed": { + "title": "Already Streamed", + "type": "boolean" + } + }, + "required": [ + "text", + "already_streamed" + ], + "title": "MessageInterimPayload", + "type": "object" + }, + "MessageReactParams": { + "additionalProperties": false, + "description": "``row_id`` is ``messages.id``; a not-yet-persisted live message names ``newest_role`` instead.\n``emoji`` null clears; the same emoji again retracts.", + "properties": { + "session_id": { + "title": "Session Id", + "type": "string" + }, + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + }, + "row_id": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Row Id" + }, + "newest_role": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Newest Role" + }, + "emoji": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Emoji" + }, + "author": { + "anyOf": [ + { + "$ref": "#/components/schemas/ReactionAuthor" + }, + { + "type": "null" + } + ], + "default": null + } + }, + "required": [ + "session_id" + ], + "title": "MessageReactParams", + "type": "object" + }, + "MessageReactResult": { + "additionalProperties": false, + "properties": { + "row_id": { + "title": "Row Id", + "type": "integer" + }, + "reactions": { + "items": { + "$ref": "#/components/schemas/tui_gateway_contracts_billing_delegation_pets_MessageReaction" + }, + "title": "Reactions", + "type": "array" + } + }, + "required": [ + "row_id", + "reactions" + ], + "title": "MessageReactResult", + "type": "object" + }, + "MessageReactionPayload": { + "additionalProperties": false, + "description": "``tools/react_to_message_tool.py``.", + "properties": { + "row_id": { + "title": "Row Id", + "type": "integer" + }, + "reactions": { + "items": { + "$ref": "#/components/schemas/tui_gateway_contracts_events_MessageReaction" + }, + "title": "Reactions", + "type": "array" + }, + "role": { + "title": "Role", + "type": "string" + } + }, + "required": [ + "row_id", + "reactions", + "role" + ], + "title": "MessageReactionPayload", + "type": "object" + }, + "MoaAggregatingPayload": { + "additionalProperties": false, + "properties": { + "aggregator": { + "title": "Aggregator", + "type": "string" + } + }, + "required": [ + "aggregator" + ], + "title": "MoaAggregatingPayload", + "type": "object" + }, + "MoaPhasePayload": { + "additionalProperties": false, + "properties": { + "phase": { + "title": "Phase", + "type": "string" + }, + "refs_done": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Refs Done" + }, + "refs_total": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Refs Total" + }, + "aggregator": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Aggregator" + } + }, + "required": [ + "phase" + ], + "title": "MoaPhasePayload", + "type": "object" + }, + "MoaProgressPayload": { + "additionalProperties": false, + "properties": { + "label": { + "title": "Label", + "type": "string" + }, + "refs_done": { + "title": "Refs Done", + "type": "integer" + }, + "refs_total": { + "title": "Refs Total", + "type": "integer" + } + }, + "required": [ + "label", + "refs_done", + "refs_total" + ], + "title": "MoaProgressPayload", + "type": "object" + }, + "MoaReferencePayload": { + "additionalProperties": false, + "description": "``tool_progress._progress_moa_reference``.", + "properties": { + "label": { + "title": "Label", + "type": "string" + }, + "text": { + "title": "Text", + "type": "string" + }, + "index": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Index" + }, + "count": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Count" + } + }, + "required": [ + "label", + "text" + ], + "title": "MoaReferencePayload", + "type": "object" + }, + "ModelCapabilities": { + "additionalProperties": false, + "description": "``hermes_cli/inventory.py::_apply_capabilities``.", + "properties": { + "fast": { + "title": "Fast", + "type": "boolean" + }, + "reasoning": { + "title": "Reasoning", + "type": "boolean" + }, + "can_disable_reasoning": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Can Disable Reasoning" + } + }, + "required": [ + "fast", + "reasoning" + ], + "title": "ModelCapabilities", + "type": "object" + }, + "ModelDisconnectParams": { + "additionalProperties": false, + "properties": { + "slug": { + "title": "Slug", + "type": "string" + }, + "session_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Session Id" + } + }, + "required": [ + "slug" + ], + "title": "ModelDisconnectParams", + "type": "object" + }, + "ModelDisconnectResult": { + "additionalProperties": false, + "properties": { + "slug": { + "title": "Slug", + "type": "string" + }, + "name": { + "title": "Name", + "type": "string" + }, + "disconnected": { + "title": "Disconnected", + "type": "boolean" + } + }, + "required": [ + "slug", + "name", + "disconnected" + ], + "title": "ModelDisconnectResult", + "type": "object" + }, + "ModelOptionProvider": { + "additionalProperties": true, + "description": "One ``hermes_cli/inventory.py::build_models_payload`` provider row (the union of every field\nthe builder sets; ``pricing_pending`` / ``free_tier_pending`` mark the cached-only path).", + "properties": { + "slug": { + "title": "Slug", + "type": "string" + }, + "name": { + "title": "Name", + "type": "string" + }, + "models": { + "items": { + "type": "string" + }, + "title": "Models", + "type": "array" + }, + "total_models": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Total Models" + }, + "is_current": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Is Current" + }, + "is_user_defined": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Is User Defined" + }, + "source": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Source" + }, + "aliases": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Aliases" + }, + "api_url": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Api Url" + }, + "auth_type": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Auth Type" + }, + "authenticated": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Authenticated" + }, + "key_env": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Key Env" + }, + "warning": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Warning" + }, + "featured_models": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Featured Models" + }, + "capabilities": { + "anyOf": [ + { + "additionalProperties": { + "$ref": "#/components/schemas/ModelCapabilities" + }, + "type": "object" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Capabilities" + }, + "pricing": { + "anyOf": [ + { + "additionalProperties": { + "$ref": "#/components/schemas/ModelPricing" + }, + "type": "object" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Pricing" + }, + "pricing_pending": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Pricing Pending" + }, + "free_tier": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Free Tier" + }, + "free_tier_pending": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Free Tier Pending" + }, + "free_tier_row": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Free Tier Row" + }, + "unavailable_models": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Unavailable Models" + } + }, + "required": [ + "slug", + "name" + ], + "title": "ModelOptionProvider", + "type": "object" + }, + "ModelOptionsParams": { + "additionalProperties": false, + "properties": { + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + }, + "session_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Session Id" + }, + "explicit_only": { + "default": false, + "title": "Explicit Only", + "type": "boolean" + }, + "include_unconfigured": { + "default": false, + "title": "Include Unconfigured", + "type": "boolean" + }, + "refresh": { + "default": false, + "title": "Refresh", + "type": "boolean" + } + }, + "title": "ModelOptionsParams", + "type": "object" + }, + "ModelOptionsResult": { + "additionalProperties": false, + "properties": { + "providers": { + "items": { + "$ref": "#/components/schemas/ModelOptionProvider" + }, + "title": "Providers", + "type": "array" + }, + "model": { + "default": "", + "title": "Model", + "type": "string" + }, + "provider": { + "default": "", + "title": "Provider", + "type": "string" + } + }, + "required": [ + "providers" + ], + "title": "ModelOptionsResult", + "type": "object" + }, + "ModelPricing": { + "additionalProperties": false, + "description": "``hermes_cli/inventory.py::_apply_pricing`` \u2014 formatted $/Mtok strings (``\"\"`` unknown,\n``\"free\"``); the sale fields are Nous Portal-only.", + "properties": { + "input": { + "title": "Input", + "type": "string" + }, + "output": { + "title": "Output", + "type": "string" + }, + "cache": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Cache" + }, + "free": { + "title": "Free", + "type": "boolean" + }, + "discount_percent": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Discount Percent" + }, + "was_input": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Was Input" + }, + "was_output": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Was Output" + } + }, + "required": [ + "input", + "output", + "free" + ], + "title": "ModelPricing", + "type": "object" + }, + "ModelProviderRow": { + "additionalProperties": true, + "description": "One provider row of the shared inventory builder (``hermes_cli.inventory``); the closed\nset of keys is owned there.", + "properties": { + "slug": { + "title": "Slug", + "type": "string" + }, + "name": { + "default": "", + "title": "Name", + "type": "string" + }, + "is_current": { + "default": false, + "title": "Is Current", + "type": "boolean" + }, + "is_user_defined": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Is User Defined" + }, + "models": { + "items": {}, + "title": "Models", + "type": "array" + }, + "total_models": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Total Models" + }, + "authenticated": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Authenticated" + }, + "auth_type": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Auth Type" + }, + "key_env": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Key Env" + }, + "warning": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Warning" + } + }, + "required": [ + "slug" + ], + "title": "ModelProviderRow", + "type": "object" + }, + "ModelSaveKeyParams": { + "additionalProperties": false, + "properties": { + "slug": { + "title": "Slug", + "type": "string" + }, + "api_key": { + "title": "Api Key", + "type": "string" + }, + "session_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Session Id" + } + }, + "required": [ + "slug", + "api_key" + ], + "title": "ModelSaveKeyParams", + "type": "object" + }, + "ModelSaveKeyResult": { + "additionalProperties": false, + "properties": { + "provider": { + "$ref": "#/components/schemas/ModelProviderRow" + } + }, + "required": [ + "provider" + ], + "title": "ModelSaveKeyResult", + "type": "object" + }, + "NoticePayload": { + "additionalProperties": false, + "description": "``tui_gateway/model_switch.py`` capability-refresh notice.", + "properties": { + "message": { + "title": "Message", + "type": "string" + } + }, + "required": [ + "message" + ], + "title": "NoticePayload", + "type": "object" + }, + "NotificationClearPayload": { + "additionalProperties": false, + "properties": { + "key": { + "title": "Key", + "type": "string" + } + }, + "required": [ + "key" + ], + "title": "NotificationClearPayload", + "type": "object" + }, + "NotificationShowPayload": { + "additionalProperties": false, + "description": "``agent/credits_tracker.py::AgentNotice`` via notice_callback, and ``server._await_agent_ready``'s\nslow-build notice. ``level``: info | warn | error | success; ``kind``: sticky | ttl | agent.", + "properties": { + "text": { + "title": "Text", + "type": "string" + }, + "level": { + "title": "Level", + "type": "string" + }, + "kind": { + "title": "Kind", + "type": "string" + }, + "ttl_ms": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Ttl Ms" + }, + "key": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Key" + }, + "id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Id" + } + }, + "required": [ + "text", + "level", + "kind" + ], + "title": "NotificationShowPayload", + "type": "object" + }, + "OkResult": { + "additionalProperties": false, + "properties": { + "ok": { + "default": true, + "title": "Ok", + "type": "boolean" + } + }, + "title": "OkResult", + "type": "object" + }, + "OnboardingAnswers": { + "additionalProperties": true, + "description": "``tui_gateway/onboarding_personalization.py`` \u2014 the facts agreed during onboarding.", + "properties": { + "name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Name" + }, + "context": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Context" + }, + "theme": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Theme" + }, + "accent": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Accent" + }, + "layout": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Layout" + }, + "focus": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Focus" + }, + "connectors": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Connectors" + } + }, + "title": "OnboardingAnswers", + "type": "object" + }, + "OpenRequestEntry": { + "additionalProperties": false, + "description": "One unanswered server\u2192client request (``server_requests.Request.snapshot``); the reconnecting\nclient re-delivers it to its request handlers.", + "properties": { + "id": { + "title": "Id", + "type": "string" + }, + "method": { + "title": "Method", + "type": "string" + }, + "params": { + "additionalProperties": true, + "title": "Params", + "type": "object" + } + }, + "required": [ + "id", + "method", + "params" + ], + "title": "OpenRequestEntry", + "type": "object" + }, + "OptionalProjectResult": { + "additionalProperties": false, + "properties": { + "project": { + "anyOf": [ + { + "$ref": "#/components/schemas/ProjectInfo" + }, + { + "type": "null" + } + ], + "default": null + } + }, + "title": "OptionalProjectResult", + "type": "object" + }, + "PaneRevealPayload": { + "additionalProperties": true, + "description": "``tools/focus_pane_tool.py``.", + "properties": { + "pane": { + "title": "Pane", + "type": "string" + } + }, + "required": [ + "pane" + ], + "title": "PaneRevealPayload", + "type": "object" + }, + "PasteCollapseParams": { + "additionalProperties": false, + "properties": { + "text": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Text" + } + }, + "title": "PasteCollapseParams", + "type": "object" + }, + "PasteCollapseResult": { + "additionalProperties": false, + "properties": { + "placeholder": { + "title": "Placeholder", + "type": "string" + }, + "path": { + "title": "Path", + "type": "string" + }, + "lines": { + "title": "Lines", + "type": "integer" + } + }, + "required": [ + "placeholder", + "path", + "lines" + ], + "title": "PasteCollapseResult", + "type": "object" + }, + "PaymentMethodKind": { + "enum": [ + "card", + "link", + "unknown" + ], + "title": "PaymentMethodKind", + "type": "string" + }, + "PdfAttachParams": { + "additionalProperties": false, + "description": "Host ``path`` or base64 ``content_base64`` / ``data``; ``first_page`` / ``last_page`` bound the\nrender (per-call page cap enforced server-side).", + "properties": { + "session_id": { + "title": "Session Id", + "type": "string" + }, + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + }, + "path": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Path" + }, + "content_base64": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Content Base64" + }, + "data": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Data" + }, + "filename": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Filename" + }, + "first_page": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "First Page" + }, + "last_page": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Last Page" + } + }, + "required": [ + "session_id" + ], + "title": "PdfAttachParams", + "type": "object" + }, + "PdfAttachResult": { + "additionalProperties": false, + "properties": { + "attached": { + "title": "Attached", + "type": "boolean" + }, + "filename": { + "title": "Filename", + "type": "string" + }, + "pages_attached": { + "title": "Pages Attached", + "type": "integer" + }, + "pages": { + "items": { + "$ref": "#/components/schemas/PdfPage" + }, + "title": "Pages", + "type": "array" + }, + "count": { + "title": "Count", + "type": "integer" + }, + "text": { + "title": "Text", + "type": "string" + } + }, + "required": [ + "attached", + "filename", + "pages_attached", + "pages", + "count", + "text" + ], + "title": "PdfAttachResult", + "type": "object" + }, + "PdfPage": { + "additionalProperties": false, + "properties": { + "name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Name" + }, + "width": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Width" + }, + "height": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Height" + }, + "token_estimate": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Token Estimate" + }, + "path": { + "title": "Path", + "type": "string" + }, + "page": { + "title": "Page", + "type": "integer" + } + }, + "required": [ + "path", + "page" + ], + "title": "PdfPage", + "type": "object" + }, + "PeerRouteStatus": { + "additionalProperties": false, + "properties": { + "room_id": { + "title": "Room Id", + "type": "string" + }, + "member_id": { + "title": "Member Id", + "type": "string" + }, + "status": { + "title": "Status", + "type": "string" + } + }, + "required": [ + "room_id", + "member_id", + "status" + ], + "title": "PeerRouteStatus", + "type": "object" + }, + "PetCancelParams": { + "additionalProperties": false, + "properties": { + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + }, + "token": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Token" + } + }, + "title": "PetCancelParams", + "type": "object" + }, + "PetCancelResult": { + "additionalProperties": false, + "properties": { + "ok": { + "title": "Ok", + "type": "boolean" + } + }, + "required": [ + "ok" + ], + "title": "PetCancelResult", + "type": "object" + }, + "PetCellsParams": { + "additionalProperties": false, + "description": "``graphics`` opts into the kitty payload when the TTY speaks it; ``cols`` overrides the width.", + "properties": { + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + }, + "state": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "State" + }, + "cols": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Cols" + }, + "graphics": { + "default": false, + "title": "Graphics", + "type": "boolean" + } + }, + "title": "PetCellsParams", + "type": "object" + }, + "PetCellsResult": { + "additionalProperties": false, + "description": "Unicode: ``frames`` is frame \u2192 row \u2192 cell ``[tr,tg,tb,ta, br,bg,bb,ba]``; kitty (``graphics``\nset): ``frames`` are transmit escapes and ``placeholder`` the text grid.", + "properties": { + "enabled": { + "title": "Enabled", + "type": "boolean" + }, + "slug": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Slug" + }, + "displayName": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Displayname" + }, + "state": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "State" + }, + "cols": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Cols" + }, + "frameMs": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Framems" + }, + "frames": { + "anyOf": [ + { + "items": { + "items": { + "items": { + "items": { + "type": "integer" + }, + "type": "array" + }, + "type": "array" + }, + "type": "array" + }, + "type": "array" + }, + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Frames" + }, + "scale": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Scale" + }, + "graphics": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Graphics" + }, + "imageId": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Imageid" + }, + "color": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Color" + }, + "rows": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Rows" + }, + "placeholder": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Placeholder" + } + }, + "required": [ + "enabled" + ], + "title": "PetCellsResult", + "type": "object" + }, + "PetChangedPayload": { + "additionalProperties": true, + "description": "``change_watcher._pet_changed_payload`` \u2014 ``pet.info.meta``-shaped; ``{enabled: false}`` when off.", + "properties": { + "enabled": { + "title": "Enabled", + "type": "boolean" + }, + "slug": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Slug" + }, + "displayName": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Displayname" + }, + "scale": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Scale" + }, + "spritesheetRevision": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Spritesheetrevision" + } + }, + "required": [ + "enabled" + ], + "title": "PetChangedPayload", + "type": "object" + }, + "PetDraft": { + "additionalProperties": false, + "properties": { + "index": { + "title": "Index", + "type": "integer" + }, + "dataUri": { + "title": "Datauri", + "type": "string" + } + }, + "required": [ + "index", + "dataUri" + ], + "title": "PetDraft", + "type": "object" + }, + "PetExportResult": { + "additionalProperties": false, + "properties": { + "ok": { + "title": "Ok", + "type": "boolean" + }, + "filename": { + "title": "Filename", + "type": "string" + }, + "zipBase64": { + "title": "Zipbase64", + "type": "string" + } + }, + "required": [ + "ok", + "filename", + "zipBase64" + ], + "title": "PetExportResult", + "type": "object" + }, + "PetGalleryEntry": { + "additionalProperties": false, + "properties": { + "slug": { + "title": "Slug", + "type": "string" + }, + "displayName": { + "title": "Displayname", + "type": "string" + }, + "installed": { + "title": "Installed", + "type": "boolean" + }, + "spritesheetUrl": { + "default": "", + "title": "Spritesheeturl", + "type": "string" + }, + "curated": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Curated" + }, + "generated": { + "default": false, + "title": "Generated", + "type": "boolean" + } + }, + "required": [ + "slug", + "displayName", + "installed" + ], + "title": "PetGalleryEntry", + "type": "object" + }, + "PetGalleryParams": { + "additionalProperties": false, + "properties": { + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + }, + "localOnly": { + "default": false, + "title": "Localonly", + "type": "boolean" + } + }, + "title": "PetGalleryParams", + "type": "object" + }, + "PetGalleryResult": { + "additionalProperties": false, + "properties": { + "enabled": { + "title": "Enabled", + "type": "boolean" + }, + "active": { + "default": "", + "title": "Active", + "type": "string" + }, + "pets": { + "items": { + "$ref": "#/components/schemas/PetGalleryEntry" + }, + "title": "Pets", + "type": "array" + } + }, + "required": [ + "enabled" + ], + "title": "PetGalleryResult", + "type": "object" + }, + "PetGenProvider": { + "additionalProperties": false, + "description": "``agent/pet/generate/imagegen.py::list_sprite_providers`` row.", + "properties": { + "name": { + "title": "Name", + "type": "string" + }, + "label": { + "title": "Label", + "type": "string" + }, + "default": { + "type": "boolean", + "title": "Default" + } + }, + "required": [ + "name", + "label", + "default" + ], + "title": "PetGenProvider", + "type": "object" + }, + "PetGenerateParams": { + "additionalProperties": false, + "description": "``prompt`` or a ``referenceImage`` data URL is required (the handler answers 4004 without one).", + "properties": { + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + }, + "prompt": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Prompt" + }, + "referenceImage": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Referenceimage" + }, + "count": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Count" + }, + "style": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Style" + }, + "provider": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Provider" + } + }, + "title": "PetGenerateParams", + "type": "object" + }, + "PetGenerateProgressPayload": { + "additionalProperties": true, + "description": "``methods_session`` pet.generate: token-only init frame, then one per draft.", + "properties": { + "token": { + "title": "Token", + "type": "string" + }, + "count": { + "title": "Count", + "type": "integer" + }, + "index": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Index" + }, + "dataUri": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Datauri" + } + }, + "required": [ + "token", + "count" + ], + "title": "PetGenerateProgressPayload", + "type": "object" + }, + "PetGenerateResult": { + "additionalProperties": false, + "properties": { + "ok": { + "title": "Ok", + "type": "boolean" + }, + "token": { + "title": "Token", + "type": "string" + }, + "drafts": { + "items": { + "$ref": "#/components/schemas/PetDraft" + }, + "title": "Drafts", + "type": "array" + } + }, + "required": [ + "ok", + "token", + "drafts" + ], + "title": "PetGenerateResult", + "type": "object" + }, + "PetGenerateStatusResult": { + "additionalProperties": false, + "properties": { + "available": { + "title": "Available", + "type": "boolean" + }, + "providers": { + "items": { + "$ref": "#/components/schemas/PetGenProvider" + }, + "title": "Providers", + "type": "array" + } + }, + "required": [ + "available", + "providers" + ], + "title": "PetGenerateStatusResult", + "type": "object" + }, + "PetHatchParams": { + "additionalProperties": false, + "properties": { + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + }, + "token": { + "title": "Token", + "type": "string" + }, + "name": { + "title": "Name", + "type": "string" + }, + "cancelToken": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Canceltoken" + }, + "index": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Index" + }, + "description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Description" + }, + "prompt": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Prompt" + }, + "style": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Style" + }, + "provider": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Provider" + } + }, + "required": [ + "token", + "name" + ], + "title": "PetHatchParams", + "type": "object" + }, + "PetHatchProgressPayload": { + "additionalProperties": true, + "description": "``methods_session`` pet.hatch ``_on_progress``: ``{event, detail}`` or the parsed row form.", + "properties": { + "event": { + "title": "Event", + "type": "string" + }, + "detail": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Detail" + }, + "state": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "State" + }, + "done": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Done" + }, + "total": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Total" + } + }, + "required": [ + "event" + ], + "title": "PetHatchProgressPayload", + "type": "object" + }, + "PetHatchResult": { + "additionalProperties": false, + "description": "The hatched pet is installed but NOT active (``pet.select`` adopts, ``pet.remove`` discards).", + "properties": { + "ok": { + "title": "Ok", + "type": "boolean" + }, + "slug": { + "title": "Slug", + "type": "string" + }, + "displayName": { + "title": "Displayname", + "type": "string" + }, + "warnings": { + "items": {}, + "title": "Warnings", + "type": "array" + }, + "pet": { + "$ref": "#/components/schemas/PetSpritePayload" + } + }, + "required": [ + "ok", + "slug", + "displayName", + "pet" + ], + "title": "PetHatchResult", + "type": "object" + }, + "PetInfoMetaResult": { + "additionalProperties": false, + "properties": { + "enabled": { + "title": "Enabled", + "type": "boolean" + }, + "slug": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Slug" + }, + "displayName": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Displayname" + }, + "scale": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Scale" + }, + "spritesheetRevision": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Spritesheetrevision" + } + }, + "required": [ + "enabled" + ], + "title": "PetInfoMetaResult", + "type": "object" + }, + "PetInfoParams": { + "additionalProperties": false, + "description": "``knownRevision``: the spritesheet revision the caller already holds (send-once bytes).", + "properties": { + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + }, + "knownRevision": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Knownrevision" + } + }, + "title": "PetInfoParams", + "type": "object" + }, + "PetInfoResult": { + "additionalProperties": true, + "description": "``server._pet_sprite_payload`` behind ``enabled``; every sprite field is absent when the pet\ndisplay is off, ``spritesheetBase64`` is elided when ``spritesheetUnchanged``.", + "properties": { + "enabled": { + "title": "Enabled", + "type": "boolean" + }, + "slug": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Slug" + }, + "displayName": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Displayname" + }, + "mime": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Mime" + }, + "spritesheetBase64": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Spritesheetbase64" + }, + "spritesheetRevision": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Spritesheetrevision" + }, + "spritesheetUnchanged": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Spritesheetunchanged" + }, + "frameW": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Framew" + }, + "frameH": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Frameh" + }, + "framesPerState": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Framesperstate" + }, + "framesByState": { + "anyOf": [ + { + "additionalProperties": { + "type": "integer" + }, + "type": "object" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Framesbystate" + }, + "framesByRow": { + "anyOf": [ + { + "additionalProperties": { + "type": "integer" + }, + "type": "object" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Framesbyrow" + }, + "loopMs": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Loopms" + }, + "scale": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Scale" + }, + "stateRows": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Staterows" + } + }, + "required": [ + "enabled" + ], + "title": "PetInfoResult", + "type": "object" + }, + "PetRenameParams": { + "additionalProperties": false, + "properties": { + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + }, + "slug": { + "title": "Slug", + "type": "string" + }, + "name": { + "title": "Name", + "type": "string" + } + }, + "required": [ + "slug", + "name" + ], + "title": "PetRenameParams", + "type": "object" + }, + "PetScaleParams": { + "additionalProperties": false, + "properties": { + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + }, + "scale": { + "default": null, + "title": "Scale" + } + }, + "title": "PetScaleParams", + "type": "object" + }, + "PetScaleResult": { + "additionalProperties": false, + "properties": { + "ok": { + "title": "Ok", + "type": "boolean" + }, + "scale": { + "title": "Scale", + "type": "number" + } + }, + "required": [ + "ok", + "scale" + ], + "title": "PetScaleResult", + "type": "object" + }, + "PetSlugParams": { + "additionalProperties": false, + "properties": { + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + }, + "slug": { + "title": "Slug", + "type": "string" + } + }, + "required": [ + "slug" + ], + "title": "PetSlugParams", + "type": "object" + }, + "PetSlugResult": { + "additionalProperties": false, + "properties": { + "ok": { + "title": "Ok", + "type": "boolean" + }, + "slug": { + "title": "Slug", + "type": "string" + }, + "displayName": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Displayname" + } + }, + "required": [ + "ok", + "slug" + ], + "title": "PetSlugResult", + "type": "object" + }, + "PetSpritePayload": { + "additionalProperties": false, + "properties": { + "slug": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Slug" + }, + "displayName": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Displayname" + }, + "mime": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Mime" + }, + "spritesheetBase64": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Spritesheetbase64" + }, + "spritesheetRevision": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Spritesheetrevision" + }, + "frameW": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Framew" + }, + "frameH": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Frameh" + }, + "framesPerState": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Framesperstate" + }, + "framesByState": { + "anyOf": [ + { + "additionalProperties": { + "type": "integer" + }, + "type": "object" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Framesbystate" + }, + "framesByRow": { + "anyOf": [ + { + "additionalProperties": { + "type": "integer" + }, + "type": "object" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Framesbyrow" + }, + "loopMs": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Loopms" + }, + "scale": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Scale" + }, + "stateRows": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Staterows" + } + }, + "title": "PetSpritePayload", + "type": "object" + }, + "PetThumbParams": { + "additionalProperties": false, + "description": "``url``: spritesheet source for a not-yet-installed pet.", + "properties": { + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + }, + "slug": { + "title": "Slug", + "type": "string" + }, + "url": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Url" + } + }, + "required": [ + "slug" + ], + "title": "PetThumbParams", + "type": "object" + }, + "PetThumbResult": { + "additionalProperties": false, + "properties": { + "ok": { + "title": "Ok", + "type": "boolean" + }, + "slug": { + "title": "Slug", + "type": "string" + }, + "dataUri": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Datauri" + } + }, + "required": [ + "ok", + "slug" + ], + "title": "PetThumbResult", + "type": "object" + }, + "PingParams": { + "additionalProperties": false, + "properties": {}, + "title": "PingParams", + "type": "object" + }, + "PingResult": { + "additionalProperties": false, + "properties": { + "pong": { + "title": "Pong", + "type": "boolean" + } + }, + "required": [ + "pong" + ], + "title": "PingResult", + "type": "object" + }, + "PluginsAction": { + "enum": [ + "list", + "toggle", + "install", + "update" + ], + "title": "PluginsAction", + "type": "string" + }, + "PluginsListParams": { + "additionalProperties": false, + "properties": {}, + "title": "PluginsListParams", + "type": "object" + }, + "PluginsListResult": { + "additionalProperties": false, + "properties": { + "plugins": { + "items": { + "$ref": "#/components/schemas/LegacyPluginRow" + }, + "title": "Plugins", + "type": "array" + } + }, + "required": [ + "plugins" + ], + "title": "PluginsListResult", + "type": "object" + }, + "PluginsManageParams": { + "additionalProperties": false, + "description": "``toggle``: ``key``/``name`` + ``enable``; ``install``: ``identifier``/``repo`` or ``catalog_name``\n(+ ``force``, ``enable``, ``ref``); ``update``: ``name``.", + "properties": { + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + }, + "action": { + "$ref": "#/components/schemas/PluginsAction", + "default": "list" + }, + "key": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Key" + }, + "name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Name" + }, + "enable": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Enable" + }, + "identifier": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Identifier" + }, + "repo": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Repo" + }, + "catalog_name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Catalog Name" + }, + "force": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Force" + }, + "ref": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Ref" + } + }, + "title": "PluginsManageParams", + "type": "object" + }, + "PluginsManageResult": { + "additionalProperties": false, + "description": "``list`` \u2192 ``plugins`` + counts; ``toggle`` \u2192 ``ok``/``unchanged``/``name``/``plugin``;\n``install`` \u2192 ``hermes_cli.plugins_cmd.dashboard_install_plugin``'s ok payload; ``update`` \u2192\n``ok``/``unchanged``/``sha``.", + "properties": { + "plugins": { + "anyOf": [ + { + "items": { + "$ref": "#/components/schemas/AgentPluginRow" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Plugins" + }, + "user_count": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "User Count" + }, + "bundled_count": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Bundled Count" + }, + "ok": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Ok" + }, + "unchanged": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Unchanged" + }, + "name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Name" + }, + "plugin": { + "anyOf": [ + { + "$ref": "#/components/schemas/AgentPluginRow" + }, + { + "type": "null" + } + ], + "default": null + }, + "plugin_name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Plugin Name" + }, + "warnings": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Warnings" + }, + "missing_env": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Missing Env" + }, + "after_install_path": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "After Install Path" + }, + "enabled": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Enabled" + }, + "sha": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Sha" + } + }, + "title": "PluginsManageResult", + "type": "object" + }, + "PreviewActRequestParams": { + "additionalProperties": false, + "description": "``tools/drive_preview_tool.py`` and ``tools/annotate_preview_tool.py`` field sets.", + "properties": { + "session_id": { + "title": "Session Id", + "type": "string" + }, + "action": { + "title": "Action", + "type": "string" + }, + "ref": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Ref" + }, + "selector": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Selector" + }, + "text": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Text" + }, + "key": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Key" + }, + "submit": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Submit" + }, + "full": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Full" + }, + "to": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "To" + }, + "amount": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Amount" + }, + "max": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Max" + } + }, + "required": [ + "session_id", + "action" + ], + "title": "PreviewActRequestParams", + "type": "object" + }, + "PreviewClosePayload": { + "additionalProperties": false, + "description": "``tools/preview_tool.py`` / ``tools/close_preview_tool.py``; ``url`` '' closes every tab.", + "properties": { + "url": { + "default": "", + "title": "Url", + "type": "string" + } + }, + "title": "PreviewClosePayload", + "type": "object" + }, + "PreviewOpenPayload": { + "additionalProperties": false, + "description": "``tools/open_preview_tool.py``.", + "properties": { + "url": { + "title": "Url", + "type": "string" + }, + "label": { + "default": "", + "title": "Label", + "type": "string" + } + }, + "required": [ + "url" + ], + "title": "PreviewOpenPayload", + "type": "object" + }, + "PreviewRestartParams": { + "additionalProperties": false, + "properties": { + "session_id": { + "title": "Session Id", + "type": "string" + }, + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + }, + "url": { + "title": "Url", + "type": "string" + }, + "cwd": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Cwd" + }, + "context": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Context" + } + }, + "required": [ + "session_id", + "url" + ], + "title": "PreviewRestartParams", + "type": "object" + }, + "PreviewRestartProgressPayload": { + "additionalProperties": false, + "description": "``methods_prompt`` restart body + ``agent_callbacks._preview_restart_callbacks``.", + "properties": { + "task_id": { + "title": "Task Id", + "type": "string" + }, + "text": { + "title": "Text", + "type": "string" + }, + "level": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Level" + } + }, + "required": [ + "task_id", + "text" + ], + "title": "PreviewRestartProgressPayload", + "type": "object" + }, + "ProcessEntry": { + "additionalProperties": true, + "description": "``tools/process_registry.py::list_sessions`` row plus the gateway's ``output_tail``.", + "properties": { + "session_id": { + "title": "Session Id", + "type": "string" + }, + "command": { + "default": "", + "title": "Command", + "type": "string" + }, + "cwd": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Cwd" + }, + "pid": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Pid" + }, + "owner_task_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Owner Task Id" + }, + "started_at": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Started At" + }, + "uptime_seconds": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Uptime Seconds" + }, + "status": { + "default": "running", + "title": "Status", + "type": "string" + }, + "output_preview": { + "default": "", + "title": "Output Preview", + "type": "string" + }, + "output_tail": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Output Tail" + }, + "session_scoped": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Session Scoped" + }, + "watch_patterns": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Watch Patterns" + }, + "watch_hit": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Watch Hit" + }, + "notify_on_complete": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Notify On Complete" + }, + "exit_code": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Exit Code" + }, + "detached": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Detached" + } + }, + "required": [ + "session_id" + ], + "title": "ProcessEntry", + "type": "object" + }, + "ProcessKillParams": { + "additionalProperties": false, + "properties": { + "session_id": { + "title": "Session Id", + "type": "string" + }, + "process_id": { + "title": "Process Id", + "type": "string" + }, + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + } + }, + "required": [ + "session_id", + "process_id" + ], + "title": "ProcessKillParams", + "type": "object" + }, + "ProcessKillResult": { + "additionalProperties": true, + "description": "``tools/process_registry.py::kill_process`` snapshot; ``error`` rides on the failure statuses.", + "properties": { + "status": { + "$ref": "#/components/schemas/ProcessKillStatus" + }, + "session_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Session Id" + }, + "command": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Command" + }, + "exit_code": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Exit Code" + }, + "completion_reason": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Completion Reason" + }, + "termination_source": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Termination Source" + }, + "output": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Output" + }, + "error": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Error" + } + }, + "required": [ + "status" + ], + "title": "ProcessKillResult", + "type": "object" + }, + "ProcessKillStatus": { + "enum": [ + "killed", + "already_exited", + "not_found", + "error" + ], + "title": "ProcessKillStatus", + "type": "string" + }, + "ProcessListParams": { + "additionalProperties": false, + "properties": { + "session_id": { + "title": "Session Id", + "type": "string" + }, + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + } + }, + "required": [ + "session_id" + ], + "title": "ProcessListParams", + "type": "object" + }, + "ProcessListResult": { + "additionalProperties": false, + "properties": { + "processes": { + "items": { + "$ref": "#/components/schemas/ProcessEntry" + }, + "title": "Processes", + "type": "array" + } + }, + "title": "ProcessListResult", + "type": "object" + }, + "ProcessStopParams": { + "additionalProperties": false, + "properties": { + "session_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Session Id" + }, + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + } + }, + "title": "ProcessStopParams", + "type": "object" + }, + "ProcessStopResult": { + "additionalProperties": false, + "properties": { + "killed": { + "title": "Killed", + "type": "integer" + } + }, + "required": [ + "killed" + ], + "title": "ProcessStopResult", + "type": "object" + }, + "ProfileCanonicalSession": { + "additionalProperties": false, + "description": "The profile's \"Bot Chat\" registry row; ``resolved_id`` is the live compression tip.", + "properties": { + "id": { + "title": "Id", + "type": "string" + }, + "resolved_id": { + "title": "Resolved Id", + "type": "string" + }, + "root_title": { + "default": "", + "title": "Root Title", + "type": "string" + }, + "title": { + "default": "", + "title": "Title", + "type": "string" + }, + "preview": { + "default": "", + "title": "Preview", + "type": "string" + }, + "started_at": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "integer" + } + ], + "default": 0, + "title": "Started At" + }, + "last_active": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "integer" + } + ], + "default": 0, + "title": "Last Active" + }, + "message_count": { + "default": 0, + "title": "Message Count", + "type": "integer" + } + }, + "required": [ + "id", + "resolved_id" + ], + "title": "ProfileCanonicalSession", + "type": "object" + }, + "ProfileMirrored": { + "additionalProperties": false, + "description": "What was copied from the launch profile; ``auth`` is ``\"shared\"`` under ``share_auth``.", + "properties": { + "env": { + "default": false, + "title": "Env", + "type": "boolean" + }, + "auth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "const": "shared", + "type": "string" + } + ], + "default": false, + "title": "Auth" + }, + "model_inherited": { + "default": false, + "title": "Model Inherited", + "type": "boolean" + }, + "voice": { + "default": false, + "title": "Voice", + "type": "boolean" + } + }, + "title": "ProfileMirrored", + "type": "object" + }, + "ProfileModelPin": { + "additionalProperties": false, + "properties": { + "provider": { + "default": "", + "title": "Provider", + "type": "string" + }, + "default": { + "type": "string", + "default": "", + "title": "Default" + } + }, + "title": "ProfileModelPin", + "type": "object" + }, + "ProfileNameParams": { + "additionalProperties": false, + "properties": { + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + }, + "name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Name" + } + }, + "title": "ProfileNameParams", + "type": "object" + }, + "ProfileParams": { + "additionalProperties": false, + "description": "Any method the desktop may route to a named profile (``requestGatewayForProfile`` adds ``profile``).", + "properties": { + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + } + }, + "title": "ProfileParams", + "type": "object" + }, + "ProfileRow": { + "additionalProperties": false, + "description": "One roster row; the session fields are present only with ``include_sessions``.", + "properties": { + "name": { + "title": "Name", + "type": "string" + }, + "path": { + "title": "Path", + "type": "string" + }, + "is_default": { + "default": false, + "title": "Is Default", + "type": "boolean" + }, + "model": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Model" + }, + "provider": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Provider" + }, + "description": { + "default": "", + "title": "Description", + "type": "string" + }, + "display_name": { + "default": "", + "title": "Display Name", + "type": "string" + }, + "skill_count": { + "default": 0, + "title": "Skill Count", + "type": "integer" + }, + "last_session": { + "anyOf": [ + { + "$ref": "#/components/schemas/ProfileSessionPreview" + }, + { + "type": "null" + } + ], + "default": null + }, + "worker_session": { + "anyOf": [ + { + "$ref": "#/components/schemas/ProfileWorkerSession" + }, + { + "type": "null" + } + ], + "default": null + }, + "canonical_session": { + "anyOf": [ + { + "$ref": "#/components/schemas/ProfileCanonicalSession" + }, + { + "type": "null" + } + ], + "default": null + }, + "ui_meta_revisions": { + "additionalProperties": { + "type": "integer" + }, + "title": "Ui Meta Revisions", + "type": "object" + }, + "ui_meta": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Ui Meta" + }, + "has_avatar": { + "default": false, + "title": "Has Avatar", + "type": "boolean" + } + }, + "required": [ + "name", + "path" + ], + "title": "ProfileRow", + "type": "object" + }, + "ProfileSessionPreview": { + "additionalProperties": false, + "description": "Newest human-facing session of a profile (``_latest_profile_session_rows``).", + "properties": { + "id": { + "title": "Id", + "type": "string" + }, + "title": { + "default": "", + "title": "Title", + "type": "string" + }, + "preview": { + "default": "", + "title": "Preview", + "type": "string" + }, + "started_at": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "integer" + } + ], + "default": 0, + "title": "Started At" + }, + "last_active": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "integer" + } + ], + "default": 0, + "title": "Last Active" + }, + "message_count": { + "default": 0, + "title": "Message Count", + "type": "integer" + } + }, + "required": [ + "id" + ], + "title": "ProfileSessionPreview", + "type": "object" + }, + "ProfileWorkerSession": { + "additionalProperties": false, + "description": "Newest kanban/tool worker row, so rosters can show a profile as working.", + "properties": { + "id": { + "title": "Id", + "type": "string" + }, + "source": { + "default": "", + "title": "Source", + "type": "string" + }, + "title": { + "default": "", + "title": "Title", + "type": "string" + }, + "last_active": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "integer" + } + ], + "default": 0, + "title": "Last Active" + } + }, + "required": [ + "id" + ], + "title": "ProfileWorkerSession", + "type": "object" + }, + "ProfilesConfigureApplied": { + "additionalProperties": false, + "description": "Per-section outcome; only the sections the request carried are present.", + "properties": { + "ui_meta": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Ui Meta" + }, + "ui_meta_revisions": { + "anyOf": [ + { + "additionalProperties": { + "type": "integer" + }, + "type": "object" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Ui Meta Revisions" + }, + "ui_meta_conflicts": { + "anyOf": [ + { + "additionalProperties": { + "$ref": "#/components/schemas/UiMetaConflict" + }, + "type": "object" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Ui Meta Conflicts" + }, + "soul": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Soul" + }, + "description": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Description" + }, + "model": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Model" + }, + "skills": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Skills" + }, + "toolsets": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Toolsets" + }, + "mcp_servers": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Mcp Servers" + } + }, + "title": "ProfilesConfigureApplied", + "type": "object" + }, + "ProfilesConfigureParams": { + "additionalProperties": false, + "description": "Sections are independent; ``ui_meta_expected_revisions`` is a per-key compare-and-swap.", + "properties": { + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + }, + "name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Name" + }, + "ui_meta": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Ui Meta" + }, + "ui_meta_expected_revisions": { + "anyOf": [ + { + "additionalProperties": { + "type": "integer" + }, + "type": "object" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Ui Meta Expected Revisions" + }, + "soul": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Soul" + }, + "description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Description" + }, + "model": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Model" + }, + "provider": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Provider" + }, + "confirm_expensive_model": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Confirm Expensive Model" + }, + "disabled_skills": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Disabled Skills" + }, + "enabled_toolsets": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Enabled Toolsets" + }, + "enabled_mcp_servers": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Enabled Mcp Servers" + } + }, + "title": "ProfilesConfigureParams", + "type": "object" + }, + "ProfilesConfigureResult": { + "additionalProperties": false, + "description": "``confirm_required`` mirrors ``config.set``: a guarded model pick wrote nothing yet.", + "properties": { + "ok": { + "title": "Ok", + "type": "boolean" + }, + "applied": { + "$ref": "#/components/schemas/ProfilesConfigureApplied" + }, + "confirm_required": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Confirm Required" + }, + "confirm_message": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Confirm Message" + } + }, + "required": [ + "ok", + "applied" + ], + "title": "ProfilesConfigureResult", + "type": "object" + }, + "ProfilesCreateParams": { + "additionalProperties": false, + "description": "``clone_from`` omitted = fresh profile + bundled skills; ``mirror_credentials`` defaults on\nso a headless bot has a provider.", + "properties": { + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + }, + "name": { + "title": "Name", + "type": "string" + }, + "description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Description" + }, + "clone_from": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Clone From" + }, + "clone_all": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Clone All" + }, + "clone_channels": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Clone Channels" + }, + "no_skills": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "No Skills" + }, + "no_alias": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "No Alias" + }, + "soul": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Soul" + }, + "model": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Model" + }, + "provider": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Provider" + }, + "share_auth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Share Auth" + }, + "mirror_credentials": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Mirror Credentials" + } + }, + "required": [ + "name" + ], + "title": "ProfilesCreateParams", + "type": "object" + }, + "ProfilesCreateResult": { + "additionalProperties": false, + "properties": { + "ok": { + "default": true, + "title": "Ok", + "type": "boolean" + }, + "name": { + "title": "Name", + "type": "string" + }, + "path": { + "title": "Path", + "type": "string" + }, + "soul_written": { + "default": false, + "title": "Soul Written", + "type": "boolean" + }, + "model_set": { + "default": false, + "title": "Model Set", + "type": "boolean" + }, + "mirrored": { + "$ref": "#/components/schemas/ProfileMirrored" + } + }, + "required": [ + "name", + "path", + "mirrored" + ], + "title": "ProfilesCreateResult", + "type": "object" + }, + "ProfilesDescribeResult": { + "additionalProperties": false, + "description": "Editor snapshot; ``toolsets_pinned`` says whether ``tools.enabled_toolsets`` is explicit.", + "properties": { + "name": { + "title": "Name", + "type": "string" + }, + "description": { + "default": "", + "title": "Description", + "type": "string" + }, + "soul": { + "default": "", + "title": "Soul", + "type": "string" + }, + "model": { + "$ref": "#/components/schemas/ProfileModelPin" + }, + "skills": { + "items": { + "$ref": "#/components/schemas/CapabilityEntry" + }, + "title": "Skills", + "type": "array" + }, + "toolsets": { + "items": { + "$ref": "#/components/schemas/ToolsetEntry" + }, + "title": "Toolsets", + "type": "array" + }, + "toolsets_pinned": { + "default": false, + "title": "Toolsets Pinned", + "type": "boolean" + }, + "mcp_servers": { + "items": { + "$ref": "#/components/schemas/McpServerEntry" + }, + "title": "Mcp Servers", + "type": "array" + } + }, + "required": [ + "name", + "model" + ], + "title": "ProfilesDescribeResult", + "type": "object" + }, + "ProfilesGetAssetParams": { + "additionalProperties": false, + "properties": { + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + }, + "name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Name" + }, + "asset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Asset" + } + }, + "title": "ProfilesGetAssetParams", + "type": "object" + }, + "ProfilesGetAssetResult": { + "additionalProperties": false, + "description": "Absent is ``found: false``, not an error.", + "properties": { + "found": { + "title": "Found", + "type": "boolean" + }, + "mime": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Mime" + }, + "size": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Size" + }, + "data": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Data" + } + }, + "required": [ + "found" + ], + "title": "ProfilesGetAssetResult", + "type": "object" + }, + "ProfilesListParams": { + "additionalProperties": false, + "properties": { + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + }, + "include_sessions": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Include Sessions" + } + }, + "title": "ProfilesListParams", + "type": "object" + }, + "ProfilesListResult": { + "additionalProperties": false, + "description": "``bot_mode_protocol`` tells clients this backend injects the teammate protocol itself.", + "properties": { + "profiles": { + "items": { + "$ref": "#/components/schemas/ProfileRow" + }, + "title": "Profiles", + "type": "array" + }, + "bot_mode_protocol": { + "default": true, + "title": "Bot Mode Protocol", + "type": "boolean" + } + }, + "title": "ProfilesListResult", + "type": "object" + }, + "ProfilesRememberOnboardingParams": { + "additionalProperties": false, + "properties": { + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + }, + "answers": { + "anyOf": [ + { + "$ref": "#/components/schemas/OnboardingAnswers" + }, + { + "type": "null" + } + ], + "default": null + } + }, + "title": "ProfilesRememberOnboardingParams", + "type": "object" + }, + "ProfilesRememberOnboardingResult": { + "additionalProperties": false, + "properties": { + "saved": { + "default": true, + "title": "Saved", + "type": "boolean" + }, + "profile": { + "default": "default", + "title": "Profile", + "type": "string" + }, + "target": { + "default": "user", + "title": "Target", + "type": "string" + } + }, + "title": "ProfilesRememberOnboardingResult", + "type": "object" + }, + "ProfilesSetAssetParams": { + "additionalProperties": false, + "description": "``data`` is a data URL or bare base64 (PNG/JPEG/WebP, sniffed); ``clear`` deletes instead.", + "properties": { + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + }, + "name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Name" + }, + "asset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Asset" + }, + "data": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Data" + }, + "clear": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Clear" + } + }, + "title": "ProfilesSetAssetParams", + "type": "object" + }, + "ProfilesSetAssetResult": { + "additionalProperties": false, + "properties": { + "ok": { + "default": true, + "title": "Ok", + "type": "boolean" + }, + "asset": { + "title": "Asset", + "type": "string" + }, + "size": { + "default": 0, + "title": "Size", + "type": "integer" + }, + "removed": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Removed" + } + }, + "required": [ + "asset" + ], + "title": "ProfilesSetAssetResult", + "type": "object" + }, + "ProjectFacts": { + "additionalProperties": false, + "description": "``agent/coding_context.py::project_facts_for`` \u2014 the system prompt's coding-context detection.", + "properties": { + "root": { + "title": "Root", + "type": "string" + }, + "manifests": { + "items": { + "type": "string" + }, + "title": "Manifests", + "type": "array" + }, + "packageManagers": { + "items": { + "type": "string" + }, + "title": "Packagemanagers", + "type": "array" + }, + "verifyCommands": { + "items": { + "type": "string" + }, + "title": "Verifycommands", + "type": "array" + }, + "contextFiles": { + "items": { + "type": "string" + }, + "title": "Contextfiles", + "type": "array" + } + }, + "required": [ + "root", + "manifests", + "packageManagers", + "verifyCommands", + "contextFiles" + ], + "title": "ProjectFacts", + "type": "object" + }, + "ProjectFactsParams": { + "additionalProperties": false, + "properties": { + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + }, + "cwd": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Cwd" + } + }, + "title": "ProjectFactsParams", + "type": "object" + }, + "ProjectFactsResult": { + "additionalProperties": false, + "description": "``facts`` null outside a workspace (or when detection failed).", + "properties": { + "facts": { + "anyOf": [ + { + "$ref": "#/components/schemas/ProjectFacts" + }, + { + "type": "null" + } + ], + "default": null + } + }, + "title": "ProjectFactsResult", + "type": "object" + }, + "ProjectFolder": { + "additionalProperties": false, + "description": "``hermes_cli/projects_db.py::ProjectFolder.to_dict``.", + "properties": { + "path": { + "title": "Path", + "type": "string" + }, + "label": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Label" + }, + "is_primary": { + "default": false, + "title": "Is Primary", + "type": "boolean" + }, + "added_at": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Added At" + } + }, + "required": [ + "path" + ], + "title": "ProjectFolder", + "type": "object" + }, + "ProjectFolderParams": { + "additionalProperties": false, + "properties": { + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + }, + "id": { + "title": "Id", + "type": "string" + }, + "path": { + "title": "Path", + "type": "string" + } + }, + "required": [ + "id", + "path" + ], + "title": "ProjectFolderParams", + "type": "object" + }, + "ProjectIdParams": { + "additionalProperties": false, + "description": "Any method addressed at one stored project (``5062`` when the id resolves to nothing).", + "properties": { + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + }, + "id": { + "title": "Id", + "type": "string" + } + }, + "required": [ + "id" + ], + "title": "ProjectIdParams", + "type": "object" + }, + "ProjectInfo": { + "additionalProperties": false, + "description": "``hermes_cli/projects_db.py::Project.to_dict`` \u2014 one stored project with its folders.", + "properties": { + "id": { + "title": "Id", + "type": "string" + }, + "slug": { + "title": "Slug", + "type": "string" + }, + "name": { + "title": "Name", + "type": "string" + }, + "description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Description" + }, + "icon": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Icon" + }, + "color": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Color" + }, + "board_slug": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Board Slug" + }, + "primary_path": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Primary Path" + }, + "archived": { + "default": false, + "title": "Archived", + "type": "boolean" + }, + "created_at": { + "title": "Created At", + "type": "integer" + }, + "folders": { + "items": { + "$ref": "#/components/schemas/ProjectFolder" + }, + "title": "Folders", + "type": "array" + } + }, + "required": [ + "id", + "slug", + "name", + "created_at" + ], + "title": "ProjectInfo", + "type": "object" + }, + "ProjectRef": { + "additionalProperties": false, + "description": "``tui_gateway/server.py::_project_info_for_cwd``.", + "properties": { + "id": { + "title": "Id", + "type": "string" + }, + "slug": { + "title": "Slug", + "type": "string" + }, + "name": { + "title": "Name", + "type": "string" + }, + "primary_path": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Primary Path" + } + }, + "required": [ + "id", + "slug", + "name" + ], + "title": "ProjectRef", + "type": "object" + }, + "ProjectResult": { + "additionalProperties": false, + "properties": { + "project": { + "$ref": "#/components/schemas/ProjectInfo" + } + }, + "required": [ + "project" + ], + "title": "ProjectResult", + "type": "object" + }, + "ProjectTreeLane": { + "additionalProperties": false, + "description": "One branch / worktree / kanban lane inside a repo; ``sessions`` is empty unless hydrated.", + "properties": { + "id": { + "title": "Id", + "type": "string" + }, + "label": { + "title": "Label", + "type": "string" + }, + "path": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Path" + }, + "isMain": { + "default": false, + "title": "Ismain", + "type": "boolean" + }, + "isKanban": { + "default": false, + "title": "Iskanban", + "type": "boolean" + }, + "sessions": { + "items": { + "$ref": "#/components/schemas/ProjectTreeSession" + }, + "title": "Sessions", + "type": "array" + } + }, + "required": [ + "id", + "label" + ], + "title": "ProjectTreeLane", + "type": "object" + }, + "ProjectTreeNode": { + "additionalProperties": false, + "description": "``project_tree._project_node`` \u2014 explicit, auto (git root) or the synthetic Home bucket.", + "properties": { + "id": { + "title": "Id", + "type": "string" + }, + "label": { + "title": "Label", + "type": "string" + }, + "path": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Path" + }, + "color": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Color" + }, + "icon": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Icon" + }, + "isAuto": { + "default": false, + "title": "Isauto", + "type": "boolean" + }, + "isNoProject": { + "default": false, + "title": "Isnoproject", + "type": "boolean" + }, + "sessionCount": { + "default": 0, + "title": "Sessioncount", + "type": "integer" + }, + "lastActive": { + "default": 0.0, + "title": "Lastactive", + "type": "number" + }, + "totalTokens": { + "default": 0, + "title": "Totaltokens", + "type": "integer" + }, + "totalCostUsd": { + "default": 0.0, + "title": "Totalcostusd", + "type": "number" + }, + "repos": { + "items": { + "$ref": "#/components/schemas/ProjectTreeRepo" + }, + "title": "Repos", + "type": "array" + }, + "previewSessions": { + "items": { + "$ref": "#/components/schemas/ProjectTreeSession" + }, + "title": "Previewsessions", + "type": "array" + } + }, + "required": [ + "id", + "label" + ], + "title": "ProjectTreeNode", + "type": "object" + }, + "ProjectTreeRepo": { + "additionalProperties": false, + "properties": { + "id": { + "title": "Id", + "type": "string" + }, + "label": { + "title": "Label", + "type": "string" + }, + "path": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Path" + }, + "groups": { + "items": { + "$ref": "#/components/schemas/ProjectTreeLane" + }, + "title": "Groups", + "type": "array" + }, + "sessionCount": { + "default": 0, + "title": "Sessioncount", + "type": "integer" + } + }, + "required": [ + "id", + "label" + ], + "title": "ProjectTreeRepo", + "type": "object" + }, + "ProjectTreeSession": { + "additionalProperties": true, + "description": "``methods_projects._project_tree_row`` + ``project_tree.stamp_profile``: the minimal row the\nsidebar renders, stamped with the profile it belongs to.", + "properties": { + "id": { + "title": "Id", + "type": "string" + }, + "title": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Title" + }, + "preview": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Preview" + }, + "source": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Source" + }, + "model": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Model" + }, + "started_at": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Started At" + }, + "ended_at": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Ended At" + }, + "last_active": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Last Active" + }, + "message_count": { + "default": 0, + "title": "Message Count", + "type": "integer" + }, + "tool_call_count": { + "default": 0, + "title": "Tool Call Count", + "type": "integer" + }, + "input_tokens": { + "default": 0, + "title": "Input Tokens", + "type": "integer" + }, + "output_tokens": { + "default": 0, + "title": "Output Tokens", + "type": "integer" + }, + "is_active": { + "default": false, + "title": "Is Active", + "type": "boolean" + }, + "cwd": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Cwd" + }, + "git_branch": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Git Branch" + }, + "git_repo_root": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Git Repo Root" + }, + "parent_session_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Parent Session Id" + }, + "pinned": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Pinned" + }, + "unread": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Unread" + }, + "archived": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Archived" + }, + "actual_cost_usd": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Actual Cost Usd" + }, + "estimated_cost_usd": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Estimated Cost Usd" + }, + "handoff_platform": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Handoff Platform" + }, + "handoff_state": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Handoff State" + }, + "_lineage_root_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Lineage Root Id" + }, + "_lineage_ids": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Lineage Ids" + }, + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + } + }, + "required": [ + "id" + ], + "title": "ProjectTreeSession", + "type": "object" + }, + "ProjectsAddFolderParams": { + "additionalProperties": false, + "properties": { + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + }, + "id": { + "title": "Id", + "type": "string" + }, + "path": { + "title": "Path", + "type": "string" + }, + "label": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Label" + }, + "is_primary": { + "default": false, + "title": "Is Primary", + "type": "boolean" + } + }, + "required": [ + "id", + "path" + ], + "title": "ProjectsAddFolderParams", + "type": "object" + }, + "ProjectsArchiveParams": { + "additionalProperties": false, + "properties": { + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + }, + "id": { + "title": "Id", + "type": "string" + }, + "restore": { + "default": false, + "title": "Restore", + "type": "boolean" + } + }, + "required": [ + "id" + ], + "title": "ProjectsArchiveParams", + "type": "object" + }, + "ProjectsCreateParams": { + "additionalProperties": false, + "description": "``use`` also activates the new project.", + "properties": { + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + }, + "name": { + "title": "Name", + "type": "string" + }, + "folders": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Folders" + }, + "slug": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Slug" + }, + "primary_path": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Primary Path" + }, + "description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Description" + }, + "icon": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Icon" + }, + "color": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Color" + }, + "board_slug": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Board Slug" + }, + "use": { + "default": false, + "title": "Use", + "type": "boolean" + } + }, + "required": [ + "name" + ], + "title": "ProjectsCreateParams", + "type": "object" + }, + "ProjectsDiscoverReposParams": { + "additionalProperties": false, + "description": "``scan`` asks the host to walk the policy roots itself (remote-gateway desktop).", + "properties": { + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + }, + "scan": { + "default": false, + "title": "Scan", + "type": "boolean" + } + }, + "title": "ProjectsDiscoverReposParams", + "type": "object" + }, + "ProjectsDiscoverReposResult": { + "additionalProperties": false, + "properties": { + "repos": { + "items": { + "$ref": "#/components/schemas/DiscoveredRepo" + }, + "title": "Repos", + "type": "array" + }, + "discovery_policy": { + "anyOf": [ + { + "$ref": "#/components/schemas/RepoDiscoveryPolicy" + }, + { + "type": "null" + } + ], + "default": null + } + }, + "required": [ + "repos" + ], + "title": "ProjectsDiscoverReposResult", + "type": "object" + }, + "ProjectsForCwdParams": { + "additionalProperties": false, + "description": "Absent ``cwd`` resolves the gateway's default completion cwd.", + "properties": { + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + }, + "cwd": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Cwd" + } + }, + "title": "ProjectsForCwdParams", + "type": "object" + }, + "ProjectsForCwdResult": { + "additionalProperties": false, + "properties": { + "project": { + "anyOf": [ + { + "$ref": "#/components/schemas/ProjectInfo" + }, + { + "type": "null" + } + ], + "default": null + }, + "cwd": { + "title": "Cwd", + "type": "string" + }, + "branch": { + "default": "", + "title": "Branch", + "type": "string" + } + }, + "required": [ + "cwd" + ], + "title": "ProjectsForCwdResult", + "type": "object" + }, + "ProjectsPayload": { + "additionalProperties": false, + "description": "``methods_projects._projects_payload``: every project (archived included) + the active id.", + "properties": { + "projects": { + "items": { + "$ref": "#/components/schemas/ProjectInfo" + }, + "title": "Projects", + "type": "array" + }, + "active_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Active Id" + } + }, + "required": [ + "projects" + ], + "title": "ProjectsPayload", + "type": "object" + }, + "ProjectsProjectSessionsParams": { + "additionalProperties": false, + "properties": { + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + }, + "project_id": { + "title": "Project Id", + "type": "string" + }, + "session_limit": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Session Limit" + } + }, + "required": [ + "project_id" + ], + "title": "ProjectsProjectSessionsParams", + "type": "object" + }, + "ProjectsProjectSessionsResult": { + "additionalProperties": false, + "properties": { + "project": { + "anyOf": [ + { + "$ref": "#/components/schemas/ProjectTreeNode" + }, + { + "type": "null" + } + ], + "default": null + } + }, + "title": "ProjectsProjectSessionsResult", + "type": "object" + }, + "ProjectsRecordReposParams": { + "additionalProperties": false, + "description": "Repos as ``{root, label}`` objects or bare root strings; entries without a root are skipped.", + "properties": { + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + }, + "repos": { + "anyOf": [ + { + "items": { + "anyOf": [ + { + "$ref": "#/components/schemas/RecordRepoItem" + }, + { + "type": "string" + } + ] + }, + "type": "array" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Repos" + }, + "discovery_policy": { + "anyOf": [ + { + "$ref": "#/components/schemas/RepoDiscoveryPolicyParams" + }, + { + "type": "null" + } + ], + "default": null + } + }, + "title": "ProjectsRecordReposParams", + "type": "object" + }, + "ProjectsRecordReposResult": { + "additionalProperties": false, + "properties": { + "repos": { + "items": { + "$ref": "#/components/schemas/DiscoveredRepo" + }, + "title": "Repos", + "type": "array" + }, + "discovery_policy": { + "anyOf": [ + { + "$ref": "#/components/schemas/RepoDiscoveryPolicy" + }, + { + "type": "null" + } + ], + "default": null + }, + "accepted": { + "title": "Accepted", + "type": "boolean" + } + }, + "required": [ + "repos", + "accepted" + ], + "title": "ProjectsRecordReposResult", + "type": "object" + }, + "ProjectsSetActiveParams": { + "additionalProperties": false, + "description": "No ``id`` (or null) clears the active project.", + "properties": { + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + }, + "id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Id" + } + }, + "title": "ProjectsSetActiveParams", + "type": "object" + }, + "ProjectsTreeParams": { + "additionalProperties": false, + "properties": { + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + }, + "preview_limit": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Preview Limit" + }, + "session_limit": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Session Limit" + } + }, + "title": "ProjectsTreeParams", + "type": "object" + }, + "ProjectsTreeResult": { + "additionalProperties": false, + "properties": { + "projects": { + "items": { + "$ref": "#/components/schemas/ProjectTreeNode" + }, + "title": "Projects", + "type": "array" + }, + "active_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Active Id" + }, + "scoped_session_ids": { + "items": { + "type": "string" + }, + "title": "Scoped Session Ids", + "type": "array" + } + }, + "required": [ + "projects" + ], + "title": "ProjectsTreeResult", + "type": "object" + }, + "ProjectsUpdateParams": { + "additionalProperties": false, + "description": "Absent keys are left untouched; ``''`` clears ``color`` / ``icon``.", + "properties": { + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + }, + "id": { + "title": "Id", + "type": "string" + }, + "name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Name" + }, + "description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Description" + }, + "icon": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Icon" + }, + "color": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Color" + }, + "board_slug": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Board Slug" + } + }, + "required": [ + "id" + ], + "title": "ProjectsUpdateParams", + "type": "object" + }, + "PromptSubmitParams": { + "additionalProperties": false, + "description": "``text`` is normally a string; the relay / hosted paths may hand a structured (parts list)\npayload, and the busy path renders it. Truncation (rewind / edit / regenerate) needs explicit\nconsent: ``confirm_truncate`` plus one durable target (``truncate_before_row_id`` preferred,\n``truncate_before_message_id``, or the legacy ``truncate_before_user_ordinal``).", + "properties": { + "session_id": { + "title": "Session Id", + "type": "string" + }, + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + }, + "text": { + "default": "", + "title": "Text" + }, + "display_kind": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Display Kind" + }, + "interrupted": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Interrupted" + }, + "queued": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Queued" + }, + "surface": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Surface" + }, + "voice_context": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Voice Context" + }, + "truncate_before_user_ordinal": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Truncate Before User Ordinal" + }, + "truncate_before_row_id": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Truncate Before Row Id" + }, + "truncate_before_message_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Truncate Before Message Id" + }, + "confirm_truncate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Confirm Truncate" + }, + "confirm_empty_truncate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Confirm Empty Truncate" + }, + "rebind_survivor_row_ids": { + "anyOf": [ + { + "items": { + "type": "integer" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Rebind Survivor Row Ids" + } + }, + "required": [ + "session_id" + ], + "title": "PromptSubmitParams", + "type": "object" + }, + "PromptSubmitResult": { + "additionalProperties": false, + "description": "``status`` is absent only on the typed-stop-phrase reply (``voice_stopped``). After a\ntruncation the survivor row ids let the client rebind its cached ``rowId``s (``None`` map\nentries: drop the cached id). ``turn_isolation`` marks a compute-host dispatch.", + "properties": { + "status": { + "anyOf": [ + { + "$ref": "#/components/schemas/PromptSubmitStatus" + }, + { + "type": "null" + } + ], + "default": null + }, + "voice_stopped": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Voice Stopped" + }, + "survivor_user_row_ids": { + "anyOf": [ + { + "items": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ] + }, + "type": "array" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Survivor User Row Ids" + }, + "survivor_row_id_map": { + "anyOf": [ + { + "additionalProperties": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ] + }, + "type": "object" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Survivor Row Id Map" + }, + "turn_isolation": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Turn Isolation" + } + }, + "title": "PromptSubmitResult", + "type": "object" + }, + "PromptSubmitStatus": { + "enum": [ + "streaming", + "queued", + "steered", + "redirected" + ], + "title": "PromptSubmitStatus", + "type": "string" + }, + "QueuedPrompt": { + "additionalProperties": false, + "properties": { + "user": { + "title": "User", + "type": "string" + } + }, + "required": [ + "user" + ], + "title": "QueuedPrompt", + "type": "object" + }, + "ReactionAuthor": { + "enum": [ + "user", + "agent" + ], + "title": "ReactionAuthor", + "type": "string" + }, + "ReactionPayload": { + "additionalProperties": false, + "description": "``agent_callbacks`` reaction_callback.", + "properties": { + "kind": { + "title": "Kind", + "type": "string" + } + }, + "required": [ + "kind" + ], + "title": "ReactionPayload", + "type": "object" + }, + "ReadRangeRequestParams": { + "additionalProperties": false, + "properties": { + "session_id": { + "title": "Session Id", + "type": "string" + }, + "start": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Start" + }, + "count": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Count" + } + }, + "required": [ + "session_id" + ], + "title": "ReadRangeRequestParams", + "type": "object" + }, + "RecordRepoItem": { + "additionalProperties": false, + "properties": { + "root": { + "title": "Root", + "type": "string" + }, + "label": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Label" + } + }, + "required": [ + "root" + ], + "title": "RecordRepoItem", + "type": "object" + }, + "RelayAgentRow": { + "additionalProperties": true, + "description": "A roster row the Desktop pushes (``tools/bot_relay.py::_normalize_roster_row``); invalid\nrows are dropped server-side, so the shape stays open.", + "properties": { + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + }, + "handle": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Handle" + }, + "connection_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Connection Id" + }, + "connection_label": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Connection Label" + }, + "title": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Title" + }, + "description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Description" + }, + "online": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Online" + } + }, + "title": "RelayAgentRow", + "type": "object" + }, + "RelayEnvelope": { + "additionalProperties": true, + "description": "``tools/bot_relay.py::enqueue_envelope``.", + "properties": { + "id": { + "title": "Id", + "type": "string" + }, + "created_at": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "number" + } + ], + "title": "Created At" + }, + "from_profile": { + "title": "From Profile", + "type": "string" + }, + "from_handle": { + "title": "From Handle", + "type": "string" + }, + "target_connection": { + "title": "Target Connection", + "type": "string" + }, + "target_profile": { + "title": "Target Profile", + "type": "string" + }, + "target_handle": { + "title": "Target Handle", + "type": "string" + }, + "message": { + "title": "Message", + "type": "string" + } + }, + "required": [ + "id", + "created_at", + "from_profile", + "from_handle", + "target_connection", + "target_profile", + "target_handle", + "message" + ], + "title": "RelayEnvelope", + "type": "object" + }, + "ReloadEnvParams": { + "additionalProperties": false, + "properties": {}, + "title": "ReloadEnvParams", + "type": "object" + }, + "ReloadEnvResult": { + "additionalProperties": false, + "properties": { + "updated": { + "title": "Updated", + "type": "integer" + } + }, + "required": [ + "updated" + ], + "title": "ReloadEnvResult", + "type": "object" + }, + "ReloadMcpParams": { + "additionalProperties": false, + "description": "Without ``confirm`` the handler may answer ``confirm_required`` (per ``approvals.mcp_reload_confirm``);\n``always`` persists the opt-out; ``rev`` is the config revision the caller wants loaded (coalescing).", + "properties": { + "session_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Session Id" + }, + "confirm": { + "default": false, + "title": "Confirm", + "type": "boolean" + }, + "always": { + "default": false, + "title": "Always", + "type": "boolean" + }, + "rev": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Rev" + } + }, + "title": "ReloadMcpParams", + "type": "object" + }, + "ReloadMcpResult": { + "additionalProperties": false, + "properties": { + "status": { + "$ref": "#/components/schemas/ReloadMcpStatus" + }, + "message": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Message" + }, + "loaded_rev": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Loaded Rev" + }, + "coalesced": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Coalesced" + }, + "turn_isolation": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Turn Isolation" + }, + "host_ack": { + "anyOf": [ + {}, + { + "type": "null" + } + ], + "default": null, + "title": "Host Ack" + } + }, + "required": [ + "status" + ], + "title": "ReloadMcpResult", + "type": "object" + }, + "ReloadMcpStatus": { + "enum": [ + "confirm_required", + "reloaded" + ], + "title": "ReloadMcpStatus", + "type": "string" + }, + "RepoDiscoveryPolicy": { + "additionalProperties": false, + "description": "``methods_projects._repo_discovery_policy`` \u2014 the effective ``desktop.repo_scan_*`` config.", + "properties": { + "enabled": { + "title": "Enabled", + "type": "boolean" + }, + "roots": { + "items": { + "type": "string" + }, + "title": "Roots", + "type": "array" + }, + "exclude_paths": { + "items": { + "type": "string" + }, + "title": "Exclude Paths", + "type": "array" + } + }, + "required": [ + "enabled", + "roots", + "exclude_paths" + ], + "title": "RepoDiscoveryPolicy", + "type": "object" + }, + "RepoDiscoveryPolicyParams": { + "additionalProperties": false, + "description": "The policy the desktop scanned under (short or ``repo_scan_*`` long keys both accepted).", + "properties": { + "enabled": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Enabled" + }, + "roots": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Roots" + }, + "exclude_paths": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Exclude Paths" + }, + "repo_scan_enabled": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Repo Scan Enabled" + }, + "repo_scan_roots": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Repo Scan Roots" + }, + "repo_scan_exclude_paths": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Repo Scan Exclude Paths" + } + }, + "title": "RepoDiscoveryPolicyParams", + "type": "object" + }, + "RequestAnswerParams": { + "additionalProperties": false, + "properties": { + "id": { + "title": "Id", + "type": "string" + }, + "result": { + "additionalProperties": true, + "title": "Result", + "type": "object" + }, + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + } + }, + "required": [ + "id", + "result" + ], + "title": "RequestAnswerParams", + "type": "object" + }, + "RequestAnswerResult": { + "additionalProperties": false, + "properties": { + "status": { + "$ref": "#/components/schemas/ClarifyLockStatus" + } + }, + "required": [ + "status" + ], + "title": "RequestAnswerResult", + "type": "object" + }, + "RequestCancelPayload": { + "additionalProperties": false, + "properties": { + "id": { + "title": "Id", + "type": "string" + }, + "method": { + "title": "Method", + "type": "string" + }, + "reason": { + "title": "Reason", + "type": "string" + } + }, + "required": [ + "id", + "method", + "reason" + ], + "title": "RequestCancelPayload", + "type": "object" + }, + "ResumePhaseStatus": { + "enum": [ + "loading", + "complete", + "failed" + ], + "title": "ResumePhaseStatus", + "type": "string" + }, + "ReviewSummaryPayload": { + "additionalProperties": false, + "description": "``server`` background_review_callback.", + "properties": { + "text": { + "title": "Text", + "type": "string" + } + }, + "required": [ + "text" + ], + "title": "ReviewSummaryPayload", + "type": "object" + }, + "RollbackCheckpoint": { + "additionalProperties": false, + "properties": { + "hash": { + "default": "", + "title": "Hash", + "type": "string" + }, + "timestamp": { + "default": "", + "title": "Timestamp", + "type": "string" + }, + "message": { + "default": "", + "title": "Message", + "type": "string" + } + }, + "title": "RollbackCheckpoint", + "type": "object" + }, + "RollbackDiffParams": { + "additionalProperties": false, + "properties": { + "session_id": { + "title": "Session Id", + "type": "string" + }, + "hash": { + "title": "Hash", + "type": "string" + }, + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + } + }, + "required": [ + "session_id", + "hash" + ], + "title": "RollbackDiffParams", + "type": "object" + }, + "RollbackDiffResult": { + "additionalProperties": false, + "properties": { + "stat": { + "default": "", + "title": "Stat", + "type": "string" + }, + "diff": { + "default": "", + "title": "Diff", + "type": "string" + }, + "rendered": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Rendered" + } + }, + "title": "RollbackDiffResult", + "type": "object" + }, + "RollbackListParams": { + "additionalProperties": false, + "properties": { + "session_id": { + "title": "Session Id", + "type": "string" + }, + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + } + }, + "required": [ + "session_id" + ], + "title": "RollbackListParams", + "type": "object" + }, + "RollbackListResult": { + "additionalProperties": false, + "properties": { + "enabled": { + "title": "Enabled", + "type": "boolean" + }, + "checkpoints": { + "items": { + "$ref": "#/components/schemas/RollbackCheckpoint" + }, + "title": "Checkpoints", + "type": "array" + } + }, + "required": [ + "enabled" + ], + "title": "RollbackListResult", + "type": "object" + }, + "RollbackRestoreParams": { + "additionalProperties": false, + "properties": { + "session_id": { + "title": "Session Id", + "type": "string" + }, + "hash": { + "title": "Hash", + "type": "string" + }, + "file_path": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "File Path" + }, + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + } + }, + "required": [ + "session_id", + "hash" + ], + "title": "RollbackRestoreParams", + "type": "object" + }, + "RollbackRestoreResult": { + "additionalProperties": true, + "description": "``tools/checkpoint_manager.py::restore`` outcome; ``history_removed`` is added for a full\n(non-file) restore that also rewound the live transcript.", + "properties": { + "success": { + "title": "Success", + "type": "boolean" + }, + "restored_to": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Restored To" + }, + "reason": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Reason" + }, + "directory": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Directory" + }, + "file": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "File" + }, + "restored_files": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Restored Files" + }, + "skipped_user_edits": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Skipped User Edits" + }, + "skipped_oversize": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Skipped Oversize" + }, + "failed_deletes": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Failed Deletes" + }, + "history_removed": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "History Removed" + }, + "error": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Error" + }, + "debug": { + "anyOf": [ + {}, + { + "type": "null" + } + ], + "default": null, + "title": "Debug" + } + }, + "required": [ + "success" + ], + "title": "RollbackRestoreResult", + "type": "object" + }, + "Room": { + "additionalProperties": false, + "description": "``gateway/hosted_rooms.py::_room_from_row`` plus the branch-only keys ``create`` (legacy\nadoption), ``state`` (``authority_claim``) and ``rename`` (``event``) add.", + "properties": { + "room_id": { + "title": "Room Id", + "type": "string" + }, + "name": { + "title": "Name", + "type": "string" + }, + "members": { + "items": { + "$ref": "#/components/schemas/RoomMember" + }, + "title": "Members", + "type": "array" + }, + "authority_gateway_id": { + "title": "Authority Gateway Id", + "type": "string" + }, + "authority_epoch": { + "title": "Authority Epoch", + "type": "integer" + }, + "revision": { + "title": "Revision", + "type": "integer" + }, + "created_at": { + "title": "Created At", + "type": "number" + }, + "updated_at": { + "title": "Updated At", + "type": "number" + }, + "idempotent": { + "default": false, + "title": "Idempotent", + "type": "boolean" + }, + "disbanded_at": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Disbanded At" + }, + "latest_seq": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Latest Seq" + }, + "adopted": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Adopted" + }, + "claim_event": { + "anyOf": [ + { + "$ref": "#/components/schemas/RoomEvent" + }, + { + "type": "null" + } + ], + "default": null + }, + "authority_claim": { + "anyOf": [ + { + "$ref": "#/components/schemas/RoomEvent" + }, + { + "type": "null" + } + ], + "default": null + }, + "event": { + "anyOf": [ + { + "$ref": "#/components/schemas/RoomEvent" + }, + { + "type": "null" + } + ], + "default": null + } + }, + "required": [ + "room_id", + "name", + "members", + "authority_gateway_id", + "authority_epoch", + "revision", + "created_at", + "updated_at" + ], + "title": "Room", + "type": "object" + }, + "RoomActor": { + "additionalProperties": false, + "properties": { + "kind": { + "title": "Kind", + "type": "string" + }, + "id": { + "title": "Id", + "type": "string" + } + }, + "required": [ + "kind", + "id" + ], + "title": "RoomActor", + "type": "object" + }, + "RoomAuthority": { + "additionalProperties": false, + "properties": { + "gateway_id": { + "title": "Gateway Id", + "type": "string" + }, + "epoch": { + "title": "Epoch", + "type": "integer" + } + }, + "required": [ + "gateway_id", + "epoch" + ], + "title": "RoomAuthority", + "type": "object" + }, + "RoomDriverStatus": { + "additionalProperties": false, + "description": "``HostedRoomService.status(room_id)``; ``pending_actions`` rows are ``{kind: retry, task_id}``\nor the driver's approval action (``kind: approval`` + run/session/approval context).", + "properties": { + "running": { + "title": "Running", + "type": "boolean" + }, + "working": { + "title": "Working", + "type": "boolean" + }, + "blocked": { + "title": "Blocked", + "type": "boolean" + }, + "counts": { + "additionalProperties": { + "type": "integer" + }, + "title": "Counts", + "type": "object" + }, + "pending_actions": { + "items": { + "additionalProperties": true, + "type": "object" + }, + "title": "Pending Actions", + "type": "array" + }, + "peer_routes": { + "items": { + "$ref": "#/components/schemas/PeerRouteStatus" + }, + "title": "Peer Routes", + "type": "array" + } + }, + "required": [ + "running", + "working", + "blocked", + "counts", + "pending_actions", + "peer_routes" + ], + "title": "RoomDriverStatus", + "type": "object" + }, + "RoomEvent": { + "additionalProperties": false, + "description": "``gateway/hosted_rooms.py::_event_from_row``.", + "properties": { + "room_id": { + "title": "Room Id", + "type": "string" + }, + "seq": { + "title": "Seq", + "type": "integer" + }, + "event_id": { + "title": "Event Id", + "type": "string" + }, + "kind": { + "title": "Kind", + "type": "string" + }, + "actor": { + "$ref": "#/components/schemas/RoomActor" + }, + "authority_epoch": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Authority Epoch" + }, + "payload": { + "additionalProperties": true, + "title": "Payload", + "type": "object" + }, + "created_at": { + "title": "Created At", + "type": "number" + }, + "idempotent": { + "default": false, + "title": "Idempotent", + "type": "boolean" + } + }, + "required": [ + "room_id", + "seq", + "event_id", + "kind", + "actor", + "payload", + "created_at" + ], + "title": "RoomEvent", + "type": "object" + }, + "RoomExecutionPolicy": { + "additionalProperties": false, + "description": "``gateway/hosted_room_execution_policy.py::execution_policy_mapping``.", + "properties": { + "version": { + "title": "Version", + "type": "integer" + }, + "target_profile": { + "title": "Target Profile", + "type": "string" + }, + "enabled_toolsets": { + "items": { + "type": "string" + }, + "title": "Enabled Toolsets", + "type": "array" + }, + "approval_mode": { + "title": "Approval Mode", + "type": "string" + }, + "max_iterations": { + "title": "Max Iterations", + "type": "integer" + }, + "policy_digest": { + "title": "Policy Digest", + "type": "string" + } + }, + "required": [ + "version", + "target_profile", + "enabled_toolsets", + "approval_mode", + "max_iterations", + "policy_digest" + ], + "title": "RoomExecutionPolicy", + "type": "object" + }, + "RoomLinkCatalog": { + "additionalProperties": false, + "description": "``gateway/hosted_room_peer.py::GatewayRoomCatalog.as_mapping``.", + "properties": { + "installation_id": { + "title": "Installation Id", + "type": "string" + }, + "protocol_versions": { + "items": { + "type": "integer" + }, + "title": "Protocol Versions", + "type": "array" + }, + "link_modes": { + "items": { + "type": "string" + }, + "title": "Link Modes", + "type": "array" + }, + "persistent_process": { + "title": "Persistent Process", + "type": "boolean" + }, + "text": { + "title": "Text", + "type": "boolean" + }, + "attachments": { + "title": "Attachments", + "type": "boolean" + }, + "execution_policy": { + "$ref": "#/components/schemas/RoomExecutionPolicy" + }, + "catalog_digest": { + "title": "Catalog Digest", + "type": "string" + }, + "endpoint": { + "anyOf": [ + { + "$ref": "#/components/schemas/RoomLinkEndpoint" + }, + { + "type": "null" + } + ], + "default": null + } + }, + "required": [ + "installation_id", + "protocol_versions", + "link_modes", + "persistent_process", + "text", + "attachments", + "execution_policy", + "catalog_digest" + ], + "title": "RoomLinkCatalog", + "type": "object" + }, + "RoomLinkEndpoint": { + "additionalProperties": false, + "description": "``GatewayRoomCatalog.endpoint_mapping``: ``url``/``transport_security`` when available,\n``reason`` when not.", + "properties": { + "available": { + "title": "Available", + "type": "boolean" + }, + "url": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Url" + }, + "transport_security": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Transport Security" + }, + "reason": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Reason" + } + }, + "required": [ + "available" + ], + "title": "RoomLinkEndpoint", + "type": "object" + }, + "RoomLinkStatus": { + "additionalProperties": false, + "description": "``enabled`` with ``profile``/``catalog``/``endpoint``, or disabled with a ``reason``.", + "properties": { + "enabled": { + "title": "Enabled", + "type": "boolean" + }, + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + }, + "catalog": { + "anyOf": [ + { + "$ref": "#/components/schemas/RoomLinkCatalog" + }, + { + "type": "null" + } + ], + "default": null + }, + "endpoint": { + "anyOf": [ + { + "$ref": "#/components/schemas/RoomLinkEndpoint" + }, + { + "type": "null" + } + ], + "default": null + }, + "reason": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Reason" + } + }, + "required": [ + "enabled" + ], + "title": "RoomLinkStatus", + "type": "object" + }, + "RoomMember": { + "additionalProperties": true, + "description": "One roster row (``hosted_room_discussion.validate_roster``); legacy rooms may carry\npre-normalisation rows, so the set stays open.", + "properties": { + "member_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Member Id" + }, + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + }, + "handle": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Handle" + }, + "display_name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Display Name" + }, + "target": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Target" + } + }, + "title": "RoomMember", + "type": "object" + }, + "RoomMemberInput": { + "additionalProperties": true, + "description": "A roster row as the client proposes it; ``validate_roster`` owns the exact rules.", + "properties": { + "member_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Member Id" + }, + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + }, + "handle": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Handle" + }, + "display_name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Display Name" + }, + "target": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Target" + } + }, + "title": "RoomMemberInput", + "type": "object" + }, + "RoomTaskReceipt": { + "additionalProperties": false, + "properties": { + "room_id": { + "title": "Room Id", + "type": "string" + }, + "task_id": { + "title": "Task Id", + "type": "string" + }, + "thread_id": { + "title": "Thread Id", + "type": "string" + }, + "turn_id": { + "title": "Turn Id", + "type": "string" + }, + "status": { + "title": "Status", + "type": "string" + }, + "execution_generation": { + "title": "Execution Generation", + "type": "integer" + }, + "cancel_generation": { + "title": "Cancel Generation", + "type": "integer" + } + }, + "required": [ + "room_id", + "task_id", + "thread_id", + "turn_id", + "status", + "execution_generation", + "cancel_generation" + ], + "title": "RoomTaskReceipt", + "type": "object" + }, + "RoomTombstone": { + "additionalProperties": false, + "properties": { + "room_id": { + "title": "Room Id", + "type": "string" + }, + "disbanded_at": { + "title": "Disbanded At", + "type": "number" + }, + "idempotent": { + "title": "Idempotent", + "type": "boolean" + }, + "history_expired": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "History Expired" + }, + "event": { + "anyOf": [ + { + "$ref": "#/components/schemas/RoomEvent" + }, + { + "type": "null" + } + ], + "default": null + } + }, + "required": [ + "room_id", + "disbanded_at", + "idempotent" + ], + "title": "RoomTombstone", + "type": "object" + }, + "SecretRequestParams": { + "additionalProperties": false, + "properties": { + "session_id": { + "title": "Session Id", + "type": "string" + }, + "env_var": { + "title": "Env Var", + "type": "string" + }, + "prompt": { + "title": "Prompt", + "type": "string" + }, + "metadata": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Metadata" + } + }, + "required": [ + "session_id", + "env_var", + "prompt" + ], + "title": "SecretRequestParams", + "type": "object" + }, + "SeedMessage": { + "additionalProperties": false, + "description": "One create-time transcript row (``session_history._coerce_seed_history``); ``text`` is the\nlegacy alias of ``content``; only ``display_kind: \"hidden\"`` is accepted from the wire.", + "properties": { + "role": { + "title": "Role", + "type": "string" + }, + "content": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Content" + }, + "text": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Text" + }, + "display_kind": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Display Kind" + } + }, + "required": [ + "role" + ], + "title": "SeedMessage", + "type": "object" + }, + "SessionActivateParams": { + "additionalProperties": false, + "properties": { + "session_id": { + "title": "Session Id", + "type": "string" + }, + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + }, + "cols": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Cols" + }, + "omit_messages": { + "default": false, + "title": "Omit Messages", + "type": "boolean" + } + }, + "required": [ + "session_id" + ], + "title": "SessionActivateParams", + "type": "object" + }, + "SessionActivateResult": { + "additionalProperties": false, + "properties": { + "session_id": { + "title": "Session Id", + "type": "string" + }, + "message_count": { + "title": "Message Count", + "type": "integer" + }, + "messages": { + "items": { + "$ref": "#/components/schemas/TranscriptMessage" + }, + "title": "Messages", + "type": "array" + }, + "info": { + "$ref": "#/components/schemas/SessionLiveInfo" + }, + "stored_session_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Stored Session Id" + }, + "resumed": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Resumed" + }, + "session_key": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Session Key" + }, + "messages_omitted": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Messages Omitted" + }, + "hydrating": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Hydrating" + }, + "running": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Running" + }, + "turn_started_at": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Turn Started At" + }, + "started_at": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Started At" + }, + "status": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Status" + }, + "inflight": { + "anyOf": [ + { + "$ref": "#/components/schemas/InflightTurn" + }, + { + "type": "null" + } + ], + "default": null + }, + "queued": { + "anyOf": [ + { + "$ref": "#/components/schemas/QueuedPrompt" + }, + { + "type": "null" + } + ], + "default": null + }, + "pending_approval": { + "anyOf": [ + { + "$ref": "#/components/schemas/tui_gateway_contracts_sessions_PendingApproval" + }, + { + "type": "null" + } + ], + "default": null + }, + "open_requests": { + "anyOf": [ + { + "items": { + "$ref": "#/components/schemas/OpenRequestEntry" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Open Requests" + }, + "todo_state": { + "anyOf": [ + { + "$ref": "#/components/schemas/TodoState" + }, + { + "type": "null" + } + ], + "default": null + }, + "auto_continue": { + "anyOf": [ + { + "$ref": "#/components/schemas/AutoContinue" + }, + { + "type": "null" + } + ], + "default": null + } + }, + "required": [ + "session_id", + "message_count", + "messages", + "info" + ], + "title": "SessionActivateResult", + "type": "object" + }, + "SessionActiveItem": { + "additionalProperties": false, + "description": "``server._session_live_item``.", + "properties": { + "current": { + "title": "Current", + "type": "boolean" + }, + "id": { + "title": "Id", + "type": "string" + }, + "last_active": { + "title": "Last Active", + "type": "number" + }, + "message_count": { + "title": "Message Count", + "type": "integer" + }, + "model": { + "title": "Model", + "type": "string" + }, + "preview": { + "title": "Preview", + "type": "string" + }, + "session_key": { + "title": "Session Key", + "type": "string" + }, + "started_at": { + "title": "Started At", + "type": "number" + }, + "status": { + "$ref": "#/components/schemas/LiveSessionStatus" + }, + "title": { + "title": "Title", + "type": "string" + } + }, + "required": [ + "current", + "id", + "last_active", + "message_count", + "model", + "preview", + "session_key", + "started_at", + "status", + "title" + ], + "title": "SessionActiveItem", + "type": "object" + }, + "SessionActiveListParams": { + "additionalProperties": false, + "properties": { + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + }, + "current_session_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Current Session Id" + } + }, + "title": "SessionActiveListParams", + "type": "object" + }, + "SessionActiveListResult": { + "additionalProperties": false, + "properties": { + "sessions": { + "items": { + "$ref": "#/components/schemas/SessionActiveItem" + }, + "title": "Sessions", + "type": "array" + } + }, + "required": [ + "sessions" + ], + "title": "SessionActiveListResult", + "type": "object" + }, + "SessionBranchParams": { + "additionalProperties": false, + "properties": { + "session_id": { + "title": "Session Id", + "type": "string" + }, + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + }, + "name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Name" + }, + "count": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Count" + } + }, + "required": [ + "session_id" + ], + "title": "SessionBranchParams", + "type": "object" + }, + "SessionBranchResult": { + "additionalProperties": false, + "properties": { + "session_id": { + "title": "Session Id", + "type": "string" + }, + "stored_session_id": { + "title": "Stored Session Id", + "type": "string" + }, + "title": { + "title": "Title", + "type": "string" + }, + "parent": { + "title": "Parent", + "type": "string" + }, + "message_count": { + "title": "Message Count", + "type": "integer" + }, + "messages": { + "items": { + "$ref": "#/components/schemas/TranscriptMessage" + }, + "title": "Messages", + "type": "array" + }, + "info": { + "$ref": "#/components/schemas/SessionLiveInfo" + } + }, + "required": [ + "session_id", + "stored_session_id", + "title", + "parent", + "message_count", + "messages", + "info" + ], + "title": "SessionBranchResult", + "type": "object" + }, + "SessionCloseParams": { + "additionalProperties": false, + "properties": { + "session_id": { + "title": "Session Id", + "type": "string" + }, + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + } + }, + "required": [ + "session_id" + ], + "title": "SessionCloseParams", + "type": "object" + }, + "SessionCloseResult": { + "additionalProperties": false, + "properties": { + "closed": { + "title": "Closed", + "type": "boolean" + } + }, + "required": [ + "closed" + ], + "title": "SessionCloseResult", + "type": "object" + }, + "SessionCompressParams": { + "additionalProperties": false, + "properties": { + "session_id": { + "title": "Session Id", + "type": "string" + }, + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + }, + "focus_topic": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Focus Topic" + } + }, + "required": [ + "session_id" + ], + "title": "SessionCompressParams", + "type": "object" + }, + "SessionCompressResult": { + "additionalProperties": true, + "description": "In-process: the before/after summary + replacement transcript. Compute host: its result passes\nthrough (hence open) with ``turn_isolation``; a lock held elsewhere answers ``compressed: false``.", + "properties": { + "status": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Status" + }, + "removed": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Removed" + }, + "before_messages": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Before Messages" + }, + "after_messages": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "After Messages" + }, + "before_tokens": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Before Tokens" + }, + "after_tokens": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "After Tokens" + }, + "summary": { + "anyOf": [ + { + "$ref": "#/components/schemas/CompressionSummary" + }, + { + "type": "null" + } + ], + "default": null + }, + "usage": { + "anyOf": [ + { + "$ref": "#/components/schemas/Usage" + }, + { + "type": "null" + } + ], + "default": null + }, + "info": { + "anyOf": [ + { + "$ref": "#/components/schemas/SessionLiveInfo" + }, + { + "type": "null" + } + ], + "default": null + }, + "messages": { + "anyOf": [ + { + "items": { + "$ref": "#/components/schemas/TranscriptMessage" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Messages" + }, + "compressed": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Compressed" + }, + "lock_held": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Lock Held" + }, + "message": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Message" + }, + "turn_isolation": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Turn Isolation" + }, + "host_ack": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Host Ack" + } + }, + "title": "SessionCompressResult", + "type": "object" + }, + "SessionContextBreakdownParams": { + "additionalProperties": false, + "properties": { + "session_id": { + "title": "Session Id", + "type": "string" + }, + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + } + }, + "required": [ + "session_id" + ], + "title": "SessionContextBreakdownParams", + "type": "object" + }, + "SessionContextBreakdownResult": { + "additionalProperties": false, + "description": "``agent.context_breakdown.compute_session_context_breakdown`` (empty categories before the agent builds).", + "properties": { + "categories": { + "items": { + "$ref": "#/components/schemas/ContextCategory" + }, + "title": "Categories", + "type": "array" + }, + "context_max": { + "title": "Context Max", + "type": "integer" + }, + "context_percent": { + "title": "Context Percent", + "type": "integer" + }, + "context_used": { + "title": "Context Used", + "type": "integer" + }, + "estimated_total": { + "title": "Estimated Total", + "type": "integer" + }, + "context_estimated": { + "title": "Context Estimated", + "type": "boolean" + }, + "context_source": { + "title": "Context Source", + "type": "string" + }, + "model": { + "title": "Model", + "type": "string" + } + }, + "required": [ + "categories", + "context_max", + "context_percent", + "context_used", + "estimated_total", + "context_estimated", + "context_source", + "model" + ], + "title": "SessionContextBreakdownResult", + "type": "object" + }, + "SessionControlArgs": { + "additionalProperties": false, + "description": "``subgoal.add`` reads ``text``; ``subgoal.remove`` reads the 1-based ``index``.", + "properties": { + "text": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Text" + }, + "index": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Index" + } + }, + "title": "SessionControlArgs", + "type": "object" + }, + "SessionControlDispatch": { + "additionalProperties": false, + "description": "``_dispatch_envelope`` \u2014 the command result's user-visible envelope, every key always present.", + "properties": { + "type": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Type" + }, + "output": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Output" + }, + "notice": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Notice" + }, + "message": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Message" + }, + "display": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Display" + } + }, + "required": [ + "type", + "output", + "notice", + "message", + "display" + ], + "title": "SessionControlDispatch", + "type": "object" + }, + "SessionControlParams": { + "additionalProperties": false, + "description": "``action`` is validated by the handler (unknown / gate actions answer ``4004``), so it stays a\nstring on the wire; ``SessionControlAction`` lists the accepted set.", + "properties": { + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + }, + "session_id": { + "title": "Session Id", + "type": "string" + }, + "action": { + "title": "Action", + "type": "string" + }, + "args": { + "anyOf": [ + { + "$ref": "#/components/schemas/SessionControlArgs" + }, + { + "type": "null" + } + ], + "default": null + } + }, + "required": [ + "session_id", + "action" + ], + "title": "SessionControlParams", + "type": "object" + }, + "SessionControlReadParams": { + "additionalProperties": false, + "properties": { + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + }, + "session_id": { + "title": "Session Id", + "type": "string" + } + }, + "required": [ + "session_id" + ], + "title": "SessionControlReadParams", + "type": "object" + }, + "SessionControlReadResult": { + "additionalProperties": false, + "properties": { + "control": { + "$ref": "#/components/schemas/tui_gateway_contracts_config_free_tier_control_SessionControlSnapshot" + } + }, + "required": [ + "control" + ], + "title": "SessionControlReadResult", + "type": "object" + }, + "SessionControlResult": { + "additionalProperties": false, + "properties": { + "control": { + "$ref": "#/components/schemas/tui_gateway_contracts_config_free_tier_control_SessionControlSnapshot" + }, + "dispatch": { + "$ref": "#/components/schemas/SessionControlDispatch" + } + }, + "required": [ + "control", + "dispatch" + ], + "title": "SessionControlResult", + "type": "object" + }, + "SessionControlUpdatePayload": { + "additionalProperties": false, + "properties": { + "control": { + "$ref": "#/components/schemas/tui_gateway_contracts_events_SessionControlSnapshot" + } + }, + "required": [ + "control" + ], + "title": "SessionControlUpdatePayload", + "type": "object" + }, + "SessionCorrectionParams": { + "additionalProperties": false, + "properties": { + "session_id": { + "title": "Session Id", + "type": "string" + }, + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + }, + "text": { + "title": "Text", + "type": "string" + } + }, + "required": [ + "session_id", + "text" + ], + "title": "SessionCorrectionParams", + "type": "object" + }, + "SessionCorrectionResult": { + "additionalProperties": false, + "properties": { + "status": { + "$ref": "#/components/schemas/CorrectionStatus" + }, + "text": { + "title": "Text", + "type": "string" + } + }, + "required": [ + "status", + "text" + ], + "title": "SessionCorrectionResult", + "type": "object" + }, + "SessionCreateParams": { + "additionalProperties": false, + "properties": { + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + }, + "cols": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Cols" + }, + "source": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Source" + }, + "cwd": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Cwd" + }, + "messages": { + "anyOf": [ + { + "items": { + "$ref": "#/components/schemas/SeedMessage" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Messages" + }, + "parent_session_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Parent Session Id" + }, + "title": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Title" + }, + "model": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Model" + }, + "provider": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Provider" + }, + "reasoning_effort": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Reasoning Effort" + }, + "fast": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Fast" + }, + "close_on_disconnect": { + "default": false, + "title": "Close On Disconnect", + "type": "boolean" + }, + "hidden": { + "default": false, + "title": "Hidden", + "type": "boolean" + }, + "room_plumbing": { + "default": false, + "title": "Room Plumbing", + "type": "boolean" + }, + "follow_profile_config": { + "default": false, + "title": "Follow Profile Config", + "type": "boolean" + } + }, + "title": "SessionCreateParams", + "type": "object" + }, + "SessionCreateResult": { + "additionalProperties": false, + "properties": { + "session_id": { + "title": "Session Id", + "type": "string" + }, + "stored_session_id": { + "title": "Stored Session Id", + "type": "string" + }, + "message_count": { + "title": "Message Count", + "type": "integer" + }, + "messages": { + "items": { + "$ref": "#/components/schemas/TranscriptMessage" + }, + "title": "Messages", + "type": "array" + }, + "info": { + "$ref": "#/components/schemas/SessionLiveInfo" + } + }, + "required": [ + "session_id", + "stored_session_id", + "message_count", + "messages", + "info" + ], + "title": "SessionCreateResult", + "type": "object" + }, + "SessionCwdSetParams": { + "additionalProperties": false, + "properties": { + "session_id": { + "title": "Session Id", + "type": "string" + }, + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + }, + "cwd": { + "title": "Cwd", + "type": "string" + } + }, + "required": [ + "session_id", + "cwd" + ], + "title": "SessionCwdSetParams", + "type": "object" + }, + "SessionCwdSetResult": { + "additionalProperties": true, + "description": "The refreshed ``session.info`` view (full agent view, or the lazy shape).", + "properties": { + "model": { + "default": "", + "title": "Model", + "type": "string" + }, + "provider": { + "default": "", + "title": "Provider", + "type": "string" + }, + "reasoning_effort": { + "default": "", + "title": "Reasoning Effort", + "type": "string" + }, + "service_tier": { + "default": "", + "title": "Service Tier", + "type": "string" + }, + "fast": { + "default": false, + "title": "Fast", + "type": "boolean" + }, + "yolo": { + "default": false, + "title": "Yolo", + "type": "boolean" + }, + "approval_mode": { + "default": "manual", + "title": "Approval Mode", + "type": "string" + }, + "tools": { + "additionalProperties": { + "items": { + "type": "string" + }, + "type": "array" + }, + "title": "Tools", + "type": "object" + }, + "skills": { + "additionalProperties": true, + "title": "Skills", + "type": "object" + }, + "cwd": { + "default": "", + "title": "Cwd", + "type": "string" + }, + "branch": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Branch" + }, + "project": { + "anyOf": [ + { + "$ref": "#/components/schemas/ProjectRef" + }, + { + "type": "null" + } + ], + "default": null + }, + "terminal_backend": { + "default": "", + "title": "Terminal Backend", + "type": "string" + }, + "personality": { + "default": "", + "title": "Personality", + "type": "string" + }, + "running": { + "default": false, + "title": "Running", + "type": "boolean" + }, + "turn_started_at": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Turn Started At" + }, + "title": { + "default": "", + "title": "Title", + "type": "string" + }, + "stored_session_id": { + "default": "", + "title": "Stored Session Id", + "type": "string" + }, + "desktop_contract": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Desktop Contract" + }, + "version": { + "default": "", + "title": "Version", + "type": "string" + }, + "release_date": { + "default": "", + "title": "Release Date", + "type": "string" + }, + "update_behind": { + "anyOf": [ + {}, + { + "type": "null" + } + ], + "default": null, + "title": "Update Behind" + }, + "update_command": { + "default": "", + "title": "Update Command", + "type": "string" + }, + "usage": { + "anyOf": [ + { + "$ref": "#/components/schemas/Usage" + }, + { + "type": "null" + } + ], + "default": null + }, + "profile_name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile Name" + }, + "mcp_servers": { + "items": { + "$ref": "#/components/schemas/McpServerStatus" + }, + "title": "Mcp Servers", + "type": "array" + }, + "system_prompt": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "System Prompt" + }, + "credential_warning": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Credential Warning" + }, + "lazy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Lazy" + } + }, + "title": "SessionCwdSetResult", + "type": "object" + }, + "SessionDeleteParams": { + "additionalProperties": false, + "description": "``session_id`` is the STORED id.", + "properties": { + "session_id": { + "title": "Session Id", + "type": "string" + }, + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + } + }, + "required": [ + "session_id" + ], + "title": "SessionDeleteParams", + "type": "object" + }, + "SessionDeleteResult": { + "additionalProperties": false, + "properties": { + "deleted": { + "title": "Deleted", + "type": "string" + } + }, + "required": [ + "deleted" + ], + "title": "SessionDeleteResult", + "type": "object" + }, + "SessionEventsSinceParams": { + "additionalProperties": false, + "properties": { + "session_id": { + "title": "Session Id", + "type": "string" + }, + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + }, + "last_seen": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Last Seen" + } + }, + "required": [ + "session_id" + ], + "title": "SessionEventsSinceParams", + "type": "object" + }, + "SessionEventsSinceResult": { + "additionalProperties": false, + "properties": { + "events": { + "items": { + "additionalProperties": true, + "type": "object" + }, + "title": "Events", + "type": "array" + }, + "latest_seq": { + "title": "Latest Seq", + "type": "integer" + }, + "truncated": { + "title": "Truncated", + "type": "boolean" + }, + "count": { + "title": "Count", + "type": "integer" + }, + "epoch": { + "title": "Epoch", + "type": "string" + }, + "open_requests": { + "items": { + "$ref": "#/components/schemas/OpenRequestEntry" + }, + "title": "Open Requests", + "type": "array" + } + }, + "required": [ + "events", + "latest_seq", + "truncated", + "count", + "epoch", + "open_requests" + ], + "title": "SessionEventsSinceResult", + "type": "object" + }, + "SessionEventsStatsParams": { + "additionalProperties": false, + "properties": { + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + } + }, + "title": "SessionEventsStatsParams", + "type": "object" + }, + "SessionEventsStatsResult": { + "additionalProperties": false, + "description": "``event_replay.replay_stats``.", + "properties": { + "sessions": { + "title": "Sessions", + "type": "integer" + }, + "events": { + "title": "Events", + "type": "integer" + }, + "bytes": { + "title": "Bytes", + "type": "integer" + }, + "max_per_session": { + "title": "Max Per Session", + "type": "integer" + }, + "max_bytes_per_session": { + "title": "Max Bytes Per Session", + "type": "integer" + }, + "max_bytes_process": { + "title": "Max Bytes Process", + "type": "integer" + } + }, + "required": [ + "sessions", + "events", + "bytes", + "max_per_session", + "max_bytes_per_session", + "max_bytes_process" + ], + "title": "SessionEventsStatsResult", + "type": "object" + }, + "SessionForeignIdParams": { + "additionalProperties": false, + "properties": { + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + }, + "id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Id" + } + }, + "title": "SessionForeignIdParams", + "type": "object" + }, + "SessionForeignImportResult": { + "additionalProperties": false, + "properties": { + "session_id": { + "title": "Session Id", + "type": "string" + }, + "already_imported": { + "default": false, + "title": "Already Imported", + "type": "boolean" + } + }, + "required": [ + "session_id" + ], + "title": "SessionForeignImportResult", + "type": "object" + }, + "SessionForeignListParams": { + "additionalProperties": false, + "properties": { + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + }, + "source": { + "anyOf": [ + { + "$ref": "#/components/schemas/ForeignSource" + }, + { + "type": "null" + } + ], + "default": null + }, + "offset": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Offset" + }, + "limit": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Limit" + } + }, + "title": "SessionForeignListParams", + "type": "object" + }, + "SessionForeignListResult": { + "additionalProperties": false, + "description": "``unreadable`` counts logs on this page that failed to parse.", + "properties": { + "sessions": { + "items": { + "$ref": "#/components/schemas/ForeignSessionRow" + }, + "title": "Sessions", + "type": "array" + }, + "next_offset": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Next Offset" + }, + "host": { + "title": "Host", + "type": "string" + }, + "unreadable": { + "default": 0, + "title": "Unreadable", + "type": "integer" + } + }, + "required": [ + "host" + ], + "title": "SessionForeignListResult", + "type": "object" + }, + "SessionForeignPreviewResult": { + "additionalProperties": false, + "description": "Bounded to the last 40 turns / 8000 chars each; ``already_imported`` is the local id.", + "properties": { + "messages": { + "items": { + "$ref": "#/components/schemas/ForeignTurn" + }, + "title": "Messages", + "type": "array" + }, + "total": { + "default": 0, + "title": "Total", + "type": "integer" + }, + "truncated": { + "default": false, + "title": "Truncated", + "type": "boolean" + }, + "already_imported": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Already Imported" + }, + "cwd": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Cwd" + } + }, + "title": "SessionForeignPreviewResult", + "type": "object" + }, + "SessionHistoryParams": { + "additionalProperties": false, + "properties": { + "session_id": { + "title": "Session Id", + "type": "string" + }, + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + } + }, + "required": [ + "session_id" + ], + "title": "SessionHistoryParams", + "type": "object" + }, + "SessionHistoryResult": { + "additionalProperties": false, + "properties": { + "count": { + "title": "Count", + "type": "integer" + }, + "messages": { + "items": { + "$ref": "#/components/schemas/TranscriptMessage" + }, + "title": "Messages", + "type": "array" + } + }, + "required": [ + "count", + "messages" + ], + "title": "SessionHistoryResult", + "type": "object" + }, + "SessionInterruptParams": { + "additionalProperties": false, + "properties": { + "session_id": { + "title": "Session Id", + "type": "string" + }, + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + }, + "expected_hosted_task_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Expected Hosted Task Id" + } + }, + "required": [ + "session_id" + ], + "title": "SessionInterruptParams", + "type": "object" + }, + "SessionInterruptResult": { + "additionalProperties": false, + "properties": { + "status": { + "$ref": "#/components/schemas/InterruptStatus" + }, + "interrupted": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Interrupted" + }, + "turn_isolation": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Turn Isolation" + } + }, + "required": [ + "status" + ], + "title": "SessionInterruptResult", + "type": "object" + }, + "SessionListParams": { + "additionalProperties": false, + "properties": { + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + }, + "title": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Title" + }, + "limit": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Limit" + }, + "include_hidden": { + "default": false, + "title": "Include Hidden", + "type": "boolean" + } + }, + "title": "SessionListParams", + "type": "object" + }, + "SessionListResult": { + "additionalProperties": false, + "properties": { + "sessions": { + "items": { + "$ref": "#/components/schemas/SessionListRow" + }, + "title": "Sessions", + "type": "array" + } + }, + "required": [ + "sessions" + ], + "title": "SessionListResult", + "type": "object" + }, + "SessionListRow": { + "additionalProperties": false, + "description": "``methods_session._session_row_summary``; ``resolved_id`` only on a title lookup that followed a\ncompression lineage to its tip.", + "properties": { + "id": { + "title": "Id", + "type": "string" + }, + "resolved_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Resolved Id" + }, + "title": { + "default": "", + "title": "Title", + "type": "string" + }, + "preview": { + "default": "", + "title": "Preview", + "type": "string" + }, + "started_at": { + "default": 0, + "title": "Started At", + "type": "number" + }, + "message_count": { + "default": 0, + "title": "Message Count", + "type": "integer" + }, + "source": { + "default": "", + "title": "Source", + "type": "string" + } + }, + "required": [ + "id" + ], + "title": "SessionListRow", + "type": "object" + }, + "SessionLiveInfo": { + "additionalProperties": true, + "description": "``tui_gateway/server.py::_session_info`` \u2014 the ``session.info`` event and the ``info`` field of\n``session.create`` / ``session.resume`` / ``session.activate`` results.", + "properties": { + "model": { + "default": "", + "title": "Model", + "type": "string" + }, + "provider": { + "default": "", + "title": "Provider", + "type": "string" + }, + "reasoning_effort": { + "default": "", + "title": "Reasoning Effort", + "type": "string" + }, + "service_tier": { + "default": "", + "title": "Service Tier", + "type": "string" + }, + "fast": { + "default": false, + "title": "Fast", + "type": "boolean" + }, + "yolo": { + "default": false, + "title": "Yolo", + "type": "boolean" + }, + "approval_mode": { + "default": "manual", + "title": "Approval Mode", + "type": "string" + }, + "tools": { + "additionalProperties": { + "items": { + "type": "string" + }, + "type": "array" + }, + "title": "Tools", + "type": "object" + }, + "skills": { + "additionalProperties": true, + "title": "Skills", + "type": "object" + }, + "cwd": { + "default": "", + "title": "Cwd", + "type": "string" + }, + "branch": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Branch" + }, + "project": { + "anyOf": [ + { + "$ref": "#/components/schemas/ProjectRef" + }, + { + "type": "null" + } + ], + "default": null + }, + "terminal_backend": { + "default": "", + "title": "Terminal Backend", + "type": "string" + }, + "personality": { + "default": "", + "title": "Personality", + "type": "string" + }, + "running": { + "default": false, + "title": "Running", + "type": "boolean" + }, + "turn_started_at": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Turn Started At" + }, + "title": { + "default": "", + "title": "Title", + "type": "string" + }, + "stored_session_id": { + "default": "", + "title": "Stored Session Id", + "type": "string" + }, + "desktop_contract": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Desktop Contract" + }, + "version": { + "default": "", + "title": "Version", + "type": "string" + }, + "release_date": { + "default": "", + "title": "Release Date", + "type": "string" + }, + "update_behind": { + "anyOf": [ + {}, + { + "type": "null" + } + ], + "default": null, + "title": "Update Behind" + }, + "update_command": { + "default": "", + "title": "Update Command", + "type": "string" + }, + "usage": { + "anyOf": [ + { + "$ref": "#/components/schemas/Usage" + }, + { + "type": "null" + } + ], + "default": null + }, + "profile_name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile Name" + }, + "mcp_servers": { + "items": { + "$ref": "#/components/schemas/McpServerStatus" + }, + "title": "Mcp Servers", + "type": "array" + }, + "system_prompt": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "System Prompt" + }, + "credential_warning": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Credential Warning" + }, + "lazy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Lazy" + } + }, + "title": "SessionLiveInfo", + "type": "object" + }, + "SessionMostRecentParams": { + "additionalProperties": false, + "properties": { + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + } + }, + "title": "SessionMostRecentParams", + "type": "object" + }, + "SessionMostRecentResult": { + "additionalProperties": false, + "properties": { + "session_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Session Id" + }, + "title": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Title" + }, + "started_at": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Started At" + }, + "source": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Source" + } + }, + "required": [ + "session_id" + ], + "title": "SessionMostRecentResult", + "type": "object" + }, + "SessionParams": { + "additionalProperties": false, + "description": "Any method addressed at one live session.", + "properties": { + "session_id": { + "title": "Session Id", + "type": "string" + }, + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + } + }, + "required": [ + "session_id" + ], + "title": "SessionParams", + "type": "object" + }, + "SessionReclaimedPayload": { + "additionalProperties": false, + "description": "``session_lifecycle._announce_session_reclaimed`` (broadcast).", + "properties": { + "session_id": { + "title": "Session Id", + "type": "string" + }, + "stored_session_id": { + "title": "Stored Session Id", + "type": "string" + }, + "reason": { + "title": "Reason", + "type": "string" + } + }, + "required": [ + "session_id", + "stored_session_id", + "reason" + ], + "title": "SessionReclaimedPayload", + "type": "object" + }, + "SessionResumeParams": { + "additionalProperties": false, + "description": "``session_id`` is the STORED id (or an exact title); the reply's ``session_id`` is the runtime id.", + "properties": { + "session_id": { + "title": "Session Id", + "type": "string" + }, + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + }, + "cols": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Cols" + }, + "source": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Source" + }, + "lazy": { + "default": false, + "title": "Lazy", + "type": "boolean" + }, + "defer_history": { + "default": false, + "title": "Defer History", + "type": "boolean" + }, + "omit_messages": { + "default": false, + "title": "Omit Messages", + "type": "boolean" + }, + "eager_build": { + "default": false, + "title": "Eager Build", + "type": "boolean" + }, + "close_on_disconnect": { + "default": false, + "title": "Close On Disconnect", + "type": "boolean" + } + }, + "required": [ + "session_id" + ], + "title": "SessionResumeParams", + "type": "object" + }, + "SessionResumeProgressPayload": { + "additionalProperties": false, + "description": "``server._hydrate_resume_history``.", + "properties": { + "phase": { + "title": "Phase", + "type": "string" + }, + "status": { + "$ref": "#/components/schemas/ResumePhaseStatus" + }, + "message_count": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Message Count" + }, + "message": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Message" + } + }, + "required": [ + "phase", + "status" + ], + "title": "SessionResumeProgressPayload", + "type": "object" + }, + "SessionResumeResult": { + "additionalProperties": false, + "properties": { + "session_id": { + "title": "Session Id", + "type": "string" + }, + "message_count": { + "title": "Message Count", + "type": "integer" + }, + "messages": { + "items": { + "$ref": "#/components/schemas/TranscriptMessage" + }, + "title": "Messages", + "type": "array" + }, + "info": { + "$ref": "#/components/schemas/SessionLiveInfo" + }, + "stored_session_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Stored Session Id" + }, + "resumed": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Resumed" + }, + "session_key": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Session Key" + }, + "messages_omitted": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Messages Omitted" + }, + "hydrating": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Hydrating" + }, + "running": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Running" + }, + "turn_started_at": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Turn Started At" + }, + "started_at": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Started At" + }, + "status": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Status" + }, + "inflight": { + "anyOf": [ + { + "$ref": "#/components/schemas/InflightTurn" + }, + { + "type": "null" + } + ], + "default": null + }, + "queued": { + "anyOf": [ + { + "$ref": "#/components/schemas/QueuedPrompt" + }, + { + "type": "null" + } + ], + "default": null + }, + "pending_approval": { + "anyOf": [ + { + "$ref": "#/components/schemas/tui_gateway_contracts_sessions_PendingApproval" + }, + { + "type": "null" + } + ], + "default": null + }, + "open_requests": { + "anyOf": [ + { + "items": { + "$ref": "#/components/schemas/OpenRequestEntry" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Open Requests" + }, + "todo_state": { + "anyOf": [ + { + "$ref": "#/components/schemas/TodoState" + }, + { + "type": "null" + } + ], + "default": null + }, + "auto_continue": { + "anyOf": [ + { + "$ref": "#/components/schemas/AutoContinue" + }, + { + "type": "null" + } + ], + "default": null + } + }, + "required": [ + "session_id", + "message_count", + "messages", + "info" + ], + "title": "SessionResumeResult", + "type": "object" + }, + "SessionSaveParams": { + "additionalProperties": false, + "properties": { + "session_id": { + "title": "Session Id", + "type": "string" + }, + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + } + }, + "required": [ + "session_id" + ], + "title": "SessionSaveParams", + "type": "object" + }, + "SessionSaveResult": { + "additionalProperties": true, + "description": "Under turn isolation the compute host's result passes through verbatim.", + "properties": { + "file": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "File" + } + }, + "title": "SessionSaveResult", + "type": "object" + }, + "SessionSetHiddenParams": { + "additionalProperties": false, + "description": "``session_id`` is a live runtime id first, else a stored id / key / title.", + "properties": { + "session_id": { + "title": "Session Id", + "type": "string" + }, + "hidden": { + "default": true, + "title": "Hidden", + "type": "boolean" + }, + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + } + }, + "required": [ + "session_id" + ], + "title": "SessionSetHiddenParams", + "type": "object" + }, + "SessionSetHiddenResult": { + "additionalProperties": false, + "properties": { + "hidden": { + "title": "Hidden", + "type": "boolean" + }, + "session_key": { + "title": "Session Key", + "type": "string" + } + }, + "required": [ + "hidden", + "session_key" + ], + "title": "SessionSetHiddenResult", + "type": "object" + }, + "SessionStatusParams": { + "additionalProperties": false, + "properties": { + "session_id": { + "title": "Session Id", + "type": "string" + }, + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + } + }, + "required": [ + "session_id" + ], + "title": "SessionStatusParams", + "type": "object" + }, + "SessionStatusResult": { + "additionalProperties": false, + "properties": { + "output": { + "title": "Output", + "type": "string" + } + }, + "required": [ + "output" + ], + "title": "SessionStatusResult", + "type": "object" + }, + "SessionTitleParams": { + "additionalProperties": false, + "properties": { + "session_id": { + "title": "Session Id", + "type": "string" + }, + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + }, + "title": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Title" + } + }, + "required": [ + "session_id" + ], + "title": "SessionTitleParams", + "type": "object" + }, + "SessionTitlePayload": { + "additionalProperties": false, + "description": "``prompt_turn._invoke_agent`` ``_on_session_title`` hook.", + "properties": { + "session_id": { + "title": "Session Id", + "type": "string" + }, + "title": { + "title": "Title", + "type": "string" + } + }, + "required": [ + "session_id", + "title" + ], + "title": "SessionTitlePayload", + "type": "object" + }, + "SessionTitleResult": { + "additionalProperties": false, + "properties": { + "title": { + "title": "Title", + "type": "string" + }, + "session_key": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Session Key" + }, + "pending": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Pending" + } + }, + "required": [ + "title" + ], + "title": "SessionTitleResult", + "type": "object" + }, + "SessionUndoParams": { + "additionalProperties": false, + "properties": { + "session_id": { + "title": "Session Id", + "type": "string" + }, + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + } + }, + "required": [ + "session_id" + ], + "title": "SessionUndoParams", + "type": "object" + }, + "SessionUndoResult": { + "additionalProperties": false, + "properties": { + "removed": { + "title": "Removed", + "type": "integer" + } + }, + "required": [ + "removed" + ], + "title": "SessionUndoResult", + "type": "object" + }, + "SessionUsageParams": { + "additionalProperties": false, + "properties": { + "session_id": { + "title": "Session Id", + "type": "string" + }, + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + } + }, + "required": [ + "session_id" + ], + "title": "SessionUsageParams", + "type": "object" + }, + "SessionUsagePayload": { + "additionalProperties": false, + "description": "``server._start_usage_ticker``.", + "properties": { + "usage": { + "$ref": "#/components/schemas/Usage" + } + }, + "required": [ + "usage" + ], + "title": "SessionUsagePayload", + "type": "object" + }, + "SessionUsageResult": { + "additionalProperties": true, + "properties": { + "model": { + "default": "", + "title": "Model", + "type": "string" + }, + "input": { + "default": 0, + "title": "Input", + "type": "integer" + }, + "output": { + "default": 0, + "title": "Output", + "type": "integer" + }, + "reasoning": { + "default": 0, + "title": "Reasoning", + "type": "integer" + }, + "prompt": { + "default": 0, + "title": "Prompt", + "type": "integer" + }, + "completion": { + "default": 0, + "title": "Completion", + "type": "integer" + }, + "total": { + "default": 0, + "title": "Total", + "type": "integer" + }, + "calls": { + "default": 0, + "title": "Calls", + "type": "integer" + }, + "compressions": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Compressions" + }, + "context_used": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Context Used" + }, + "context_max": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Context Max" + }, + "context_percent": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Context Percent" + }, + "context_source": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Context Source" + }, + "context_estimated": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Context Estimated" + }, + "cache_hit_pct": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Cache Hit Pct" + }, + "cache_read": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Cache Read" + }, + "cache_write": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Cache Write" + }, + "avg_latency_s": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Avg Latency S" + }, + "avg_tps": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Avg Tps" + }, + "active_subagents": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Active Subagents" + }, + "dev_credits_spent_micros": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Dev Credits Spent Micros" + }, + "cost_usd": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Cost Usd" + }, + "cost_status": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Cost Status" + }, + "credits_lines": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Credits Lines" + } + }, + "title": "SessionUsageResult", + "type": "object" + }, + "SessionWorkspaceMoveParams": { + "additionalProperties": false, + "properties": { + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + }, + "session_key": { + "title": "Session Key", + "type": "string" + }, + "cwd": { + "title": "Cwd", + "type": "string" + } + }, + "required": [ + "session_key", + "cwd" + ], + "title": "SessionWorkspaceMoveParams", + "type": "object" + }, + "SessionWorkspaceMoveResult": { + "additionalProperties": false, + "properties": { + "cwd": { + "title": "Cwd", + "type": "string" + }, + "branch": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Branch" + }, + "git_repo_root": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Git Repo Root" + } + }, + "required": [ + "cwd" + ], + "title": "SessionWorkspaceMoveResult", + "type": "object" + }, + "SetupReadyPayload": { + "additionalProperties": true, + "description": "``hermes_cli/free_tier_bootstrap.py::SetupRecord.as_payload``.", + "properties": { + "provider_configured": { + "title": "Provider Configured", + "type": "boolean" + }, + "inference_provider": { + "title": "Inference Provider", + "type": "string" + }, + "free_tier": { + "title": "Free Tier", + "type": "boolean" + }, + "has_identity": { + "title": "Has Identity", + "type": "boolean" + }, + "other_providers": { + "title": "Other Providers", + "type": "boolean" + }, + "error": { + "default": "", + "title": "Error", + "type": "string" + }, + "finished_at": { + "title": "Finished At", + "type": "number" + } + }, + "required": [ + "provider_configured", + "inference_provider", + "free_tier", + "has_identity", + "other_providers", + "finished_at" + ], + "title": "SetupReadyPayload", + "type": "object" + }, + "SetupRuntimeCheckParams": { + "additionalProperties": false, + "properties": { + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + }, + "provider": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Provider" + } + }, + "title": "SetupRuntimeCheckParams", + "type": "object" + }, + "SetupRuntimeCheckResult": { + "additionalProperties": false, + "description": "``ok=False`` + ``error`` when the resolved model can't be served; ``free_tier`` says the\nselected route is the welcome host.", + "properties": { + "ok": { + "title": "Ok", + "type": "boolean" + }, + "provider": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Provider" + }, + "model": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Model" + }, + "source": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Source" + }, + "error": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Error" + }, + "free_tier": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Free Tier" + }, + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + } + }, + "required": [ + "ok" + ], + "title": "SetupRuntimeCheckResult", + "type": "object" + }, + "SetupStatusResult": { + "additionalProperties": false, + "description": "``provider_configured`` is the loose answer; the boot record's fields (``ready``,\n``free_tier``, ``other_providers``, ``inference_provider``) ride along on the launch profile.\nAn unknown ``profile`` answers ``ok=False`` + ``error``.", + "properties": { + "provider_configured": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Provider Configured" + }, + "ready": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Ready" + }, + "free_tier": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Free Tier" + }, + "other_providers": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Other Providers" + }, + "inference_provider": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Inference Provider" + }, + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + }, + "ok": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Ok" + }, + "error": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Error" + } + }, + "title": "SetupStatusResult", + "type": "object" + }, + "ShellExecParams": { + "additionalProperties": false, + "properties": { + "command": { + "title": "Command", + "type": "string" + }, + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + } + }, + "required": [ + "command" + ], + "title": "ShellExecParams", + "type": "object" + }, + "ShellExecResult": { + "additionalProperties": false, + "properties": { + "stdout": { + "title": "Stdout", + "type": "string" + }, + "stderr": { + "title": "Stderr", + "type": "string" + }, + "code": { + "title": "Code", + "type": "integer" + } + }, + "required": [ + "stdout", + "stderr", + "code" + ], + "title": "ShellExecResult", + "type": "object" + }, + "SideAgentCompletePayload": { + "additionalProperties": false, + "description": "``methods_prompt._spawn_side_agent``: ``{task_id, **extra, text}``; btw adds ``question``.", + "properties": { + "task_id": { + "title": "Task Id", + "type": "string" + }, + "text": { + "title": "Text", + "type": "string" + }, + "question": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Question" + } + }, + "required": [ + "task_id", + "text" + ], + "title": "SideAgentCompletePayload", + "type": "object" + }, + "SideAgentParams": { + "additionalProperties": false, + "properties": { + "session_id": { + "title": "Session Id", + "type": "string" + }, + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + }, + "text": { + "title": "Text", + "type": "string" + } + }, + "required": [ + "session_id", + "text" + ], + "title": "SideAgentParams", + "type": "object" + }, + "SkillBrowseItem": { + "additionalProperties": true, + "description": "``hermes_cli.skills_hub.browse_skills`` row.", + "properties": { + "name": { + "default": "", + "title": "Name", + "type": "string" + }, + "description": { + "default": "", + "title": "Description", + "type": "string" + }, + "source": { + "default": "", + "title": "Source", + "type": "string" + }, + "trust": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Trust" + }, + "identifier": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Identifier" + } + }, + "title": "SkillBrowseItem", + "type": "object" + }, + "SkillCatalogEntry": { + "additionalProperties": false, + "properties": { + "usage": { + "default": 0, + "title": "Usage", + "type": "integer" + }, + "origin": { + "default": "local", + "title": "Origin", + "type": "string" + } + }, + "title": "SkillCatalogEntry", + "type": "object" + }, + "SkillCommandRef": { + "additionalProperties": false, + "properties": { + "name": { + "title": "Name", + "type": "string" + }, + "description": { + "default": "", + "title": "Description", + "type": "string" + } + }, + "required": [ + "name" + ], + "title": "SkillCommandRef", + "type": "object" + }, + "SkillHubHit": { + "additionalProperties": false, + "properties": { + "name": { + "title": "Name", + "type": "string" + }, + "description": { + "title": "Description", + "type": "string" + } + }, + "required": [ + "name", + "description" + ], + "title": "SkillHubHit", + "type": "object" + }, + "SkillInspectInfo": { + "additionalProperties": true, + "description": "``hermes_cli.skills_hub.inspect_skill``; ``{}`` when the identifier resolves nowhere.", + "properties": { + "name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Name" + }, + "description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Description" + }, + "source": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Source" + }, + "identifier": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Identifier" + }, + "tags": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Tags" + }, + "skill_md_preview": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Skill Md Preview" + } + }, + "title": "SkillInspectInfo", + "type": "object" + }, + "SkillsAction": { + "enum": [ + "list", + "search", + "install", + "browse", + "inspect" + ], + "title": "SkillsAction", + "type": "string" + }, + "SkillsManageParams": { + "additionalProperties": false, + "description": "``query`` is the search text / hub identifier / browse page (digits); ``page`` / ``page_size``\napply to ``browse``.", + "properties": { + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + }, + "action": { + "$ref": "#/components/schemas/SkillsAction", + "default": "list" + }, + "query": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Query" + }, + "page": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Page" + }, + "page_size": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Page Size" + } + }, + "title": "SkillsManageParams", + "type": "object" + }, + "SkillsManageResult": { + "additionalProperties": false, + "description": "Shape follows the action: ``list`` \u2192 ``skills`` (category \u2192 names); ``search`` \u2192 ``results``;\n``install`` \u2192 ``installed`` + ``name``; ``browse`` \u2192 ``items`` + paging; ``inspect`` \u2192 ``info``.", + "properties": { + "skills": { + "anyOf": [ + { + "additionalProperties": { + "items": { + "type": "string" + }, + "type": "array" + }, + "type": "object" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Skills" + }, + "results": { + "anyOf": [ + { + "items": { + "$ref": "#/components/schemas/SkillHubHit" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Results" + }, + "installed": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Installed" + }, + "name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Name" + }, + "items": { + "anyOf": [ + { + "items": { + "$ref": "#/components/schemas/SkillBrowseItem" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Items" + }, + "page": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Page" + }, + "total_pages": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Total Pages" + }, + "total": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Total" + }, + "info": { + "anyOf": [ + { + "$ref": "#/components/schemas/SkillInspectInfo" + }, + { + "type": "null" + } + ], + "default": null + } + }, + "title": "SkillsManageResult", + "type": "object" + }, + "SkillsReloadDiff": { + "additionalProperties": true, + "description": "``agent.skill_commands.reload_skills``.", + "properties": { + "added": { + "items": { + "$ref": "#/components/schemas/SkillCommandRef" + }, + "title": "Added", + "type": "array" + }, + "removed": { + "items": { + "$ref": "#/components/schemas/SkillCommandRef" + }, + "title": "Removed", + "type": "array" + }, + "unchanged": { + "items": { + "type": "string" + }, + "title": "Unchanged", + "type": "array" + }, + "total": { + "default": 0, + "title": "Total", + "type": "integer" + }, + "commands": { + "default": 0, + "title": "Commands", + "type": "integer" + } + }, + "title": "SkillsReloadDiff", + "type": "object" + }, + "SkillsReloadParams": { + "additionalProperties": false, + "properties": {}, + "title": "SkillsReloadParams", + "type": "object" + }, + "SkillsReloadResult": { + "additionalProperties": false, + "properties": { + "output": { + "title": "Output", + "type": "string" + }, + "result": { + "$ref": "#/components/schemas/SkillsReloadDiff" + } + }, + "required": [ + "output", + "result" + ], + "title": "SkillsReloadResult", + "type": "object" + }, + "SkinPayload": { + "additionalProperties": true, + "description": "``tui_gateway/change_watcher.py::resolve_skin`` \u2014 the resolved active skin (``HermesSkin``).\n``{}`` when the skin engine failed to load. Colour maps are token \u2192 colour string.", + "properties": { + "name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Name" + }, + "colors": { + "anyOf": [ + { + "additionalProperties": { + "type": "string" + }, + "type": "object" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Colors" + }, + "light_colors": { + "anyOf": [ + { + "additionalProperties": { + "type": "string" + }, + "type": "object" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Light Colors" + }, + "dark_colors": { + "anyOf": [ + { + "additionalProperties": { + "type": "string" + }, + "type": "object" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Dark Colors" + }, + "branding": { + "anyOf": [ + { + "additionalProperties": { + "type": "string" + }, + "type": "object" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Branding" + }, + "banner_logo": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Banner Logo" + }, + "banner_hero": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Banner Hero" + }, + "tool_prefix": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Tool Prefix" + }, + "help_header": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Help Header" + } + }, + "title": "SkinPayload", + "type": "object" + }, + "SlashExecParams": { + "additionalProperties": false, + "properties": { + "session_id": { + "title": "Session Id", + "type": "string" + }, + "command": { + "title": "Command", + "type": "string" + }, + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + } + }, + "required": [ + "session_id", + "command" + ], + "title": "SlashExecParams", + "type": "object" + }, + "SlashExecResult": { + "additionalProperties": false, + "description": "Plain worker/plugin text in ``output`` (+ ``warning``), or \u2014 when the command was rerouted to\n``command.dispatch`` \u2014 that method's directive fields with ``type`` set.", + "properties": { + "output": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Output" + }, + "warning": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Warning" + }, + "type": { + "anyOf": [ + { + "$ref": "#/components/schemas/DispatchType" + }, + { + "type": "null" + } + ], + "default": null + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Target" + }, + "message": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Message" + }, + "notice": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Notice" + }, + "display": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Display" + }, + "name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Name" + }, + "status": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Status" + } + }, + "title": "SlashExecResult", + "type": "object" + }, + "SpawnTreeEntry": { + "additionalProperties": true, + "description": "Index row (``server._append_spawn_tree_index``) or a legacy file scan.", + "properties": { + "path": { + "title": "Path", + "type": "string" + }, + "session_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Session Id" + }, + "started_at": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Started At" + }, + "finished_at": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Finished At" + }, + "label": { + "default": "", + "title": "Label", + "type": "string" + }, + "count": { + "default": 0, + "title": "Count", + "type": "integer" + } + }, + "required": [ + "path" + ], + "title": "SpawnTreeEntry", + "type": "object" + }, + "SpawnTreeListParams": { + "additionalProperties": false, + "properties": { + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + }, + "session_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Session Id" + }, + "cross_session": { + "default": false, + "title": "Cross Session", + "type": "boolean" + }, + "limit": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Limit" + } + }, + "title": "SpawnTreeListParams", + "type": "object" + }, + "SpawnTreeListResult": { + "additionalProperties": false, + "properties": { + "entries": { + "items": { + "$ref": "#/components/schemas/SpawnTreeEntry" + }, + "title": "Entries", + "type": "array" + } + }, + "required": [ + "entries" + ], + "title": "SpawnTreeListResult", + "type": "object" + }, + "SpawnTreeLoadParams": { + "additionalProperties": false, + "properties": { + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + }, + "path": { + "title": "Path", + "type": "string" + } + }, + "required": [ + "path" + ], + "title": "SpawnTreeLoadParams", + "type": "object" + }, + "SpawnTreeLoadResult": { + "additionalProperties": true, + "description": "The snapshot file as written by ``spawn_tree.save`` (open: the file is the contract).", + "properties": { + "session_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Session Id" + }, + "started_at": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Started At" + }, + "finished_at": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Finished At" + }, + "label": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Label" + }, + "subagents": { + "items": { + "additionalProperties": true, + "type": "object" + }, + "title": "Subagents", + "type": "array" + } + }, + "title": "SpawnTreeLoadResult", + "type": "object" + }, + "SpawnTreeSaveParams": { + "additionalProperties": false, + "properties": { + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + }, + "subagents": { + "items": { + "additionalProperties": true, + "type": "object" + }, + "title": "Subagents", + "type": "array" + }, + "session_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Session Id" + }, + "started_at": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Started At" + }, + "finished_at": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Finished At" + }, + "label": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Label" + } + }, + "required": [ + "subagents" + ], + "title": "SpawnTreeSaveParams", + "type": "object" + }, + "SpawnTreeSaveResult": { + "additionalProperties": false, + "properties": { + "path": { + "title": "Path", + "type": "string" + }, + "session_id": { + "title": "Session Id", + "type": "string" + } + }, + "required": [ + "path", + "session_id" + ], + "title": "SpawnTreeSaveResult", + "type": "object" + }, + "StatusUpdatePayload": { + "additionalProperties": false, + "description": "``server._status_update`` and the direct emitters (goal / loop / heartbeat / process).", + "properties": { + "kind": { + "title": "Kind", + "type": "string" + }, + "text": { + "title": "Text", + "type": "string" + } + }, + "required": [ + "kind", + "text" + ], + "title": "StatusUpdatePayload", + "type": "object" + }, + "SteerStatus": { + "enum": [ + "queued", + "rejected" + ], + "title": "SteerStatus", + "type": "string" + }, + "StreamDeltaPayload": { + "additionalProperties": false, + "description": "``prompt_turn._invoke_agent._stream`` (message.delta: ``text`` + optional ``rendered``),\n``agent_callbacks._agent_cbs`` (reasoning.delta / thinking.delta), ``tool_progress._progress_reasoning``\n(reasoning.available). ``verbose`` rides only when the session's verbose reasoning mode is on.", + "properties": { + "text": { + "title": "Text", + "type": "string" + }, + "rendered": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Rendered" + }, + "verbose": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Verbose" + } + }, + "required": [ + "text" + ], + "title": "StreamDeltaPayload", + "type": "object" + }, + "SubagentEventPayload": { + "additionalProperties": false, + "description": "``tool_progress._progress_subagent`` \u2014 every ``subagent.*`` frame; identity fields are optional\nbecause older emitters omit them and the TUI spawn tree falls back to flat rendering.", + "properties": { + "goal": { + "title": "Goal", + "type": "string" + }, + "task_count": { + "title": "Task Count", + "type": "integer" + }, + "task_index": { + "title": "Task Index", + "type": "integer" + }, + "subagent_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Subagent Id" + }, + "parent_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Parent Id" + }, + "child_session_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Child Session Id" + }, + "delegation_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Delegation Id" + }, + "depth": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Depth" + }, + "model": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Model" + }, + "tool_count": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Tool Count" + }, + "toolsets": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Toolsets" + }, + "input_tokens": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Input Tokens" + }, + "output_tokens": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Output Tokens" + }, + "reasoning_tokens": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Reasoning Tokens" + }, + "api_calls": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Api Calls" + }, + "files_read": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Files Read" + }, + "files_written": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Files Written" + }, + "output_tail": { + "anyOf": [ + { + "items": { + "$ref": "#/components/schemas/SubagentOutputTailEntry" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Output Tail" + }, + "tool_name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Tool Name" + }, + "text": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Text" + }, + "status": { + "anyOf": [ + { + "$ref": "#/components/schemas/SubagentStatus" + }, + { + "type": "null" + } + ], + "default": null + }, + "summary": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Summary" + }, + "duration_seconds": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Duration Seconds" + }, + "tool_preview": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Tool Preview" + } + }, + "required": [ + "goal", + "task_count", + "task_index" + ], + "title": "SubagentEventPayload", + "type": "object" + }, + "SubagentIdParams": { + "additionalProperties": false, + "properties": { + "session_id": { + "title": "Session Id", + "type": "string" + }, + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + }, + "subagent_id": { + "title": "Subagent Id", + "type": "string" + } + }, + "required": [ + "session_id", + "subagent_id" + ], + "title": "SubagentIdParams", + "type": "object" + }, + "SubagentInterruptResult": { + "additionalProperties": false, + "properties": { + "found": { + "title": "Found", + "type": "boolean" + }, + "subagent_id": { + "title": "Subagent Id", + "type": "string" + } + }, + "required": [ + "found", + "subagent_id" + ], + "title": "SubagentInterruptResult", + "type": "object" + }, + "SubagentListResult": { + "additionalProperties": false, + "description": "``delegations`` is reserved for async delegation records and is currently always empty.", + "properties": { + "subagents": { + "items": { + "$ref": "#/components/schemas/SubagentSnapshot" + }, + "title": "Subagents", + "type": "array" + }, + "delegations": { + "items": { + "additionalProperties": true, + "type": "object" + }, + "title": "Delegations", + "type": "array" + } + }, + "title": "SubagentListResult", + "type": "object" + }, + "SubagentOutputTailEntry": { + "additionalProperties": false, + "description": "``tools/delegate_tool_results.py::_extract_output_tail`` row.", + "properties": { + "tool": { + "title": "Tool", + "type": "string" + }, + "preview": { + "title": "Preview", + "type": "string" + }, + "is_error": { + "title": "Is Error", + "type": "boolean" + } + }, + "required": [ + "tool", + "preview", + "is_error" + ], + "title": "SubagentOutputTailEntry", + "type": "object" + }, + "SubagentSnapshot": { + "additionalProperties": false, + "description": "``methods_subagents._SUBAGENT_SNAPSHOT_FIELDS`` projection of one live child record.", + "properties": { + "subagent_id": { + "title": "Subagent Id", + "type": "string" + }, + "parent_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Parent Id" + }, + "depth": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Depth" + }, + "goal": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Goal" + }, + "delegation_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Delegation Id" + }, + "model": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Model" + }, + "started_at": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Started At" + }, + "status": { + "anyOf": [ + { + "$ref": "#/components/schemas/SubagentStatus" + }, + { + "type": "null" + } + ], + "default": null + }, + "tool_count": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Tool Count" + }, + "last_tool": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Last Tool" + }, + "accepting_steer": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Accepting Steer" + } + }, + "required": [ + "subagent_id" + ], + "title": "SubagentSnapshot", + "type": "object" + }, + "SubagentStatus": { + "description": "Lifecycle of one delegated child (``tools/delegate_tool_child_run.py``); ``failed`` /\n``error`` / ``timeout`` / ``interrupted`` / ``completed`` are terminal.", + "enum": [ + "queued", + "running", + "completed", + "failed", + "error", + "timeout", + "interrupted" + ], + "title": "SubagentStatus", + "type": "string" + }, + "SubagentSteerParams": { + "additionalProperties": false, + "properties": { + "session_id": { + "title": "Session Id", + "type": "string" + }, + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + }, + "subagent_id": { + "title": "Subagent Id", + "type": "string" + }, + "text": { + "title": "Text", + "type": "string" + } + }, + "required": [ + "session_id", + "subagent_id", + "text" + ], + "title": "SubagentSteerParams", + "type": "object" + }, + "SubagentSteerResult": { + "additionalProperties": false, + "description": "``queued`` is not ``delivered``: a child past its final tool batch surfaces ``missed_steer``.", + "properties": { + "status": { + "$ref": "#/components/schemas/SteerStatus" + }, + "subagent_id": { + "title": "Subagent Id", + "type": "string" + }, + "text": { + "title": "Text", + "type": "string" + } + }, + "required": [ + "status", + "subagent_id", + "text" + ], + "title": "SubagentSteerResult", + "type": "object" + }, + "SubagentTailResult": { + "additionalProperties": false, + "description": "``available`` is false while the child has no live transcript yet (or it was cleaned up).", + "properties": { + "subagent_id": { + "title": "Subagent Id", + "type": "string" + }, + "available": { + "default": false, + "title": "Available", + "type": "boolean" + }, + "text": { + "default": "", + "title": "Text", + "type": "string" + }, + "truncated": { + "default": false, + "title": "Truncated", + "type": "boolean" + } + }, + "required": [ + "subagent_id" + ], + "title": "SubagentTailResult", + "type": "object" + }, + "SubscriptionChangeEffect": { + "enum": [ + "charge_now", + "scheduled", + "no_op", + "blocked" + ], + "title": "SubscriptionChangeEffect", + "type": "string" + }, + "SubscriptionChangeParams": { + "additionalProperties": false, + "description": "Either a target tier (downgrade / same-price change) or ``cancel`` (period-end cancellation).", + "properties": { + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + }, + "subscription_type_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Subscription Type Id" + }, + "cancel": { + "default": false, + "title": "Cancel", + "type": "boolean" + } + }, + "title": "SubscriptionChangeParams", + "type": "object" + }, + "SubscriptionContext": { + "enum": [ + "personal", + "team" + ], + "title": "SubscriptionContext", + "type": "string" + }, + "SubscriptionPreviewParams": { + "additionalProperties": false, + "properties": { + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + }, + "subscription_type_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Subscription Type Id" + } + }, + "title": "SubscriptionPreviewParams", + "type": "object" + }, + "SubscriptionPreviewResult": { + "additionalProperties": false, + "description": "``_serialize_subscription_preview`` on success; ``effect`` drives the confirm copy.", + "properties": { + "ok": { + "title": "Ok", + "type": "boolean" + }, + "error": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Error" + }, + "message": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Message" + }, + "portal_url": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Portal Url" + }, + "retry_after": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "number" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Retry After" + }, + "payload": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Payload" + }, + "actor": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Actor" + }, + "code": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Code" + }, + "recovery": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Recovery" + }, + "effect": { + "anyOf": [ + { + "$ref": "#/components/schemas/SubscriptionChangeEffect" + }, + { + "type": "null" + } + ], + "default": null + }, + "reason": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Reason" + }, + "current_tier_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Current Tier Id" + }, + "current_tier_name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Current Tier Name" + }, + "target_tier_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Target Tier Id" + }, + "target_tier_name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Target Tier Name" + }, + "monthly_credits_delta": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Monthly Credits Delta" + }, + "amount_due_now_cents": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Amount Due Now Cents" + }, + "effective_at": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Effective At" + } + }, + "required": [ + "ok" + ], + "title": "SubscriptionPreviewResult", + "type": "object" + }, + "SubscriptionStateResult": { + "additionalProperties": false, + "description": "``_serialize_subscription_state``; the view's fallback emits only ``ok / logged_in / error``.", + "properties": { + "ok": { + "title": "Ok", + "type": "boolean" + }, + "logged_in": { + "title": "Logged In", + "type": "boolean" + }, + "is_admin": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Is Admin" + }, + "can_change_plan": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Can Change Plan" + }, + "org_name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Org Name" + }, + "org_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Org Id" + }, + "role": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Role" + }, + "context": { + "anyOf": [ + { + "$ref": "#/components/schemas/SubscriptionContext" + }, + { + "type": "null" + } + ], + "default": null + }, + "current": { + "anyOf": [ + { + "$ref": "#/components/schemas/CurrentSubscription" + }, + { + "type": "null" + } + ], + "default": null + }, + "tiers": { + "anyOf": [ + { + "items": { + "$ref": "#/components/schemas/SubscriptionTierOption" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Tiers" + }, + "portal_url": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Portal Url" + }, + "error": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Error" + }, + "usage": { + "anyOf": [ + { + "$ref": "#/components/schemas/UsageModel" + }, + { + "type": "null" + } + ], + "default": null + } + }, + "required": [ + "ok", + "logged_in" + ], + "title": "SubscriptionStateResult", + "type": "object" + }, + "SubscriptionTierOption": { + "additionalProperties": false, + "properties": { + "tier_id": { + "title": "Tier Id", + "type": "string" + }, + "name": { + "title": "Name", + "type": "string" + }, + "tier_order": { + "title": "Tier Order", + "type": "integer" + }, + "dollars_per_month_display": { + "title": "Dollars Per Month Display", + "type": "string" + }, + "monthly_credits": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Monthly Credits" + }, + "is_current": { + "title": "Is Current", + "type": "boolean" + }, + "is_enabled": { + "title": "Is Enabled", + "type": "boolean" + } + }, + "required": [ + "tier_id", + "name", + "tier_order", + "dollars_per_month_display", + "is_current", + "is_enabled" + ], + "title": "SubscriptionTierOption", + "type": "object" + }, + "SubscriptionUpgradeParams": { + "additionalProperties": false, + "properties": { + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + }, + "subscription_type_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Subscription Type Id" + }, + "idempotency_key": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Idempotency Key" + } + }, + "title": "SubscriptionUpgradeParams", + "type": "object" + }, + "SubscriptionUpgradeResult": { + "additionalProperties": false, + "description": "The money route: ``status`` separates a completed upgrade from an SCA / decline that must\nfinish in the portal at ``recovery_url``; ``idempotency_key`` is echoed (also on error) so a\nretry reuses it.", + "properties": { + "ok": { + "title": "Ok", + "type": "boolean" + }, + "error": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Error" + }, + "message": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Message" + }, + "portal_url": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Portal Url" + }, + "retry_after": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "number" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Retry After" + }, + "payload": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Payload" + }, + "actor": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Actor" + }, + "code": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Code" + }, + "recovery": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Recovery" + }, + "status": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Status" + }, + "target_tier_name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Target Tier Name" + }, + "recovery_url": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Recovery Url" + }, + "reason": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Reason" + }, + "idempotency_key": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Idempotency Key" + } + }, + "required": [ + "ok" + ], + "title": "SubscriptionUpgradeResult", + "type": "object" + }, + "SystemBatteryParams": { + "additionalProperties": false, + "properties": { + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + } + }, + "title": "SystemBatteryParams", + "type": "object" + }, + "SystemBatteryResult": { + "additionalProperties": false, + "properties": { + "available": { + "title": "Available", + "type": "boolean" + }, + "percent": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Percent" + }, + "plugged": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Plugged" + }, + "category": { + "$ref": "#/components/schemas/BatteryCategory", + "default": "dim" + } + }, + "required": [ + "available" + ], + "title": "SystemBatteryResult", + "type": "object" + }, + "TaskIdResult": { + "additionalProperties": false, + "description": "The side agent runs detached; its answer lands on the parent session as an event carrying\nthis ``task_id``.", + "properties": { + "task_id": { + "title": "Task Id", + "type": "string" + } + }, + "required": [ + "task_id" + ], + "title": "TaskIdResult", + "type": "object" + }, + "TerminalClosePayload": { + "additionalProperties": false, + "properties": { + "process_id": { + "title": "Process Id", + "type": "string" + } + }, + "required": [ + "process_id" + ], + "title": "TerminalClosePayload", + "type": "object" + }, + "TerminalOutputPayload": { + "additionalProperties": false, + "description": "``session_notifications`` process_registry.on_output.", + "properties": { + "process_id": { + "title": "Process Id", + "type": "string" + }, + "chunk": { + "title": "Chunk", + "type": "string" + } + }, + "required": [ + "process_id", + "chunk" + ], + "title": "TerminalOutputPayload", + "type": "object" + }, + "TerminalResizeParams": { + "additionalProperties": false, + "properties": { + "session_id": { + "title": "Session Id", + "type": "string" + }, + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + }, + "cols": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Cols" + } + }, + "required": [ + "session_id" + ], + "title": "TerminalResizeParams", + "type": "object" + }, + "TerminalResizeResult": { + "additionalProperties": false, + "properties": { + "cols": { + "title": "Cols", + "type": "integer" + } + }, + "required": [ + "cols" + ], + "title": "TerminalResizeResult", + "type": "object" + }, + "TipShowPayload": { + "additionalProperties": false, + "description": "``tools/tip_tool.py``.", + "properties": { + "selector": { + "title": "Selector", + "type": "string" + }, + "text": { + "title": "Text", + "type": "string" + }, + "title": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Title" + }, + "side": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Side" + } + }, + "required": [ + "selector", + "text" + ], + "title": "TipShowPayload", + "type": "object" + }, + "TodoState": { + "additionalProperties": false, + "description": "``tool_progress._normalize_todo_state``: the authoritative todo snapshot.", + "properties": { + "todos": { + "items": { + "additionalProperties": true, + "type": "object" + }, + "title": "Todos", + "type": "array" + }, + "revision": { + "title": "Revision", + "type": "integer" + } + }, + "required": [ + "todos", + "revision" + ], + "title": "TodoState", + "type": "object" + }, + "TodoUpdatedPayload": { + "additionalProperties": false, + "description": "``tool_progress._normalize_todo_state`` \u2014 full task snapshot.", + "properties": { + "todos": { + "items": {}, + "title": "Todos", + "type": "array" + }, + "revision": { + "title": "Revision", + "type": "integer" + } + }, + "required": [ + "todos", + "revision" + ], + "title": "TodoUpdatedPayload", + "type": "object" + }, + "ToolCompletePayload": { + "additionalProperties": false, + "description": "``tool_progress._on_tool_complete``; ``todos``/``revision`` merged in for the todo tools.", + "properties": { + "tool_id": { + "title": "Tool Id", + "type": "string" + }, + "name": { + "title": "Name", + "type": "string" + }, + "args": { + "additionalProperties": true, + "title": "Args", + "type": "object" + }, + "duration_s": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Duration S" + }, + "result": { + "default": null, + "title": "Result" + }, + "summary": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Summary" + }, + "result_text": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Result Text" + }, + "inline_diff": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Inline Diff" + }, + "todos": { + "anyOf": [ + { + "items": {}, + "type": "array" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Todos" + }, + "revision": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Revision" + } + }, + "required": [ + "tool_id", + "name", + "args" + ], + "title": "ToolCompletePayload", + "type": "object" + }, + "ToolGeneratingPayload": { + "additionalProperties": false, + "description": "``agent_callbacks`` tool_gen_callback.", + "properties": { + "name": { + "title": "Name", + "type": "string" + } + }, + "required": [ + "name" + ], + "title": "ToolGeneratingPayload", + "type": "object" + }, + "ToolOutputRiskPayload": { + "additionalProperties": false, + "description": "``tool_progress._progress_output_risk``.", + "properties": { + "tool_id": { + "title": "Tool Id", + "type": "string" + }, + "name": { + "title": "Name", + "type": "string" + }, + "risk": { + "title": "Risk", + "type": "string" + }, + "findings": { + "items": { + "type": "string" + }, + "title": "Findings", + "type": "array" + }, + "redacted": { + "title": "Redacted", + "type": "boolean" + } + }, + "required": [ + "tool_id", + "name", + "risk", + "findings", + "redacted" + ], + "title": "ToolOutputRiskPayload", + "type": "object" + }, + "ToolShowRow": { + "additionalProperties": false, + "properties": { + "name": { + "title": "Name", + "type": "string" + }, + "description": { + "title": "Description", + "type": "string" + } + }, + "required": [ + "name", + "description" + ], + "title": "ToolShowRow", + "type": "object" + }, + "ToolShowSection": { + "additionalProperties": false, + "properties": { + "name": { + "title": "Name", + "type": "string" + }, + "tools": { + "items": { + "$ref": "#/components/schemas/ToolShowRow" + }, + "title": "Tools", + "type": "array" + } + }, + "required": [ + "name", + "tools" + ], + "title": "ToolShowSection", + "type": "object" + }, + "ToolStartPayload": { + "additionalProperties": false, + "description": "``tool_progress._on_tool_start`` (+ ``agent_callbacks._mirror_subagent_to_child`` rows with\n``preview`` and empty ``args``). ``todos``/``revision`` are NOT set by the emitter; kept optional\nbecause tool.start rows may pass through connector redaction unchanged.", + "properties": { + "tool_id": { + "title": "Tool Id", + "type": "string" + }, + "name": { + "title": "Name", + "type": "string" + }, + "context": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Context" + }, + "args": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Args" + }, + "args_text": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Args Text" + }, + "preview": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Preview" + } + }, + "required": [ + "tool_id", + "name" + ], + "title": "ToolStartPayload", + "type": "object" + }, + "ToolsAction": { + "enum": [ + "enable", + "disable" + ], + "title": "ToolsAction", + "type": "string" + }, + "ToolsConfigureParams": { + "additionalProperties": false, + "description": "``names`` are toolset keys or ``server:tool`` MCP targets; with ``session_id`` the live session's\nprofile is authoritative and its agent is rebuilt.", + "properties": { + "action": { + "$ref": "#/components/schemas/ToolsAction" + }, + "names": { + "items": { + "type": "string" + }, + "title": "Names", + "type": "array" + }, + "session_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Session Id" + }, + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + } + }, + "required": [ + "action", + "names" + ], + "title": "ToolsConfigureParams", + "type": "object" + }, + "ToolsConfigureResult": { + "additionalProperties": false, + "properties": { + "changed": { + "items": { + "type": "string" + }, + "title": "Changed", + "type": "array" + }, + "enabled_toolsets": { + "items": { + "type": "string" + }, + "title": "Enabled Toolsets", + "type": "array" + }, + "info": { + "anyOf": [ + { + "$ref": "#/components/schemas/SessionLiveInfo" + }, + { + "type": "null" + } + ], + "default": null + }, + "missing_servers": { + "items": { + "type": "string" + }, + "title": "Missing Servers", + "type": "array" + }, + "reset": { + "title": "Reset", + "type": "boolean" + }, + "unknown": { + "items": { + "type": "string" + }, + "title": "Unknown", + "type": "array" + } + }, + "required": [ + "changed", + "enabled_toolsets", + "missing_servers", + "reset", + "unknown" + ], + "title": "ToolsConfigureResult", + "type": "object" + }, + "ToolsShowResult": { + "additionalProperties": false, + "properties": { + "sections": { + "items": { + "$ref": "#/components/schemas/ToolShowSection" + }, + "title": "Sections", + "type": "array" + }, + "total": { + "title": "Total", + "type": "integer" + } + }, + "required": [ + "sections", + "total" + ], + "title": "ToolsShowResult", + "type": "object" + }, + "ToolsetEntry": { + "additionalProperties": false, + "properties": { + "name": { + "title": "Name", + "type": "string" + }, + "enabled": { + "default": true, + "title": "Enabled", + "type": "boolean" + }, + "label": { + "default": "", + "title": "Label", + "type": "string" + }, + "description": { + "default": "", + "title": "Description", + "type": "string" + }, + "tool_count": { + "default": 0, + "title": "Tool Count", + "type": "integer" + } + }, + "required": [ + "name" + ], + "title": "ToolsetEntry", + "type": "object" + }, + "ToolsetRow": { + "additionalProperties": false, + "description": "One row of ``methods_tools._toolset_rows``; ``tools`` only when the caller asked for them\n(``tools.list``).", + "properties": { + "name": { + "title": "Name", + "type": "string" + }, + "description": { + "title": "Description", + "type": "string" + }, + "tool_count": { + "title": "Tool Count", + "type": "integer" + }, + "enabled": { + "title": "Enabled", + "type": "boolean" + }, + "tools": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Tools" + } + }, + "required": [ + "name", + "description", + "tool_count", + "enabled" + ], + "title": "ToolsetRow", + "type": "object" + }, + "ToolsetsListResult": { + "additionalProperties": false, + "properties": { + "toolsets": { + "items": { + "$ref": "#/components/schemas/ToolsetRow" + }, + "title": "Toolsets", + "type": "array" + } + }, + "required": [ + "toolsets" + ], + "title": "ToolsetsListResult", + "type": "object" + }, + "TourRequestParams": { + "additionalProperties": false, + "description": "``tools/tour_tool.py`` field set.", + "properties": { + "session_id": { + "title": "Session Id", + "type": "string" + }, + "action": { + "title": "Action", + "type": "string" + }, + "surface": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Surface" + }, + "selector": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Selector" + }, + "title": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Title" + }, + "text": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Text" + }, + "side": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Side" + }, + "steps": { + "anyOf": [ + { + "items": { + "$ref": "#/components/schemas/TourStep" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Steps" + }, + "step_index": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Step Index" + } + }, + "required": [ + "session_id", + "action" + ], + "title": "TourRequestParams", + "type": "object" + }, + "TourStep": { + "additionalProperties": true, + "properties": { + "selector": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Selector" + }, + "title": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Title" + }, + "text": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Text" + }, + "side": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Side" + } + }, + "title": "TourStep", + "type": "object" + }, + "TranscriptMessage": { + "additionalProperties": true, + "description": "One stored transcript row as ``session.history`` / resume ``messages`` deliver it.", + "properties": { + "role": { + "title": "Role", + "type": "string" + }, + "content": { + "default": null, + "title": "Content" + }, + "timestamp": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Timestamp" + }, + "tool_calls": { + "anyOf": [ + { + "items": { + "additionalProperties": true, + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Tool Calls" + }, + "tool_call_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Tool Call Id" + }, + "name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Name" + }, + "display_kind": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Display Kind" + }, + "row_id": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Row Id" + }, + "reasoning": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Reasoning" + } + }, + "required": [ + "role" + ], + "title": "TranscriptMessage", + "type": "object" + }, + "TurnStatus": { + "description": "``prompt_turn._result_status``.", + "enum": [ + "complete", + "error", + "interrupted" + ], + "title": "TurnStatus", + "type": "string" + }, + "UiMetaConflict": { + "additionalProperties": false, + "properties": { + "expected": { + "default": null, + "title": "Expected" + }, + "actual": { + "default": 0, + "title": "Actual", + "type": "integer" + } + }, + "title": "UiMetaConflict", + "type": "object" + }, + "Usage": { + "additionalProperties": true, + "description": "``tui_gateway/server.py::_get_usage`` + ``agent/context_breakdown.py::context_usage_fields``.", + "properties": { + "model": { + "default": "", + "title": "Model", + "type": "string" + }, + "input": { + "default": 0, + "title": "Input", + "type": "integer" + }, + "output": { + "default": 0, + "title": "Output", + "type": "integer" + }, + "reasoning": { + "default": 0, + "title": "Reasoning", + "type": "integer" + }, + "prompt": { + "default": 0, + "title": "Prompt", + "type": "integer" + }, + "completion": { + "default": 0, + "title": "Completion", + "type": "integer" + }, + "total": { + "default": 0, + "title": "Total", + "type": "integer" + }, + "calls": { + "default": 0, + "title": "Calls", + "type": "integer" + }, + "compressions": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Compressions" + }, + "context_used": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Context Used" + }, + "context_max": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Context Max" + }, + "context_percent": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Context Percent" + }, + "context_source": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Context Source" + }, + "context_estimated": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Context Estimated" + }, + "cache_hit_pct": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Cache Hit Pct" + }, + "cache_read": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Cache Read" + }, + "cache_write": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Cache Write" + }, + "avg_latency_s": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Avg Latency S" + }, + "avg_tps": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Avg Tps" + }, + "active_subagents": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Active Subagents" + }, + "dev_credits_spent_micros": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Dev Credits Spent Micros" + }, + "cost_usd": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Cost Usd" + }, + "cost_status": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Cost Status" + } + }, + "title": "Usage", + "type": "object" + }, + "UsageBar": { + "additionalProperties": false, + "description": "``_serialize_usage_bar``: one bar, magnitudes pre-formatted; ``pct_used`` only for ``plan``.", + "properties": { + "kind": { + "$ref": "#/components/schemas/UsageBarKind" + }, + "remaining_display": { + "title": "Remaining Display", + "type": "string" + }, + "total_display": { + "title": "Total Display", + "type": "string" + }, + "spent_display": { + "title": "Spent Display", + "type": "string" + }, + "pct_used": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Pct Used" + }, + "fill_fraction": { + "title": "Fill Fraction", + "type": "number" + } + }, + "required": [ + "kind", + "remaining_display", + "total_display", + "spent_display", + "fill_fraction" + ], + "title": "UsageBar", + "type": "object" + }, + "UsageBarKind": { + "enum": [ + "plan", + "topup" + ], + "title": "UsageBarKind", + "type": "string" + }, + "UsageModel": { + "additionalProperties": false, + "description": "``_serialize_usage_model`` \u2014 also embedded as ``usage`` in the billing / subscription states,\nwhere the fail-open form is a bare ``{available: false}`` (no ``ok``).", + "properties": { + "ok": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Ok" + }, + "available": { + "title": "Available", + "type": "boolean" + }, + "status": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Status" + }, + "plan_name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Plan Name" + }, + "renews_at": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Renews At" + }, + "renews_display": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Renews Display" + }, + "subscription_remaining_display": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Subscription Remaining Display" + }, + "topup_remaining_display": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Topup Remaining Display" + }, + "total_spendable_display": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Total Spendable Display" + }, + "has_topup": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Has Topup" + }, + "plan_bar": { + "anyOf": [ + { + "$ref": "#/components/schemas/UsageBar" + }, + { + "type": "null" + } + ], + "default": null + }, + "topup_bar": { + "anyOf": [ + { + "$ref": "#/components/schemas/UsageBar" + }, + { + "type": "null" + } + ], + "default": null + } + }, + "required": [ + "available" + ], + "title": "UsageModel", + "type": "object" + }, + "ValueResult": { + "additionalProperties": false, + "description": "The answer to any one-string prompt (sudo, secret, vault prompts, desktop bridges,\nmcp.setup): ``''`` means skipped / declined.", + "properties": { + "value": { + "title": "Value", + "type": "string" + } + }, + "required": [ + "value" + ], + "title": "ValueResult", + "type": "object" + }, + "VaultAddParams": { + "additionalProperties": false, + "description": "``secret`` goes straight into the encrypted store; the result carries only the new id.", + "properties": { + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + }, + "kind": { + "anyOf": [ + { + "$ref": "#/components/schemas/VaultKind" + }, + { + "type": "null" + } + ], + "default": null + }, + "label": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Label" + }, + "origin": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Origin" + }, + "secret": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Secret" + } + }, + "title": "VaultAddParams", + "type": "object" + }, + "VaultAddResult": { + "additionalProperties": false, + "properties": { + "id": { + "title": "Id", + "type": "string" + } + }, + "required": [ + "id" + ], + "title": "VaultAddResult", + "type": "object" + }, + "VaultCodeRequestParams": { + "additionalProperties": false, + "properties": { + "session_id": { + "title": "Session Id", + "type": "string" + }, + "site": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Site" + }, + "hint": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Hint" + } + }, + "required": [ + "session_id" + ], + "title": "VaultCodeRequestParams", + "type": "object" + }, + "VaultItem": { + "additionalProperties": false, + "description": "Metadata-only view (``VaultItemMeta.to_dict`` + ``backend``); never a secret.", + "properties": { + "id": { + "title": "Id", + "type": "string" + }, + "kind": { + "title": "Kind", + "type": "string" + }, + "label": { + "title": "Label", + "type": "string" + }, + "origin": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Origin" + }, + "created_at": { + "default": "", + "title": "Created At", + "type": "string" + }, + "identifier": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Identifier" + }, + "identifier_type": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Identifier Type" + }, + "has_otp": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Has Otp" + }, + "backend": { + "title": "Backend", + "type": "string" + } + }, + "required": [ + "id", + "kind", + "label", + "backend" + ], + "title": "VaultItem", + "type": "object" + }, + "VaultKind": { + "enum": [ + "login", + "payment", + "address" + ], + "title": "VaultKind", + "type": "string" + }, + "VaultListResult": { + "additionalProperties": false, + "properties": { + "items": { + "items": { + "$ref": "#/components/schemas/VaultItem" + }, + "title": "Items", + "type": "array" + } + }, + "title": "VaultListResult", + "type": "object" + }, + "VaultLockParams": { + "additionalProperties": false, + "properties": { + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + }, + "name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Name" + } + }, + "title": "VaultLockParams", + "type": "object" + }, + "VaultLockResult": { + "additionalProperties": false, + "properties": { + "locked": { + "default": true, + "title": "Locked", + "type": "boolean" + } + }, + "title": "VaultLockResult", + "type": "object" + }, + "VaultRemoveParams": { + "additionalProperties": false, + "properties": { + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + }, + "id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Id" + } + }, + "title": "VaultRemoveParams", + "type": "object" + }, + "VaultRemoveResult": { + "additionalProperties": false, + "properties": { + "removed": { + "title": "Removed", + "type": "boolean" + } + }, + "required": [ + "removed" + ], + "title": "VaultRemoveResult", + "type": "object" + }, + "VaultSaveLoginRequestParams": { + "additionalProperties": false, + "properties": { + "session_id": { + "title": "Session Id", + "type": "string" + }, + "origin": { + "title": "Origin", + "type": "string" + }, + "site": { + "title": "Site", + "type": "string" + } + }, + "required": [ + "session_id", + "origin", + "site" + ], + "title": "VaultSaveLoginRequestParams", + "type": "object" + }, + "VaultSource": { + "additionalProperties": false, + "properties": { + "name": { + "title": "Name", + "type": "string" + }, + "display_name": { + "title": "Display Name", + "type": "string" + }, + "enabled": { + "title": "Enabled", + "type": "boolean" + }, + "needs_unlock": { + "title": "Needs Unlock", + "type": "boolean" + }, + "unlocked": { + "title": "Unlocked", + "type": "boolean" + }, + "installed": { + "title": "Installed", + "type": "boolean" + } + }, + "required": [ + "name", + "display_name", + "enabled", + "needs_unlock", + "unlocked", + "installed" + ], + "title": "VaultSource", + "type": "object" + }, + "VaultSourceSetParams": { + "additionalProperties": false, + "properties": { + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + }, + "name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Name" + }, + "enabled": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Enabled" + } + }, + "title": "VaultSourceSetParams", + "type": "object" + }, + "VaultSourceSetResult": { + "additionalProperties": false, + "properties": { + "name": { + "title": "Name", + "type": "string" + }, + "enabled": { + "title": "Enabled", + "type": "boolean" + } + }, + "required": [ + "name", + "enabled" + ], + "title": "VaultSourceSetResult", + "type": "object" + }, + "VaultSourcesResult": { + "additionalProperties": false, + "properties": { + "sources": { + "items": { + "$ref": "#/components/schemas/VaultSource" + }, + "title": "Sources", + "type": "array" + } + }, + "title": "VaultSourcesResult", + "type": "object" + }, + "VaultUnlockParams": { + "additionalProperties": false, + "description": "The master password is consumed by the manager CLI and never stored or logged.", + "properties": { + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + }, + "name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Name" + }, + "password": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Password" + } + }, + "title": "VaultUnlockParams", + "type": "object" + }, + "VaultUnlockRequestParams": { + "additionalProperties": false, + "properties": { + "session_id": { + "title": "Session Id", + "type": "string" + }, + "backend": { + "title": "Backend", + "type": "string" + }, + "display_name": { + "title": "Display Name", + "type": "string" + } + }, + "required": [ + "session_id", + "backend", + "display_name" + ], + "title": "VaultUnlockRequestParams", + "type": "object" + }, + "VaultUnlockResult": { + "additionalProperties": false, + "properties": { + "name": { + "title": "Name", + "type": "string" + }, + "unlocked": { + "default": true, + "title": "Unlocked", + "type": "boolean" + } + }, + "required": [ + "name" + ], + "title": "VaultUnlockResult", + "type": "object" + }, + "VerificationEvidenceRow": { + "additionalProperties": true, + "description": "One ``verification_events`` row (``agent/verification_evidence.py``).", + "properties": { + "id": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Id" + }, + "created_at": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Created At" + }, + "session_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Session Id" + }, + "cwd": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Cwd" + }, + "root": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Root" + }, + "command": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Command" + }, + "canonical_command": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Canonical Command" + }, + "kind": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Kind" + }, + "scope": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Scope" + }, + "status": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Status" + }, + "exit_code": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Exit Code" + }, + "output_summary": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Output Summary" + } + }, + "title": "VerificationEvidenceRow", + "type": "object" + }, + "VerificationStatusInfo": { + "additionalProperties": false, + "description": "``verification_status()``: ``disabled`` / ``not_applicable`` / ``unverified`` / ``stale`` or the\nlatest event's own status; ``root`` and friends only once a workspace was identified.", + "properties": { + "status": { + "title": "Status", + "type": "string" + }, + "evidence": { + "anyOf": [ + { + "$ref": "#/components/schemas/VerificationEvidenceRow" + }, + { + "type": "null" + } + ], + "default": null + }, + "root": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Root" + }, + "session_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Session Id" + }, + "changed_paths": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Changed Paths" + } + }, + "required": [ + "status" + ], + "title": "VerificationStatusInfo", + "type": "object" + }, + "VerificationStatusParams": { + "additionalProperties": false, + "properties": { + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + }, + "session_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Session Id" + }, + "session_key": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Session Key" + }, + "cwd": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Cwd" + } + }, + "title": "VerificationStatusParams", + "type": "object" + }, + "VerificationStatusResult": { + "additionalProperties": false, + "properties": { + "verification": { + "$ref": "#/components/schemas/VerificationStatusInfo" + } + }, + "required": [ + "verification" + ], + "title": "VerificationStatusResult", + "type": "object" + }, + "VoiceRecordAction": { + "enum": [ + "start", + "stop" + ], + "title": "VoiceRecordAction", + "type": "string" + }, + "VoiceRecordParams": { + "additionalProperties": false, + "properties": { + "action": { + "$ref": "#/components/schemas/VoiceRecordAction", + "default": "start" + }, + "session_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Session Id" + }, + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + } + }, + "title": "VoiceRecordParams", + "type": "object" + }, + "VoiceRecordResult": { + "additionalProperties": false, + "properties": { + "status": { + "$ref": "#/components/schemas/VoiceRecordStatus" + }, + "reason": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Reason" + } + }, + "required": [ + "status" + ], + "title": "VoiceRecordResult", + "type": "object" + }, + "VoiceRecordStatus": { + "enum": [ + "recording", + "stopped", + "busy" + ], + "title": "VoiceRecordStatus", + "type": "string" + }, + "VoiceStatusPayload": { + "additionalProperties": false, + "description": "``methods_voice._vr_on_status``; states come from the recorder (idle / listening / transcribing \u2026).", + "properties": { + "state": { + "title": "State", + "type": "string" + } + }, + "required": [ + "state" + ], + "title": "VoiceStatusPayload", + "type": "object" + }, + "VoiceToggleAction": { + "enum": [ + "status", + "on", + "off", + "tts" + ], + "title": "VoiceToggleAction", + "type": "string" + }, + "VoiceToggleParams": { + "additionalProperties": false, + "properties": { + "action": { + "$ref": "#/components/schemas/VoiceToggleAction", + "default": "status" + }, + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + } + }, + "title": "VoiceToggleParams", + "type": "object" + }, + "VoiceToggleResult": { + "additionalProperties": false, + "description": "``methods_voice.py::_voice_status_payload`` (+ the requirements probe on ``status``, the spoken\nstop hint on ``on``).", + "properties": { + "enabled": { + "title": "Enabled", + "type": "boolean" + }, + "record_key": { + "title": "Record Key", + "type": "string" + }, + "tts": { + "title": "Tts", + "type": "boolean" + }, + "stop_hint": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Stop Hint" + }, + "available": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Available" + }, + "audio_available": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Audio Available" + }, + "stt_available": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Stt Available" + }, + "details": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Details" + } + }, + "required": [ + "enabled", + "record_key", + "tts" + ], + "title": "VoiceToggleResult", + "type": "object" + }, + "VoiceTranscriptPayload": { + "additionalProperties": false, + "description": "``methods_voice._vr_transcript`` / ``_deliver_fd_transcript`` / typed stop phrase in methods_prompt.", + "properties": { + "text": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Text" + }, + "stop_phrase": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Stop Phrase" + }, + "typed": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Typed" + }, + "no_speech_limit": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "No Speech Limit" + } + }, + "title": "VoiceTranscriptPayload", + "type": "object" + }, + "VoiceTtsParams": { + "additionalProperties": false, + "properties": { + "text": { + "title": "Text", + "type": "string" + }, + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + } + }, + "required": [ + "text" + ], + "title": "VoiceTtsParams", + "type": "object" + }, + "VoiceTtsResult": { + "additionalProperties": false, + "properties": { + "status": { + "title": "Status", + "type": "string" + } + }, + "required": [ + "status" + ], + "title": "VoiceTtsResult", + "type": "object" + }, + "WaitBarrierTarget": { + "additionalProperties": false, + "properties": { + "type": { + "enum": [ + "session", + "pid" + ], + "title": "Type", + "type": "string" + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "integer" + } + ], + "title": "Target" + }, + "reason": { + "default": "", + "title": "Reason", + "type": "string" + } + }, + "required": [ + "type", + "target" + ], + "title": "WaitBarrierTarget", + "type": "object" + }, + "WaitBarrierUntil": { + "additionalProperties": false, + "properties": { + "type": { + "const": "until", + "title": "Type", + "type": "string" + }, + "until_at": { + "title": "Until At", + "type": "number" + }, + "reason": { + "default": "", + "title": "Reason", + "type": "string" + } + }, + "required": [ + "type", + "until_at" + ], + "title": "WaitBarrierUntil", + "type": "object" + }, + "WakeControlParams": { + "additionalProperties": false, + "properties": { + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + } + }, + "title": "WakeControlParams", + "type": "object" + }, + "WakeDetectedPayload": { + "additionalProperties": false, + "description": "``methods_voice`` wake detector ``_on_detect``.", + "properties": { + "phrase": { + "title": "Phrase", + "type": "string" + }, + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + }, + "start_new_session": { + "title": "Start New Session", + "type": "boolean" + } + }, + "required": [ + "phrase", + "start_new_session" + ], + "title": "WakeDetectedPayload", + "type": "object" + }, + "WakeFeedParams": { + "additionalProperties": false, + "description": "``pcm`` (or the ``pcm_b64`` alias): base64 int16 mono little-endian, 16 kHz only.", + "properties": { + "pcm": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Pcm" + }, + "pcm_b64": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Pcm B64" + }, + "sample_rate": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Sample Rate" + }, + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + } + }, + "title": "WakeFeedParams", + "type": "object" + }, + "WakeFeedResult": { + "additionalProperties": false, + "properties": { + "reason": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Reason" + }, + "fed": { + "title": "Fed", + "type": "boolean" + } + }, + "required": [ + "fed" + ], + "title": "WakeFeedResult", + "type": "object" + }, + "WakeInputDevice": { + "additionalProperties": true, + "description": "``tools/wake_word.py::_describe_input_device`` \u2014 PortAudio diagnostics for the configured mic.", + "properties": { + "selector": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Selector" + }, + "name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Name" + }, + "error": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Error" + }, + "max_input_channels": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Max Input Channels" + }, + "default_samplerate": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Default Samplerate" + }, + "hostapi_index": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Hostapi Index" + }, + "hostapi": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Hostapi" + } + }, + "title": "WakeInputDevice", + "type": "object" + }, + "WakePauseResult": { + "additionalProperties": false, + "properties": { + "reason": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Reason" + }, + "paused": { + "title": "Paused", + "type": "boolean" + } + }, + "required": [ + "paused" + ], + "title": "WakePauseResult", + "type": "object" + }, + "WakeResumeResult": { + "additionalProperties": false, + "properties": { + "reason": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Reason" + }, + "resumed": { + "title": "Resumed", + "type": "boolean" + } + }, + "required": [ + "resumed" + ], + "title": "WakeResumeResult", + "type": "object" + }, + "WakeStartParams": { + "additionalProperties": false, + "description": "``surface`` names the caller (\"tui\" | \"gui\"); ``persist`` is the explicit gesture that also\nflips ``wake_word.enabled`` on; ``client_capture`` asks for PCM streamed via wake.feed.", + "properties": { + "surface": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Surface" + }, + "persist": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Persist" + }, + "client_capture": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Client Capture" + }, + "session_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Session Id" + }, + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + } + }, + "title": "WakeStartParams", + "type": "object" + }, + "WakeStartResult": { + "additionalProperties": false, + "description": "``started: false`` carries ``reason`` (unavailable / disabled / disabled_for_surface / owned);\n``sample_rate`` / ``frame_length`` describe the PCM frames the armed detector expects.", + "properties": { + "started": { + "title": "Started", + "type": "boolean" + }, + "reason": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Reason" + }, + "hint": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Hint" + }, + "phrase": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Phrase" + }, + "provider": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Provider" + }, + "owner_surface": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Owner Surface" + }, + "enabled_persisted": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Enabled Persisted" + }, + "capture": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Capture" + }, + "sample_rate": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Sample Rate" + }, + "frame_length": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Frame Length" + } + }, + "required": [ + "started" + ], + "title": "WakeStartResult", + "type": "object" + }, + "WakeStatusParams": { + "additionalProperties": false, + "properties": { + "surface": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Surface" + }, + "client_capture": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Client Capture" + }, + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + } + }, + "title": "WakeStatusParams", + "type": "object" + }, + "WakeStatusResult": { + "additionalProperties": false, + "description": "``enabled`` is config truth; ``listening`` is this caller's armed detector; ``audio_silent``\nmeans armed but deaf (see ``hint``).", + "properties": { + "listening": { + "title": "Listening", + "type": "boolean" + }, + "owned_by_caller": { + "title": "Owned By Caller", + "type": "boolean" + }, + "owner_surface": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Owner Surface" + }, + "phrase": { + "title": "Phrase", + "type": "string" + }, + "provider": { + "title": "Provider", + "type": "string" + }, + "configured_surface": { + "title": "Configured Surface", + "type": "string" + }, + "input_device": { + "$ref": "#/components/schemas/WakeInputDevice" + }, + "available": { + "title": "Available", + "type": "boolean" + }, + "hint": { + "title": "Hint", + "type": "string" + }, + "enabled": { + "title": "Enabled", + "type": "boolean" + }, + "audio_silent": { + "title": "Audio Silent", + "type": "boolean" + }, + "capture": { + "title": "Capture", + "type": "string" + }, + "local_input_available": { + "title": "Local Input Available", + "type": "boolean" + }, + "sample_rate": { + "title": "Sample Rate", + "type": "integer" + }, + "frame_length": { + "title": "Frame Length", + "type": "integer" + } + }, + "required": [ + "listening", + "owned_by_caller", + "phrase", + "provider", + "configured_surface", + "input_device", + "available", + "hint", + "enabled", + "audio_silent", + "capture", + "local_input_available", + "sample_rate", + "frame_length" + ], + "title": "WakeStatusResult", + "type": "object" + }, + "WakeStopParams": { + "additionalProperties": false, + "properties": { + "persist": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Persist" + }, + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Profile" + } + }, + "title": "WakeStopParams", + "type": "object" + }, + "WakeStopResult": { + "additionalProperties": false, + "properties": { + "reason": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Reason" + }, + "stopped": { + "title": "Stopped", + "type": "boolean" + }, + "disabled_persisted": { + "title": "Disabled Persisted", + "type": "boolean" + } + }, + "required": [ + "stopped", + "disabled_persisted" + ], + "title": "WakeStopResult", + "type": "object" + }, + "_SessionScoped": { + "additionalProperties": false, + "description": "Handlers that look a live session up with ``_sessions.get(params.get(\"session_id\"))``: an\nabsent / unknown id falls back to the launch profile's config, so it is never required.", + "properties": { + "session_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Session Id" + } + }, + "title": "_SessionScoped", + "type": "object" + }, + "tui_gateway_contracts_billing_delegation_pets_MessageReaction": { + "additionalProperties": true, + "description": "One persisted reaction (``hermes_state_messages.py``); ``seen`` is stamped once announced.", + "properties": { + "emoji": { + "title": "Emoji", + "type": "string" + }, + "author": { + "title": "Author", + "type": "string" + }, + "at": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "default": null, + "title": "At" + }, + "seen": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Seen" + } + }, + "required": [ + "emoji", + "author" + ], + "title": "MessageReaction", + "type": "object" + }, + "tui_gateway_contracts_config_free_tier_control_SessionControlSnapshot": { + "additionalProperties": false, + "description": "``_snapshot_control`` \u2014 ``revision`` is a hash of the visible state (``\"\"`` when empty);\n``updated_at`` is the newest persisted timestamp (``0`` when none).", + "properties": { + "goal": { + "anyOf": [ + { + "$ref": "#/components/schemas/GoalSnapshot" + }, + { + "type": "null" + } + ] + }, + "loop": { + "anyOf": [ + { + "$ref": "#/components/schemas/LoopSnapshot" + }, + { + "type": "null" + } + ] + }, + "heartbeat": { + "anyOf": [ + { + "$ref": "#/components/schemas/HeartbeatSnapshot" + }, + { + "type": "null" + } + ] + }, + "revision": { + "title": "Revision", + "type": "string" + }, + "updated_at": { + "title": "Updated At", + "type": "number" + } + }, + "required": [ + "goal", + "loop", + "heartbeat", + "revision", + "updated_at" + ], + "title": "SessionControlSnapshot", + "type": "object" + }, + "tui_gateway_contracts_events_MessageReaction": { + "additionalProperties": true, + "description": "``hermes_state_messages.set_message_reaction`` row.", + "properties": { + "emoji": { + "title": "Emoji", + "type": "string" + }, + "author": { + "title": "Author", + "type": "string" + }, + "at": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "default": null, + "title": "At" + } + }, + "required": [ + "emoji", + "author" + ], + "title": "MessageReaction", + "type": "object" + }, + "tui_gateway_contracts_events_SessionControlSnapshot": { + "additionalProperties": true, + "description": "``methods_session_control._snapshot_control``; goal / loop / heartbeat sub-objects are the\nallow-listed state-file projections (owned by hermes_cli.goals / loops / heartbeat).", + "properties": { + "goal": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Goal" + }, + "loop": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Loop" + }, + "heartbeat": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Heartbeat" + }, + "revision": { + "default": "", + "title": "Revision", + "type": "string" + }, + "updated_at": { + "default": 0, + "title": "Updated At", + "type": "number" + } + }, + "title": "SessionControlSnapshot", + "type": "object" + }, + "tui_gateway_contracts_groups_bot_relay_ApprovalChoice": { + "enum": [ + "once", + "deny" + ], + "title": "ApprovalChoice", + "type": "string" + }, + "tui_gateway_contracts_prompt_voice_PendingApproval": { + "additionalProperties": true, + "description": "One unresolved ``tools/approval.py`` gateway queue entry (snapshot of its ``data``); the key\nset is owned by the approval tool, so it stays open.", + "properties": { + "request_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Request Id" + }, + "command": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Command" + }, + "description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Description" + }, + "pattern_key": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Pattern Key" + }, + "pattern_keys": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Pattern Keys" + }, + "allow_permanent": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Allow Permanent" + }, + "allow_session": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Allow Session" + }, + "smart_denied": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Smart Denied" + }, + "choices": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Choices" + }, + "tool_name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Tool Name" + } + }, + "title": "PendingApproval", + "type": "object" + }, + "tui_gateway_contracts_server_requests_ApprovalChoice": { + "enum": [ + "once", + "session", + "always", + "deny" + ], + "title": "ApprovalChoice", + "type": "string" + }, + "tui_gateway_contracts_sessions_PendingApproval": { + "additionalProperties": true, + "description": "``server._approval_request_payload`` for the oldest unresolved approval (command redacted).", + "properties": { + "request_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Request Id" + }, + "command": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Command" + }, + "description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Description" + }, + "choices": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Choices" + }, + "allow_permanent": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Allow Permanent" + }, + "allow_session": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Allow Session" + }, + "smart_denied": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Smart Denied" + }, + "tool_name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Tool Name" + } + }, + "title": "PendingApproval", + "type": "object" + } + } + }, + "x-server-requests": [ + { + "name": "approval", + "summary": "A dangerous command awaits the user's decision.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/ApprovalRequestParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/ApprovalResult" + } + } + }, + { + "name": "clarify", + "summary": "The clarify tool: ask the user one question or a batch.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/ClarifyRequestParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/ClarifyResult" + } + } + }, + { + "name": "mcp.setup", + "summary": "Consent card for installing / enabling / authorising an MCP server.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/McpSetupRequestParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/ValueResult" + } + } + }, + { + "name": "preview.act", + "summary": "Click / type / scroll / annotate inside the in-app browser preview.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/PreviewActRequestParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/ValueResult" + } + } + }, + { + "name": "preview.read", + "summary": "Read the in-app browser preview's text (JSON text answer).", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/ReadRangeRequestParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/ValueResult" + } + } + }, + { + "name": "secret", + "summary": "Masked value for a named env var (skills / setup flows).", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/SecretRequestParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/ValueResult" + } + } + }, + { + "name": "sudo", + "summary": "Masked sudo password for the terminal tool.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/EmptyRequestParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/ValueResult" + } + } + }, + { + "name": "terminal.read", + "summary": "Read the visible in-app terminal buffer (JSON text answer).", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/ReadRangeRequestParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/ValueResult" + } + } + }, + { + "name": "tour", + "summary": "Drive a guided tour highlight in the desktop renderer.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/TourRequestParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/ValueResult" + } + } + }, + { + "name": "vault.code", + "summary": "A one-time / 2FA code the user reads from their device.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/VaultCodeRequestParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/ValueResult" + } + } + }, + { + "name": "vault.save_login", + "summary": "Save a login for a site the agent is about to fill; the answer is JSON {identifier, password}.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/VaultSaveLoginRequestParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/ValueResult" + } + } + }, + { + "name": "vault.unlock_prompt", + "summary": "Master password to unlock an external password manager for this session.", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/VaultUnlockRequestParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/ValueResult" + } + } + }, + { + "name": "window.read", + "summary": "Enumerate the native window below the app (JSON text answer).", + "params": [ + { + "name": "params", + "schema": { + "$ref": "#/components/schemas/EmptyRequestParams" + } + } + ], + "result": { + "name": "result", + "schema": { + "$ref": "#/components/schemas/ValueResult" + } + } + } + ], + "x-notifications": [ + { + "name": "agent.terminal.output", + "summary": "Output chunk from an agent-owned background process.", + "params": [ + { + "name": "payload", + "schema": { + "$ref": "#/components/schemas/TerminalOutputPayload" + } + } + ] + }, + { + "name": "background.complete", + "summary": "A /background side agent finished.", + "params": [ + { + "name": "payload", + "schema": { + "$ref": "#/components/schemas/SideAgentCompletePayload" + } + } + ] + }, + { + "name": "billing.step_up.verification", + "summary": "Device-flow URL + code for the billing scope step-up; the client opens the browser.", + "params": [ + { + "name": "payload", + "schema": { + "$ref": "#/components/schemas/BillingStepUpVerificationPayload" + } + } + ] + }, + { + "name": "bot_relay.outbox.pending", + "summary": "A bot-relay outbox envelope is queued; drain it.", + "params": [ + { + "name": "payload", + "schema": { + "$ref": "#/components/schemas/ChangeSignalPayload" + } + } + ] + }, + { + "name": "browser.controller.cancel", + "summary": "Withdraw a pending controller command.", + "params": [ + { + "name": "payload", + "schema": { + "$ref": "#/components/schemas/BrowserControllerCancelPayload" + } + } + ] + }, + { + "name": "browser.controller.command", + "summary": "Dispatch one browser action to the attached controller.", + "params": [ + { + "name": "payload", + "schema": { + "$ref": "#/components/schemas/BrowserControllerCommandPayload" + } + } + ] + }, + { + "name": "browser.progress", + "summary": "Browser (CDP) connect / install progress line.", + "params": [ + { + "name": "payload", + "schema": { + "$ref": "#/components/schemas/BrowserProgressPayload" + } + } + ] + }, + { + "name": "btw.complete", + "summary": "A /btw side question was answered.", + "params": [ + { + "name": "payload", + "schema": { + "$ref": "#/components/schemas/SideAgentCompletePayload" + } + } + ] + }, + { + "name": "cron.changed", + "summary": "cron/jobs.json moved; refetch the cron list.", + "params": [ + { + "name": "payload", + "schema": { + "$ref": "#/components/schemas/ChangeSignalPayload" + } + } + ] + }, + { + "name": "error", + "summary": "A session-level failure outside a turn (agent init, model switch, compression, resume).", + "params": [ + { + "name": "payload", + "schema": { + "$ref": "#/components/schemas/ErrorPayload" + } + } + ] + }, + { + "name": "gateway.ready", + "summary": "First frame of a connection: the resolved skin, the change-event capability and the replay epoch.", + "params": [ + { + "name": "payload", + "schema": { + "$ref": "#/components/schemas/GatewayReadyPayload" + } + } + ] + }, + { + "name": "layout.apply", + "summary": "Apply a named desktop layout preset.", + "params": [ + { + "name": "payload", + "schema": { + "$ref": "#/components/schemas/LayoutApplyPayload" + } + } + ] + }, + { + "name": "message.complete", + "summary": "The turn ended: final text, usage and outcome.", + "params": [ + { + "name": "payload", + "schema": { + "$ref": "#/components/schemas/MessageCompletePayload" + } + } + ] + }, + { + "name": "message.delta", + "summary": "One streamed chunk of the assistant reply.", + "params": [ + { + "name": "payload", + "schema": { + "$ref": "#/components/schemas/StreamDeltaPayload" + } + } + ] + }, + { + "name": "message.interim", + "summary": "Interim assistant commentary (text beside tool calls) sealed as its own segment.", + "params": [ + { + "name": "payload", + "schema": { + "$ref": "#/components/schemas/MessageInterimPayload" + } + } + ] + }, + { + "name": "message.reaction", + "summary": "The agent reacted to a message; paint it live.", + "params": [ + { + "name": "payload", + "schema": { + "$ref": "#/components/schemas/MessageReactionPayload" + } + } + ] + }, + { + "name": "message.start", + "summary": "A turn began streaming; no payload.", + "params": [ + { + "name": "payload", + "schema": { + "type": "object", + "additionalProperties": false + } + } + ] + }, + { + "name": "moa.aggregating", + "summary": "The MoA aggregator started.", + "params": [ + { + "name": "payload", + "schema": { + "$ref": "#/components/schemas/MoaAggregatingPayload" + } + } + ] + }, + { + "name": "moa.phase", + "summary": "MoA phase transition (currently only ``aggregator``).", + "params": [ + { + "name": "payload", + "schema": { + "$ref": "#/components/schemas/MoaPhasePayload" + } + } + ] + }, + { + "name": "moa.progress", + "summary": "MoA reference fan-out progress (n/total).", + "params": [ + { + "name": "payload", + "schema": { + "$ref": "#/components/schemas/MoaProgressPayload" + } + } + ] + }, + { + "name": "moa.reference", + "summary": "One MoA reference model's output.", + "params": [ + { + "name": "payload", + "schema": { + "$ref": "#/components/schemas/MoaReferencePayload" + } + } + ] + }, + { + "name": "notice", + "summary": "Informational one-liner for the session (capabilities refreshed).", + "params": [ + { + "name": "payload", + "schema": { + "$ref": "#/components/schemas/NoticePayload" + } + } + ] + }, + { + "name": "notification.clear", + "summary": "Withdraw the notice with this key.", + "params": [ + { + "name": "payload", + "schema": { + "$ref": "#/components/schemas/NotificationClearPayload" + } + } + ] + }, + { + "name": "notification.show", + "summary": "Show / replace a keyed out-of-band notice (toast or status bar).", + "params": [ + { + "name": "payload", + "schema": { + "$ref": "#/components/schemas/NotificationShowPayload" + } + } + ] + }, + { + "name": "pairing.changed", + "summary": "Pairing state moved; refetch pairing.", + "params": [ + { + "name": "payload", + "schema": { + "$ref": "#/components/schemas/ChangeSignalPayload" + } + } + ] + }, + { + "name": "pane.reveal", + "summary": "Focus / reveal a named desktop pane.", + "params": [ + { + "name": "payload", + "schema": { + "$ref": "#/components/schemas/PaneRevealPayload" + } + } + ] + }, + { + "name": "pet.changed", + "summary": "The active pet / its spritesheet changed (watcher).", + "params": [ + { + "name": "payload", + "schema": { + "$ref": "#/components/schemas/PetChangedPayload" + } + } + ] + }, + { + "name": "pet.generate.progress", + "summary": "Pet base-draft generation progress.", + "params": [ + { + "name": "payload", + "schema": { + "$ref": "#/components/schemas/PetGenerateProgressPayload" + } + } + ] + }, + { + "name": "pet.hatch.progress", + "summary": "Pet hatch (row drawing) progress.", + "params": [ + { + "name": "payload", + "schema": { + "$ref": "#/components/schemas/PetHatchProgressPayload" + } + } + ] + }, + { + "name": "platforms.changed", + "summary": "gateway_state.json moved; refetch platform status.", + "params": [ + { + "name": "payload", + "schema": { + "$ref": "#/components/schemas/ChangeSignalPayload" + } + } + ] + }, + { + "name": "preview.close", + "summary": "Close the preview pane or one tab.", + "params": [ + { + "name": "payload", + "schema": { + "$ref": "#/components/schemas/PreviewClosePayload" + } + } + ] + }, + { + "name": "preview.open", + "summary": "Open a URL / file in the desktop preview pane.", + "params": [ + { + "name": "payload", + "schema": { + "$ref": "#/components/schemas/PreviewOpenPayload" + } + } + ] + }, + { + "name": "preview.restart.complete", + "summary": "The hidden preview-restart agent finished.", + "params": [ + { + "name": "payload", + "schema": { + "$ref": "#/components/schemas/SideAgentCompletePayload" + } + } + ] + }, + { + "name": "preview.restart.progress", + "summary": "Progress line from the preview-restart agent.", + "params": [ + { + "name": "payload", + "schema": { + "$ref": "#/components/schemas/PreviewRestartProgressPayload" + } + } + ] + }, + { + "name": "reaction", + "summary": "Affection reaction detected in the user's message (hearts etc.).", + "params": [ + { + "name": "payload", + "schema": { + "$ref": "#/components/schemas/ReactionPayload" + } + } + ] + }, + { + "name": "reasoning.available", + "summary": "A completed reasoning block (non-streaming providers).", + "params": [ + { + "name": "payload", + "schema": { + "$ref": "#/components/schemas/StreamDeltaPayload" + } + } + ] + }, + { + "name": "reasoning.delta", + "summary": "One streamed chunk of the model's reasoning.", + "params": [ + { + "name": "payload", + "schema": { + "$ref": "#/components/schemas/StreamDeltaPayload" + } + } + ] + }, + { + "name": "request.cancel", + "summary": "The backend withdrew an open server\u2192client request; clear the matching card only.", + "params": [ + { + "name": "payload", + "schema": { + "$ref": "#/components/schemas/RequestCancelPayload" + } + } + ] + }, + { + "name": "review.summary", + "summary": "Background review of the last turn finished.", + "params": [ + { + "name": "payload", + "schema": { + "$ref": "#/components/schemas/ReviewSummaryPayload" + } + } + ] + }, + { + "name": "session.control.update", + "summary": "Persisted goal / loop / heartbeat state changed.", + "params": [ + { + "name": "payload", + "schema": { + "$ref": "#/components/schemas/SessionControlUpdatePayload" + } + } + ] + }, + { + "name": "session.info", + "summary": "Live session settings snapshot (``server._session_info``); also the ``info`` of create/resume/activate.", + "params": [ + { + "name": "payload", + "schema": { + "$ref": "#/components/schemas/SessionLiveInfo" + } + } + ] + }, + { + "name": "session.reclaimed", + "summary": "The backend reclaimed a live session out from under its clients.", + "params": [ + { + "name": "payload", + "schema": { + "$ref": "#/components/schemas/SessionReclaimedPayload" + } + } + ] + }, + { + "name": "session.resume_progress", + "summary": "Deferred resume hydration progress.", + "params": [ + { + "name": "payload", + "schema": { + "$ref": "#/components/schemas/SessionResumeProgressPayload" + } + } + ] + }, + { + "name": "session.title", + "summary": "Auto-titling renamed the session (``session_id`` is the stored key).", + "params": [ + { + "name": "payload", + "schema": { + "$ref": "#/components/schemas/SessionTitlePayload" + } + } + ] + }, + { + "name": "session.usage", + "summary": "Mid-turn usage tick; message.complete carries the authoritative final usage.", + "params": [ + { + "name": "payload", + "schema": { + "$ref": "#/components/schemas/SessionUsagePayload" + } + } + ] + }, + { + "name": "sessions.changed", + "summary": "state.db moved; refetch the session list.", + "params": [ + { + "name": "payload", + "schema": { + "$ref": "#/components/schemas/ChangeSignalPayload" + } + } + ] + }, + { + "name": "setup.ready", + "summary": "The free-tier bootstrap finished (broadcast); the desktop's setup gate reads the record.", + "params": [ + { + "name": "payload", + "schema": { + "$ref": "#/components/schemas/SetupReadyPayload" + } + } + ] + }, + { + "name": "skin.changed", + "summary": "The active skin moved (name switch or live colour edit); repaint from this palette.", + "params": [ + { + "name": "payload", + "schema": { + "$ref": "#/components/schemas/SkinPayload" + } + } + ] + }, + { + "name": "status.update", + "summary": "Transient status line (kind: status, lifecycle, compacting, goal, loop, heartbeat, process, \u2026).", + "params": [ + { + "name": "payload", + "schema": { + "$ref": "#/components/schemas/StatusUpdatePayload" + } + } + ] + }, + { + "name": "subagent.complete", + "summary": "A child finished (status + observability rollup).", + "params": [ + { + "name": "payload", + "schema": { + "$ref": "#/components/schemas/SubagentEventPayload" + } + } + ] + }, + { + "name": "subagent.progress", + "summary": "Batched tool-name progress from a child.", + "params": [ + { + "name": "payload", + "schema": { + "$ref": "#/components/schemas/SubagentEventPayload" + } + } + ] + }, + { + "name": "subagent.spawn_requested", + "summary": "delegate_task accepted a child goal (before the child starts).", + "params": [ + { + "name": "payload", + "schema": { + "$ref": "#/components/schemas/SubagentEventPayload" + } + } + ] + }, + { + "name": "subagent.start", + "summary": "A delegated child started running.", + "params": [ + { + "name": "payload", + "schema": { + "$ref": "#/components/schemas/SubagentEventPayload" + } + } + ] + }, + { + "name": "subagent.thinking", + "summary": "A child's reasoning chunk.", + "params": [ + { + "name": "payload", + "schema": { + "$ref": "#/components/schemas/SubagentEventPayload" + } + } + ] + }, + { + "name": "subagent.tool", + "summary": "A child called a tool.", + "params": [ + { + "name": "payload", + "schema": { + "$ref": "#/components/schemas/SubagentEventPayload" + } + } + ] + }, + { + "name": "terminal.close", + "summary": "An agent-owned background process closed.", + "params": [ + { + "name": "payload", + "schema": { + "$ref": "#/components/schemas/TerminalClosePayload" + } + } + ] + }, + { + "name": "thinking.delta", + "summary": "Legacy thinking-text chunk (thinking_callback).", + "params": [ + { + "name": "payload", + "schema": { + "$ref": "#/components/schemas/StreamDeltaPayload" + } + } + ] + }, + { + "name": "tip.show", + "summary": "Point at a desktop element with a one-line tip bubble.", + "params": [ + { + "name": "payload", + "schema": { + "$ref": "#/components/schemas/TipShowPayload" + } + } + ] + }, + { + "name": "todo.updated", + "summary": "Full todo snapshot after a todo tool ran.", + "params": [ + { + "name": "payload", + "schema": { + "$ref": "#/components/schemas/TodoUpdatedPayload" + } + } + ] + }, + { + "name": "tool.complete", + "summary": "A tool call finished: parsed result, summary, optional diff / todo snapshot.", + "params": [ + { + "name": "payload", + "schema": { + "$ref": "#/components/schemas/ToolCompletePayload" + } + } + ] + }, + { + "name": "tool.generating", + "summary": "The model is emitting a tool call's arguments.", + "params": [ + { + "name": "payload", + "schema": { + "$ref": "#/components/schemas/ToolGeneratingPayload" + } + } + ] + }, + { + "name": "tool.output_risk", + "summary": "Tool output was classified as risky (prompt-injection / secret findings).", + "params": [ + { + "name": "payload", + "schema": { + "$ref": "#/components/schemas/ToolOutputRiskPayload" + } + } + ] + }, + { + "name": "tool.start", + "summary": "A tool call began (stable id + full args).", + "params": [ + { + "name": "payload", + "schema": { + "$ref": "#/components/schemas/ToolStartPayload" + } + } + ] + }, + { + "name": "voice.interrupted", + "summary": "Barge-in: the spoken interjection interrupted the turn; no payload.", + "params": [ + { + "name": "payload", + "schema": { + "type": "object", + "additionalProperties": false + } + } + ] + }, + { + "name": "voice.status", + "summary": "Voice recorder state changed.", + "params": [ + { + "name": "payload", + "schema": { + "$ref": "#/components/schemas/VoiceStatusPayload" + } + } + ] + }, + { + "name": "voice.transcript", + "summary": "A voice capture produced text (or a stop phrase / silence limit).", + "params": [ + { + "name": "payload", + "schema": { + "$ref": "#/components/schemas/VoiceTranscriptPayload" + } + } + ] + }, + { + "name": "wake.detected", + "summary": "A wake phrase fired.", + "params": [ + { + "name": "payload", + "schema": { + "$ref": "#/components/schemas/WakeDetectedPayload" + } + } + ] + } + ] +} diff --git a/scripts/ci/classify_changes.py b/scripts/ci/classify_changes.py index 6bf01febee..2e3534bd02 100644 --- a/scripts/ci/classify_changes.py +++ b/scripts/ci/classify_changes.py @@ -96,8 +96,9 @@ _PY_RELEVANT_SITE = ( # Editing only the JSON in an apps/-only PR would otherwise skip the one test # that can catch the drift, so these force the Python lane too. _PY_RELEVANT_CONTRACT_FILES = { - # tests/tui_gateway/test_gateway_event_contract.py - "apps/shared/src/gateway-events.json", + # tests/contracts/test_generated.py (rendered from tui_gateway/contracts) + "apps/shared/src/gateway-contract.generated.ts", + "apps/shared/src/gateway-contract.openrpc.json", # tests/hermes_cli/test_desktop_slash_registry.py "apps/desktop/src/lib/desktop-slash-registry.json", } diff --git a/scripts/gen_gateway_contracts.py b/scripts/gen_gateway_contracts.py index d67091b5de..a1774100c6 100644 --- a/scripts/gen_gateway_contracts.py +++ b/scripts/gen_gateway_contracts.py @@ -13,6 +13,7 @@ from __future__ import annotations import json import re import subprocess +import sys from collections import OrderedDict from pathlib import Path from typing import Any @@ -20,10 +21,13 @@ from typing import Any from pydantic import TypeAdapter from pydantic.json_schema import GenerateJsonSchema -from tui_gateway import contracts # noqa: F401 (imports every topic module → fills the tables) -from tui_gateway.contracts.registry import EVENTS, METHODS, SERVER_REQUESTS - ROOT = Path(__file__).resolve().parent.parent +if str(ROOT) not in sys.path: + sys.path.insert(0, str(ROOT)) + +from tui_gateway import contracts # noqa: E402,F401 (imports every topic module → fills the tables) +from tui_gateway.contracts.registry import EVENTS, METHODS, SERVER_REQUESTS # noqa: E402 + TS_OUT = ROOT / "apps" / "shared" / "src" / "gateway-contract.generated.ts" OPENRPC_OUT = ROOT / "apps" / "shared" / "src" / "gateway-contract.openrpc.json" @@ -73,8 +77,9 @@ class Renderer: if "enum" in schema: return " | ".join(json.dumps(v) for v in schema["enum"]) if "anyOf" in schema or "oneOf" in schema: - variants = schema.get("anyOf") or schema.get("oneOf") - return " | ".join(self.type_of(v, inline_depth=inline_depth) for v in variants) + variants = schema.get("anyOf") or schema.get("oneOf") or [] + rendered = list(dict.fromkeys(self.type_of(v, inline_depth=inline_depth) for v in variants)) + return " | ".join(rendered) t = schema.get("type") if isinstance(t, list): return " | ".join(self.type_of({**schema, "type": x}, inline_depth=inline_depth) for x in t) @@ -127,7 +132,7 @@ class Renderer: doc = _doc(schema.get("description")) if "enum" in schema: body = f"export type {name} = {self.type_of({'enum': schema['enum']})}\n" - elif "properties" in schema or schema.get("type") == "object": + elif schema.get("properties"): body = f"export interface {name} {self.object_literal(schema, 0)}\n" else: body = f"export type {name} = {self.type_of(schema)}\n" @@ -289,8 +294,6 @@ def render_all() -> dict[Path, str]: def main(argv: list[str] | None = None) -> int: - import sys - args = argv if argv is not None else sys.argv[1:] check = "--check" in args stale = [] diff --git a/tests/ci/test_classify_changes.py b/tests/ci/test_classify_changes.py index e5f312c18c..3a8d0f88b9 100644 --- a/tests/ci/test_classify_changes.py +++ b/tests/ci/test_classify_changes.py @@ -101,8 +101,12 @@ CASES = { "frontend → no uv_lock": (["apps/desktop/src/store/profile.ts"], _lanes(frontend=True)), # Cross-language contract JSON under apps/: the pytest that pins it against # the Python side must run even when nothing else in the PR is Python. - "gateway-events contract JSON → python + frontend": ( - ["apps/shared/src/gateway-events.json"], + "generated gateway contract → python + frontend": ( + ["apps/shared/src/gateway-contract.generated.ts"], + _lanes(python=True, frontend=True), + ), + "gateway OpenRPC document → python + frontend": ( + ["apps/shared/src/gateway-contract.openrpc.json"], _lanes(python=True, frontend=True), ), "desktop slash-registry JSON → python + frontend": ( diff --git a/tests/contracts/__init__.py b/tests/contracts/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/contracts/test_generated.py b/tests/contracts/test_generated.py new file mode 100644 index 0000000000..a67d22ac20 --- /dev/null +++ b/tests/contracts/test_generated.py @@ -0,0 +1,89 @@ +"""The committed TypeScript + OpenRPC contract files are exactly what ``tui_gateway/contracts`` +renders, and the contract catalog covers the whole wire. + +Regenerate with ``.venv/bin/python scripts/gen_gateway_contracts.py`` when a model changes. The +two files are listed in ``scripts/ci/classify_changes.py::_PY_RELEVANT_CONTRACT_FILES`` so a +TS-only PR that edits them still runs this test. +""" + +from __future__ import annotations + +import importlib.util +import re +from pathlib import Path + +import pytest + +REPO = Path(__file__).resolve().parents[2] +GEN = REPO / "scripts" / "gen_gateway_contracts.py" + + +@pytest.fixture(scope="module") +def gen(): + spec = importlib.util.spec_from_file_location("gen_gateway_contracts", GEN) + module = importlib.util.module_from_spec(spec) + spec.loader.exec_module(module) + return module + + +def test_generated_files_are_current(gen): + """Both committed artefacts equal an in-memory regeneration (byte-for-byte).""" + stale = [path.relative_to(REPO) for path, text in gen.render_all().items() + if (path.read_text(encoding="utf-8") if path.exists() else None) != text] + assert not stale, f"stale generated contract files {stale}: run scripts/gen_gateway_contracts.py" + + +# The emitter inventory the old gateway-events.json scan used, kept as the completeness oracle: +# names must come from CODE the gateway runs, never from the contract tables themselves. +_EMIT_HELPERS = ("_emit", "_broadcast_global_event", "_voice_emit", "_pet_emit", "_emit_tool_lifecycle") +_LITERAL_EMIT = re.compile(r"\b(?:%s)\(\s*\"([a-z_][a-z0-9_.]*)\"" % "|".join(_EMIT_HELPERS)) +_REQUEST_HELPERS = ("server_requests\\.send", "server_requests\\.send_async", "_ask", "_read_block") +_LITERAL_REQUEST = re.compile(r"\b(?:%s)\(\s*\"([a-z_][a-z0-9_.]*)\"" % "|".join(_REQUEST_HELPERS)) +_LITERAL_FRAME = re.compile(r"\"method\":\s*\"event\".{0,120}?\"type\":\s*\"([a-z_][a-z0-9_.]*)\"", re.S) +_SIDE_AGENT = re.compile(r"_spawn_side_agent\((?:[^()]|\([^()]*\))*?\"([a-z_][a-z0-9_.]*\.complete)\"", re.S) +_SUBAGENT_RELAY = re.compile(r"\"(subagent\.[a-z_]+)\"") +_DESKTOP_UI_EMIT = re.compile(r"desktop_ui\.(?:emit|emit_or_error)\(\s*\"([a-z_][a-z0-9_.]*)\"") +_BROKER_FRAME = re.compile(r"^FRAME_[A-Z_]+ = \"(browser\.controller\.[a-z_]+)\"", re.M) +_SETUP_READY = re.compile(r"^SETUP_READY_EVENT = \"([a-z_.]+)\"", re.M) + + +def _read(path: Path) -> str: + return path.read_text(encoding="utf-8") + + +def emitted_event_names() -> set[str]: + names: set[str] = set() + for src in (REPO / "tui_gateway").glob("*.py"): + text = _read(src) + names.update(_LITERAL_EMIT.findall(text)) + names.update(_LITERAL_FRAME.findall(text)) + names.update(_SIDE_AGENT.findall(text)) + from tui_gateway.agent_callbacks import _CHILD_DELTA_EVENTS + from tui_gateway.change_watcher import _CHANGE_WATCHES + + names.update(_CHANGE_WATCHES) + names.update(_CHILD_DELTA_EVENTS.values()) + for src in (REPO / "tools").glob("delegate_tool*.py"): + names.update(_SUBAGENT_RELAY.findall(_read(src))) + names.discard("subagent.text") # mirrored into the watch window as message.delta, never emitted + for src in (REPO / "tools").glob("*.py"): + names.update(_DESKTOP_UI_EMIT.findall(_read(src))) + names.update(_BROKER_FRAME.findall(_read(REPO / "gateway" / "browser_control_broker.py"))) + names.update(_SETUP_READY.findall(_read(REPO / "hermes_cli" / "free_tier_bootstrap.py"))) + return names + + +def sent_server_requests() -> set[str]: + names: set[str] = set() + for src in (REPO / "tui_gateway").glob("*.py"): + names.update(_LITERAL_REQUEST.findall(_read(src))) + return names + + +def test_catalog_covers_the_whole_wire(): + """Every registered method, every emitted event and every sent server request has a contract, + and no contract is orphaned (a deleted handler must take its contract with it).""" + from tui_gateway import server + from tui_gateway.contracts import registry + + registry.assert_complete(server._methods, emitted_event_names(), sent_server_requests()) diff --git a/tui_gateway/contracts/billing_delegation_pets.py b/tui_gateway/contracts/billing_delegation_pets.py index c8361fe11c..fe1ea70e12 100644 --- a/tui_gateway/contracts/billing_delegation_pets.py +++ b/tui_gateway/contracts/billing_delegation_pets.py @@ -1 +1,628 @@ -"""Contracts: billing_delegation_pets (authored by the contract worker).""" +"""Contracts: billing / subscription / usage envelopes, delegation controls, handoff, message +reactions, pet generation and ``project.facts`` (handlers in ``tui_gateway/methods_session.py``). + +Billing routes are FAIL-OPEN: a logged-out / unreachable portal answers an ``ok`` result whose +``error`` carries the typed code (``_serialize_billing_error``) — never a JSON-RPC error — so the +client always resolves and branches on the envelope. ``BillingEnvelope`` is that shared shape. +""" + +from __future__ import annotations + +from pydantic import Field + +from .base import JsonValue, Params, Result, WireEnum +from .common import OpenModel, ProfileParams, SessionParams +from .registry import method + +# ── billing envelope ────────────────────────────────────────────────────────────────────────── + + +class BillingEnvelope(Result): + """``tui_gateway/billing_view.py::_serialize_billing_error`` on failure (``ok`` false + typed + ``error``); success routes add their own fields. ``payload`` is the raw portal body (error + extras such as ``remainingUsd``, or the NAS success body on pending-change routes).""" + + ok: bool + error: str | None = None + message: str | None = None + portal_url: str | None = None + retry_after: int | float | None = None + payload: dict[str, JsonValue] | None = None + actor: str | None = None + code: str | None = None + recovery: str | None = None + + +# ── usage.bars (shared two-bar dollar model) ────────────────────────────────────────────────── + + +class UsageBarKind(WireEnum): + plan = "plan" + topup = "topup" + + +class UsageBar(Result): + """``_serialize_usage_bar``: one bar, magnitudes pre-formatted; ``pct_used`` only for ``plan``.""" + + kind: UsageBarKind + remaining_display: str + total_display: str + spent_display: str + pct_used: int | None = None + fill_fraction: float + + +class UsageModel(Result): + """``_serialize_usage_model`` — also embedded as ``usage`` in the billing / subscription states, + where the fail-open form is a bare ``{available: false}`` (no ``ok``).""" + + ok: bool | None = None + available: bool + status: str | None = None + plan_name: str | None = None + renews_at: str | None = None + renews_display: str | None = None + subscription_remaining_display: str | None = None + topup_remaining_display: str | None = None + total_spendable_display: str | None = None + has_topup: bool | None = None + plan_bar: UsageBar | None = None + topup_bar: UsageBar | None = None + + +method("usage.bars", params=ProfileParams, result=UsageModel, + doc="Two-bar dollar usage view shared by /usage, /topup and /subscription; fail-open to unavailable.") + + +# ── billing.state ───────────────────────────────────────────────────────────────────────────── + + +class BillingCardInfo(Result): + brand: str + last4: str + masked: str + display: str | None = None + resolved_via: str | None = None + + +class PaymentMethodKind(WireEnum): + card = "card" + link = "link" + unknown = "unknown" + + +class BillingPaymentMethod(Result): + """``_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``).""" + + kind: PaymentMethodKind + brand: str | None = None + last4: str | None = None + wallet: str | None = None + email: str | None = None + raw_kind: str | None = None + resolved_via: str | None = None + + +class BillingMonthlyCap(Result): + limit_usd: str | None = None + limit_display: str + spent_this_month_usd: str | None = None + spent_display: str + is_default_ceiling: bool + + +class AutoReloadCardKind(WireEnum): + canonical = "canonical" + distinct = "distinct" + none = "none" + + +class BillingAutoReloadCard(Result): + """Only ``distinct`` carries the payment-method identity.""" + + kind: AutoReloadCardKind + payment_method_id: str | None = None + brand: str | None = None + last4: str | None = None + + +class BillingAutoReload(Result): + enabled: bool + threshold_usd: str | None = None + threshold_display: str + reload_to_usd: str | None = None + reload_to_display: str + card: BillingAutoReloadCard | None = None + + +class BillingStateResult(Result): + """``_serialize_billing_state`` (money as strings); the ``except`` fallback emits only + ``ok / logged_in / free_tier / error``, so everything else is optional.""" + + ok: bool + logged_in: bool + free_tier: bool = False + free_tier_model: str | None = None + org_name: str | None = None + org_slug: str | None = None + role: str | None = None + is_admin: bool | None = None + can_change_plan: bool | None = None + can_charge: bool | None = None + balance_usd: str | None = None + balance_display: str | None = None + cli_billing_enabled: bool | None = None + charge_presets: list[str] | None = None + charge_presets_display: list[str] | None = None + min_usd: str | None = None + max_usd: str | None = None + card: BillingCardInfo | None = None + payment_method: BillingPaymentMethod | None = None + monthly_cap: BillingMonthlyCap | None = None + auto_reload: BillingAutoReload | None = None + portal_url: str | None = None + error: str | None = None + usage: UsageModel | None = None + + +method("billing.state", params=ProfileParams, result=BillingStateResult, + doc="Read-only billing view (no scope); the Nous free tier is answered locally without a portal call.") + + +# ── subscription.state / preview / change / resume / upgrade ────────────────────────────────── + + +class SubscriptionContext(WireEnum): + personal = "personal" + team = "team" + + +class CurrentSubscription(Result): + tier_id: str | None = None + tier_name: str | None = None + monthly_credits: str | None = None + credits_remaining: str | None = None + cycle_ends_at: str | None = None + pending_downgrade_tier_name: str | None = None + pending_downgrade_at: str | None = None + pending_downgrade_display: str | None = None + cancel_at_period_end: bool + cancellation_effective_at: str | None = None + cancellation_effective_display: str | None = None + + +class SubscriptionTierOption(Result): + tier_id: str + name: str + tier_order: int + dollars_per_month_display: str + monthly_credits: str | None = None + is_current: bool + is_enabled: bool + + +class SubscriptionStateResult(Result): + """``_serialize_subscription_state``; the view's fallback emits only ``ok / logged_in / error``.""" + + ok: bool + logged_in: bool + is_admin: bool | None = None + can_change_plan: bool | None = None + org_name: str | None = None + org_id: str | None = None + role: str | None = None + context: SubscriptionContext | None = None + current: CurrentSubscription | None = None + tiers: list[SubscriptionTierOption] | None = None + portal_url: str | None = None + error: str | None = None + usage: UsageModel | None = None + + +method("subscription.state", params=ProfileParams, result=SubscriptionStateResult, + doc="Current plan, tier catalog and usage for the picker; fail-open when logged out.") + + +class SubscriptionPreviewParams(ProfileParams): + subscription_type_id: str | None = None + + +class SubscriptionChangeEffect(WireEnum): + charge_now = "charge_now" + scheduled = "scheduled" + no_op = "no_op" + blocked = "blocked" + + +class SubscriptionPreviewResult(BillingEnvelope): + """``_serialize_subscription_preview`` on success; ``effect`` drives the confirm copy.""" + + effect: SubscriptionChangeEffect | None = None + reason: str | None = None + current_tier_id: str | None = None + current_tier_name: str | None = None + target_tier_id: str | None = None + target_tier_name: str | None = None + monthly_credits_delta: str | None = None + amount_due_now_cents: int | None = None + effective_at: str | None = None + + +method("subscription.preview", params=SubscriptionPreviewParams, result=SubscriptionPreviewResult, + doc="Chargeless quote of what a plan change would do (billing:manage).") + + +class SubscriptionChangeParams(ProfileParams): + """Either a target tier (downgrade / same-price change) or ``cancel`` (period-end cancellation).""" + + subscription_type_id: str | None = None + cancel: bool = False + + +class BillingPendingChangeResult(BillingEnvelope): + """``_billing_pending_change``: ``message`` + the raw NAS body in ``payload`` on success.""" + + +method("subscription.change", params=SubscriptionChangeParams, result=BillingPendingChangeResult, + doc="Schedule a downgrade / same-price change or a period-end cancellation.") +method("subscription.resume", params=ProfileParams, result=BillingPendingChangeResult, + doc="Clear a scheduled downgrade / cancellation (re-enables recurring spend).") + + +class SubscriptionUpgradeParams(ProfileParams): + subscription_type_id: str | None = None + idempotency_key: str | None = None + + +class SubscriptionUpgradeResult(BillingEnvelope): + """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.""" + + status: str | None = None + target_tier_name: str | None = None + recovery_url: str | None = None + reason: str | None = None + idempotency_key: str | None = None + + +method("subscription.upgrade", params=SubscriptionUpgradeParams, result=SubscriptionUpgradeResult, + doc="Prorate, charge and flip the plan (billing:manage, idempotent).") + + +# ── billing.charge / charge_status / auto_reload / step_up ─────────────────────────────────── + + +class BillingChargeParams(ProfileParams): + amount_usd: float | str | None = None + idempotency_key: str | None = None + + +class BillingChargeResult(BillingEnvelope): + """``202 {chargeId}`` — money is not confirmed yet; poll ``billing.charge_status``.""" + + charge_id: str | None = None + idempotency_key: str | None = None + + +method("billing.charge", params=BillingChargeParams, result=BillingChargeResult, + doc="Start a one-off top-up charge (billing:manage, idempotent).") + + +class BillingChargeStatusParams(ProfileParams): + charge_id: str | None = None + + +class BillingChargeStatusResult(BillingEnvelope): + """Single status read (pending | settled | failed); the caller drives the poll cadence.""" + + status: str | None = None + amount_usd: str | float | None = None + settled_at: str | None = None + reason: str | None = None + + +method("billing.charge_status", params=BillingChargeStatusParams, result=BillingChargeStatusResult, + doc="Poll one charge by id.") + + +class BillingAutoReloadParams(ProfileParams): + enabled: bool = False + threshold: float | str | None = None + top_up_amount: float | str | None = None + + +class BillingMutationResult(BillingEnvelope): + """A write with no success payload beyond ``ok``.""" + + +method("billing.auto_reload", params=BillingAutoReloadParams, result=BillingMutationResult, + doc="Enable/disable auto top-up with its threshold and reload amount (billing:manage).") + + +class BillingStepUpParams(ProfileParams): + session_id: str | None = None + + +class BillingStepUpResult(BillingEnvelope): + """``granted`` false when the server downscopes (also on every error envelope).""" + + granted: bool | None = None + + +method("billing.step_up", params=BillingStepUpParams, result=BillingStepUpResult, + doc="Run the billing:manage device flow; the URL/code arrive via billing.step_up.verification.") + + +# ── delegation / subagent.steer ─────────────────────────────────────────────────────────────── + + +class ActiveSubagent(OpenModel): + """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).""" + + subagent_id: str + parent_id: str | None = None + depth: int | None = None + goal: str | None = None + delegation_id: str | None = None + model: str | None = None + started_at: float | None = None + status: str | None = None + tool_count: int | None = None + owner_agent_session_id: str | None = None + + +class DelegationStatusResult(Result): + active: list[ActiveSubagent] + paused: bool + max_spawn_depth: int + max_concurrent_children: int + + +method("delegation.status", params=ProfileParams, result=DelegationStatusResult, + doc="Running subagent tree plus the spawn pause flag and limits.") + + +class DelegationPauseParams(ProfileParams): + paused: bool = True + + +class DelegationPauseResult(Result): + paused: bool + + +method("delegation.pause", params=DelegationPauseParams, result=DelegationPauseResult, + doc="Block/unblock NEW spawns globally (active children keep running); returns the new state.") + + +class SubagentSteerParams(SessionParams): + subagent_id: str + text: str + + +class SteerStatus(WireEnum): + queued = "queued" + rejected = "rejected" + + +class SubagentSteerResult(Result): + """``queued`` is not ``delivered``: a child past its final tool batch surfaces ``missed_steer``.""" + + status: SteerStatus + subagent_id: str + text: str + + +method("subagent.steer", params=SubagentSteerParams, result=SubagentSteerResult, + doc="Queue steering text into a live delegated child owned by this session.") + + +# ── handoff ─────────────────────────────────────────────────────────────────────────────────── + + +class HandoffRequestParams(SessionParams): + platform: str + + +class HandoffRequestResult(Result): + queued: bool + session_key: str + platform: str + home_name: str + + +method("handoff.request", params=HandoffRequestParams, result=HandoffRequestResult, + doc="Queue a handoff to a messaging platform's home channel; the gateway watcher claims it.") + + +class HandoffStateResult(Result): + """``state`` is pending | running | completed | failed, or '' when nothing was requested.""" + + state: str + platform: str + error: str + + +method("handoff.state", params=SessionParams, result=HandoffStateResult, + doc="Poll the handoff row for this session.") + + +class HandoffFailParams(SessionParams): + error: str | None = None + + +class HandoffFailResult(Result): + """``failed`` false when the watcher already claimed the row; ``state`` is what it is now.""" + + failed: bool + state: str + + +method("handoff.fail", params=HandoffFailParams, result=HandoffFailResult, + doc="Fail a not-yet-claimed handoff (client poll timeout); CAS against the watcher.") + + +# ── message.react ───────────────────────────────────────────────────────────────────────────── + + +class ReactionAuthor(WireEnum): + user = "user" + agent = "agent" + + +class MessageReactParams(SessionParams): + """``row_id`` is ``messages.id``; a not-yet-persisted live message names ``newest_role`` instead. + ``emoji`` null clears; the same emoji again retracts.""" + + row_id: int | None = None + newest_role: str | None = None + emoji: str | None = None + author: ReactionAuthor | None = None + + +class MessageReaction(OpenModel): + """One persisted reaction (``hermes_state_messages.py``); ``seen`` is stamped once announced.""" + + emoji: str + author: str + at: float | None = None + seen: bool | None = None + + +class MessageReactResult(Result): + row_id: int + reactions: list[MessageReaction] + + +method("message.react", params=MessageReactParams, result=MessageReactResult, + doc="Set/clear one author's emoji reaction on a message; returns the row's full reaction list.") + + +# ── pets: generate / hatch / cancel / status ────────────────────────────────────────────────── + + +class PetCancelParams(ProfileParams): + token: str | None = None + + +class PetCancelResult(Result): + ok: bool + + +method("pet.cancel", params=PetCancelParams, result=PetCancelResult, + doc="Stop an in-flight pet generate/hatch by token (idempotent).") + + +class PetGenProvider(Result): + """``agent/pet/generate/imagegen.py::list_sprite_providers`` row.""" + + name: str + label: str + default: bool + + +class PetGenerateStatusResult(Result): + available: bool + providers: list[PetGenProvider] + + +method("pet.generate.status", params=ProfileParams, result=PetGenerateStatusResult, + doc="Whether pet generation is possible (a reference-capable image backend) and which providers.") + + +class PetGenerateParams(ProfileParams): + """``prompt`` or a ``referenceImage`` data URL is required (the handler answers 4004 without one).""" + + prompt: str | None = None + referenceImage: str | None = None # noqa: N815 - wire key + count: int | None = None + style: str | None = None + provider: str | None = None + + +class PetDraft(Result): + index: int + dataUri: str # noqa: N815 - wire key + + +class PetGenerateResult(Result): + ok: bool + token: str + drafts: list[PetDraft] + + +method("pet.generate", params=PetGenerateParams, result=PetGenerateResult, + doc="Candidate base looks for a new pet (draft step); drafts also stream via pet.generate.progress.") + + +class PetHatchParams(ProfileParams): + token: str + name: str + cancelToken: str | None = None # noqa: N815 - wire key + index: int | None = None + description: str | None = None + prompt: str | None = None + style: str | None = None + provider: str | None = None + + +# TODO(common): ``tui_gateway/server.py::_pet_sprite_payload`` is one shape for ``pet.info`` and +# ``pet.hatch``; consolidate with the pets contract module. Every field optional: ``pet.hatch`` +# emits ``{}`` when the installed pet cannot be reloaded. +class PetSpritePayload(Result): + slug: str | None = None + displayName: str | None = None # noqa: N815 - wire key + mime: str | None = None + spritesheetBase64: str | None = None # noqa: N815 - wire key + spritesheetRevision: str | None = None # noqa: N815 - wire key + frameW: int | None = None # noqa: N815 - wire key + frameH: int | None = None # noqa: N815 - wire key + framesPerState: int | None = None # noqa: N815 - wire key + framesByState: dict[str, int] | None = None # noqa: N815 - wire key + framesByRow: dict[str, int] | None = None # noqa: N815 - wire key + loopMs: int | None = None # noqa: N815 - wire key + scale: float | None = None + stateRows: list[str] | None = None # noqa: N815 - wire key + + +class PetHatchResult(Result): + """The hatched pet is installed but NOT active (``pet.select`` adopts, ``pet.remove`` discards).""" + + ok: bool + slug: str + displayName: str # noqa: N815 - wire key + warnings: list[JsonValue] = Field(default_factory=list) + pet: PetSpritePayload + + +method("pet.hatch", params=PetHatchParams, result=PetHatchResult, + doc="Turn a base draft into a full spritesheet pet; progress streams via pet.hatch.progress.") + + +# ── project.facts ───────────────────────────────────────────────────────────────────────────── + + +class ProjectFactsParams(ProfileParams): + cwd: str | None = None + + +class ProjectFacts(Result): + """``agent/coding_context.py::project_facts_for`` — the system prompt's coding-context detection.""" + + root: str + manifests: list[str] + packageManagers: list[str] # noqa: N815 - wire key + verifyCommands: list[str] # noqa: N815 - wire key + contextFiles: list[str] # noqa: N815 - wire key + + +class ProjectFactsResult(Result): + """``facts`` null outside a workspace (or when detection failed).""" + + facts: ProjectFacts | None = None + + +method("project.facts", params=ProjectFactsParams, result=ProjectFactsResult, + doc="Structured project facts for a cwd so UIs don't re-sniff the workspace.") diff --git a/tui_gateway/contracts/config_free_tier_control.py b/tui_gateway/contracts/config_free_tier_control.py index eb497440bc..11065fecd4 100644 --- a/tui_gateway/contracts/config_free_tier_control.py +++ b/tui_gateway/contracts/config_free_tier_control.py @@ -1 +1,558 @@ -"""Contracts: config_free_tier_control (authored by the contract worker).""" +"""Contracts: config, setup readiness, free tier, model inventory, connectors, diagnostics, +image generation and structured session control. + +Handlers: ``tui_gateway/methods_config.py`` (``config.get``, ``setup.*``, ``diagnostics.share_nous``), +``methods_config_set.py`` (``config.set``), ``methods_free_tier.py``, ``methods_complete.py`` +(``model.options``), ``methods_connectors.py``, ``methods_images.py``, ``methods_session_control.py`` +and ``methods_session.py`` (``verification.status``). +""" + +from __future__ import annotations + +from typing import Literal + +from pydantic import Field + +from .base import JsonValue, Params, Result, WireEnum +from .common import OpenModel, ProfileParams, SessionLiveInfo +from .registry import method + +# ── config.get ──────────────────────────────────────────────────────────────────────────────── + + +class ConfigGetParams(ProfileParams): + """``key`` selects one getter from ``_CONFIG_GETTERS``; ``cwd`` feeds the ``project`` getter, + ``session_id`` lets ``reasoning`` / ``fast`` answer with the session's live pin.""" + + key: str + cwd: str | None = None + session_id: str | None = None + + +class ConfigProviderRef(OpenModel): + """``hermes_cli/models.py::list_available_providers`` row.""" + + id: str + label: str + aliases: list[str] = Field(default_factory=list) + authenticated: bool = False + + +class ConfigGetResult(Result): + """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``.""" + + value: str | None = None + display: str | None = None + tool_progress: str | None = None + model: str | None = None + provider: str | None = None + providers: list[ConfigProviderRef] | None = None + home: str | None = None + cwd: str | None = None + branch: str | None = None + config: dict[str, JsonValue] | None = None + prompt: str | None = None + mtime: float | None = None + mcp_rev: str | None = None + + +method("config.get", params=ConfigGetParams, result=ConfigGetResult, + doc="Read one normalised config value (or the whole effective config) the way the UIs render it.") + + +# ── config.set ──────────────────────────────────────────────────────────────────────────────── + + +class ConfigSetScope(WireEnum): + session = "session" + global_ = "global" + once = "once" + + +class ConfigSetParams(ProfileParams): + """``key`` picks the setter (``_CONFIG_SETTERS``, ``details_mode.
``, display toggles); + ``value`` is the raw word/string the setter normalises (falsy non-strings are reported back in + the error). ``scope`` applies to ``yolo`` / ``reasoning``; ``confirm_expensive_model`` to ``model``.""" + + key: str + value: JsonValue = "" + session_id: str | None = None + scope: str | None = None + confirm_expensive_model: bool = False + + +class ConfigSetResult(Result): + """``{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.""" + + key: str + value: str | bool | None = None + warning: str | None = None + confirm_required: bool | None = None + confirm_message: str | None = None + scope: str | None = None + deferred: bool | None = None + tool_progress: str | None = None + cwd: str | None = None + branch: str | None = None + history_reset: bool | None = None + info: SessionLiveInfo | None = None + + +method("config.set", params=ConfigSetParams, result=ConfigSetResult, + doc="Change one config key (persisted or session-scoped) and read back the normalised value.") + + +# ── setup readiness ─────────────────────────────────────────────────────────────────────────── + + +class SetupStatusResult(Result): + """``provider_configured`` is the loose answer; the boot record's fields (``ready``, + ``free_tier``, ``other_providers``, ``inference_provider``) ride along on the launch profile. + An unknown ``profile`` answers ``ok=False`` + ``error``.""" + + provider_configured: bool | None = None + ready: bool | None = None + free_tier: bool | None = None + other_providers: bool | None = None + inference_provider: str | None = None + profile: str | None = None + ok: bool | None = None + error: str | None = None + + +method("setup.status", params=ProfileParams, result=SetupStatusResult, + doc="Loose provider check: is ANY provider auth state discoverable for the (launch or named) profile.") + + +class SetupRuntimeCheckParams(ProfileParams): + provider: str | None = None + + +class SetupRuntimeCheckResult(Result): + """``ok=False`` + ``error`` when the resolved model can't be served; ``free_tier`` says the + selected route is the welcome host.""" + + ok: bool + provider: str | None = None + model: str | None = None + source: str | None = None + error: str | None = None + free_tier: bool | None = None + profile: str | None = None + + +method("setup.runtime_check", params=SetupRuntimeCheckParams, result=SetupRuntimeCheckResult, + doc="Strict provider check through the same runtime resolution the agent uses on session creation.") + + +# ── diagnostics.share_nous ──────────────────────────────────────────────────────────────────── + + +class DiagnosticsShareNousParams(Params): + error_context: str | None = None + extra_files: dict[str, str] | None = None + log_lines: int | None = None + + +class DiagnosticsShareNousResult(Result): + """Structured envelope: ``ok=False`` + ``error`` renders inline instead of failing the RPC.""" + + ok: bool + view_url: str | None = None + upload_id: str | None = None + expires_at: str | None = None + error: str | None = None + + +method("diagnostics.share_nous", params=DiagnosticsShareNousParams, result=DiagnosticsShareNousResult, + doc="Upload a force-redacted debug bundle to Nous-internal diagnostics storage.") + + +# ── free tier ───────────────────────────────────────────────────────────────────────────────── + + +class FreeTierStatusResult(Result): + """``available`` = an identity exists AND the tier is on; whether inference runs on it is + ``setup.runtime_check.free_tier``'s question.""" + + has_guest: bool + enabled: bool + available: bool + notice_pending: bool + model: str + label: str + + +method("free_tier.status", params=ProfileParams, result=FreeTierStatusResult, + doc="Pure read of the focused profile's free-tier identity state (no network, no side effects).") + + +class FreeTierProvisionResult(Result): + has_guest: bool + enabled: bool + error: str | None = None + + +method("free_tier.provision", params=ProfileParams, result=FreeTierProvisionResult, + doc="Explicit retry of the free-tier identity mint when the boot bootstrap could not create it.") + + +class FreeTierAckNoticeResult(Result): + acked: bool + + +method("free_tier.ack_notice", params=ProfileParams, result=FreeTierAckNoticeResult, + doc="Mark the one-time availability notice as shown on the free-tier identity.") + + +# ── model.options ───────────────────────────────────────────────────────────────────────────── + + +class ModelOptionsParams(ProfileParams): + session_id: str | None = None + explicit_only: bool = False + include_unconfigured: bool = False + refresh: bool = False + + +# TODO(common): ModelPricing / ModelCapabilities / ModelOptionProvider are also the row shape of +# ``model.save_key``'s ``provider`` — the parent consolidates into contracts/common.py. +class ModelPricing(Result): + """``hermes_cli/inventory.py::_apply_pricing`` — formatted $/Mtok strings (``""`` unknown, + ``"free"``); the sale fields are Nous Portal-only.""" + + input: str + output: str + cache: str | None = None + free: bool + discount_percent: int | None = None + was_input: str | None = None + was_output: str | None = None + + +class ModelCapabilities(Result): + """``hermes_cli/inventory.py::_apply_capabilities``.""" + + fast: bool + reasoning: bool + can_disable_reasoning: bool | None = None + + +class ModelOptionProvider(OpenModel): + """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).""" + + slug: str + name: str + models: list[str] = Field(default_factory=list) + total_models: int | None = None + is_current: bool | None = None + is_user_defined: bool | None = None + source: str | None = None + aliases: list[str] | None = None + api_url: str | None = None + auth_type: str | None = None + authenticated: bool | None = None + key_env: str | None = None + warning: str | None = None + featured_models: list[str] | None = None + capabilities: dict[str, ModelCapabilities] | None = None + pricing: dict[str, ModelPricing] | None = None + pricing_pending: bool | None = None + free_tier: bool | None = None + free_tier_pending: bool | None = None + free_tier_row: bool | None = None + unavailable_models: list[str] | None = None + + +class ModelOptionsResult(Result): + providers: list[ModelOptionProvider] + model: str = "" + provider: str = "" + + +method("model.options", params=ModelOptionsParams, result=ModelOptionsResult, + doc="Provider/model inventory for the picker, layered over the session's live provider when given.") + + +# ── connectors ──────────────────────────────────────────────────────────────────────────────── + + +class ConnectorsListParams(ProfileParams): + session_id: str + + +class ConnectorRow(OpenModel): + """One ``manage_connections`` status entry after ``connector_ui_payload`` redaction; the + connector service owns the closed key set, so unknown metadata passes through.""" + + connector: str = "" + connected: bool | None = None + enabled: bool | None = None + connectionStatus: str | None = None + name: str | None = None + description: str | None = None + + +class ConnectorsListResult(Result): + available: bool + connectors: list[ConnectorRow] + + +method("connectors.list", params=ConnectorsListParams, result=ConnectorsListResult, + doc="Connector catalog + connection state for one owned session (``available=False`` when the toolset is off).") + + +class ConnectorsConnectParams(ProfileParams): + session_id: str + connectors: list[str] + reconnect: bool = False + + +class ConnectorConnectEntry(OpenModel): + """``tools/connections_tool.py`` per-connector authorization outcome.""" + + connector: str = "" + status: str | None = None + connect_url: str | None = None + note: str | None = None + instruction: str | None = None + + +class ConnectorsConnectResult(Result): + results: list[ConnectorConnectEntry] + summary: dict[str, JsonValue] + + +method("connectors.connect", params=ConnectorsConnectParams, result=ConnectorsConnectResult, + doc="Start (or re-initiate) authorization for named connectors; returns per-connector links/status.") + + +# ── image.generate ──────────────────────────────────────────────────────────────────────────── + + +class ImageGenerateParams(Params): + prompt: str | None = None + aspect_ratio: str | None = None + probe: JsonValue | None = None # truthy word/flag: availability check only + max_bytes: int | None = None + + +class ImageGenerateResult(Result): + """``probe`` answers ``{available}`` alone; ``image_data`` (data URL) is omitted when the + download failed or exceeded ``max_bytes`` so callers fall back to ``image``.""" + + available: bool + success: bool | None = None + image: str | None = None + image_data: str | None = None + error: str | None = None + + +method("image.generate", params=ImageGenerateParams, result=ImageGenerateResult, + doc="Generate an image through the tool's provider dispatcher and hand the renderer a data URL.") + + +# ── session.control ─────────────────────────────────────────────────────────────────────────── + + +class GoalContractSnapshot(Result): + """``hermes_cli/goals.py::GoalContract.to_dict``.""" + + outcome: str = "" + verification: str = "" + constraints: str = "" + boundaries: str = "" + stop_when: str = "" + + +class GoalGateSnapshot(Result): + command: str + timeout_seconds: int + max_retries: int + attempts: int + last_exit_code: int | None = None + + +class WaitBarrierUntil(Result): + type: Literal["until"] + until_at: float + reason: str = "" + + +class WaitBarrierTarget(Result): + type: Literal["session", "pid"] + target: str | int + reason: str = "" + + +class GoalSnapshot(Result): + """``methods_session_control.py::_safe_goal_snapshot`` — the frontend-safe GoalState subset.""" + + title: str + status: str + turns_used: int + max_turns: int + contract: GoalContractSnapshot + subgoals: list[str] + gates: list[GoalGateSnapshot] + created_at: float | None = None + updated_at: float | None = None + paused_reason: str | None = None + last_verdict: str | None = None + last_reason: str | None = None + wait_barrier: WaitBarrierUntil | WaitBarrierTarget | None = Field(default=None, discriminator="type") + + +class LoopSnapshot(Result): + """``_safe_loop_snapshot`` — persisted LoopState fields, never its route.""" + + prompt: str + status: str + mode: str + interval_seconds: float + current_delay: float + times: int + until: str + max_ticks: int + ticks_fired: int + created_at: float + last_fired_at: float + next_due_at: float + awaiting_response: bool + deferred_by_goal: bool + paused_reason: str | None = None + last_stop_reason: str | None = None + + +class HeartbeatSnapshot(Result): + prompt: str + status: str + interval_seconds: int + created_at: float + last_fired_at: float + fire_count: int + + +class SessionControlSnapshot(Result): + """``_snapshot_control`` — ``revision`` is a hash of the visible state (``""`` when empty); + ``updated_at`` is the newest persisted timestamp (``0`` when none).""" + + goal: GoalSnapshot | None + loop: LoopSnapshot | None + heartbeat: HeartbeatSnapshot | None + revision: str + updated_at: float + + +class SessionControlReadParams(ProfileParams): + session_id: str + + +class SessionControlReadResult(Result): + control: SessionControlSnapshot + + +method("session.control.read", params=SessionControlReadParams, result=SessionControlReadResult, + doc="Stable, allowlisted snapshot of one live session's goal / loop / heartbeat state.") + + +class SessionControlAction(WireEnum): + goal_pause = "goal.pause" + goal_resume = "goal.resume" + goal_clear = "goal.clear" + goal_unwait = "goal.unwait" + loop_pause = "loop.pause" + loop_resume = "loop.resume" + loop_stop = "loop.stop" + subgoal_add = "subgoal.add" + subgoal_remove = "subgoal.remove" + subgoal_clear = "subgoal.clear" + heartbeat_pause = "heartbeat.pause" + heartbeat_resume = "heartbeat.resume" + heartbeat_clear = "heartbeat.clear" + + +class SessionControlArgs(Params): + """``subgoal.add`` reads ``text``; ``subgoal.remove`` reads the 1-based ``index``.""" + + text: str | None = None + index: int | None = None + + +class SessionControlParams(ProfileParams): + """``action`` is validated by the handler (unknown / gate actions answer ``4004``), so it stays a + string on the wire; ``SessionControlAction`` lists the accepted set.""" + + session_id: str + action: str + args: SessionControlArgs | None = None + + +class SessionControlDispatch(Result): + """``_dispatch_envelope`` — the command result's user-visible envelope, every key always present.""" + + type: str | None + output: str | None + notice: str | None + message: str | None + display: str | None + + +class SessionControlResult(Result): + control: SessionControlSnapshot + dispatch: SessionControlDispatch + + +method("session.control", params=SessionControlParams, result=SessionControlResult, + doc="Run one allowlisted goal / loop / subgoal / heartbeat action and return the exact resulting snapshot.") + + +# ── verification.status ─────────────────────────────────────────────────────────────────────── + + +class VerificationStatusParams(ProfileParams): + session_id: str | None = None + session_key: str | None = None + cwd: str | None = None + + +class VerificationEvidenceRow(OpenModel): + """One ``verification_events`` row (``agent/verification_evidence.py``).""" + + id: int | None = None + created_at: str | None = None + session_id: str | None = None + cwd: str | None = None + root: str | None = None + command: str | None = None + canonical_command: str | None = None + kind: str | None = None + scope: str | None = None + status: str | None = None + exit_code: int | None = None + output_summary: str | None = None + + +class VerificationStatusInfo(Result): + """``verification_status()``: ``disabled`` / ``not_applicable`` / ``unverified`` / ``stale`` or the + latest event's own status; ``root`` and friends only once a workspace was identified.""" + + status: str + evidence: VerificationEvidenceRow | None = None + root: str | None = None + session_id: str | None = None + changed_paths: list[str] | None = None + + +class VerificationStatusResult(Result): + verification: VerificationStatusInfo + + +method("verification.status", params=VerificationStatusParams, result=VerificationStatusResult, + doc="Best known verification evidence for a cwd/session; read-only, never runs checks.") diff --git a/tui_gateway/contracts/events.py b/tui_gateway/contracts/events.py index a353747407..fe94620349 100644 --- a/tui_gateway/contracts/events.py +++ b/tui_gateway/contracts/events.py @@ -1 +1,724 @@ -"""Contracts: events (authored by the contract worker).""" +"""Notification payloads: every ``event`` frame the gateway emits (``params.payload``). + +One ``Payload`` model per event name, registered with ``event(...)``; ``request.cancel`` lives in +``server_requests.py`` next to the requests it withdraws. Each model's docstring names the Python +emitter it was typed from — that emitter is the source of truth, the hand-written TS in +``apps/shared/src/gateway-events.ts`` was only the map. Fields the emitter always sets are required; +anything conditional is ``X | None = None``. + +A handful of payloads stay ``extra="allow"`` on purpose: their closed shape is owned by another +module (the skin engine, the pet store, the goal/loop/heartbeat state files, the free-tier bootstrap +record) or they are watcher signals whose payload is ``{}`` today and may grow. Everything else is +closed, so a drifted emitter fails the suite (``registry.check_payload`` raises under +``HERMES_TEST_ISOLATION``). +""" + +from __future__ import annotations + +from pydantic import Field + +from .base import JsonValue, Payload, WireEnum +from .common import SessionLiveInfo, SubagentStatus, Usage +from .registry import event + + +class OpenPayload(Payload): + """A payload whose known keys are typed but whose closed set is owned elsewhere.""" + + model_config = Payload.model_config | {"extra": "allow"} + + +# ── gateway lifecycle ───────────────────────────────────────────────────────────────────────── + + +class SkinPayload(OpenPayload): + """``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.""" + + name: str | None = None + colors: dict[str, str] | None = None + light_colors: dict[str, str] | None = None + dark_colors: dict[str, str] | None = None + branding: dict[str, str] | None = None + banner_logo: str | None = None + banner_hero: str | None = None + tool_prefix: str | None = None + help_header: str | None = None + + +class GatewayReadyPayload(Payload): + """``tui_gateway/entry.py`` (stdio) / ``tui_gateway/ws.py`` (WebSocket) first frame.""" + + skin: SkinPayload + change_events: bool + replay_epoch: str + heartbeat: bool | None = None # WebSocket transport only + + +event("gateway.ready", GatewayReadyPayload, + doc="First frame of a connection: the resolved skin, the change-event capability and the replay epoch.") +event("skin.changed", SkinPayload, + doc="The active skin moved (name switch or live colour edit); repaint from this palette.") + + +class SetupReadyPayload(OpenPayload): + """``hermes_cli/free_tier_bootstrap.py::SetupRecord.as_payload``.""" + + provider_configured: bool + inference_provider: str + free_tier: bool + has_identity: bool + other_providers: bool + error: str = "" + finished_at: float + + +event("setup.ready", SetupReadyPayload, + doc="The free-tier bootstrap finished (broadcast); the desktop's setup gate reads the record.") + + +class ErrorPayload(Payload): + """Every ``_emit("error", …)`` site sets exactly ``message``.""" + + message: str + + +event("error", ErrorPayload, doc="A session-level failure outside a turn (agent init, model switch, compression, resume).") + + +class NoticePayload(Payload): + """``tui_gateway/model_switch.py`` capability-refresh notice.""" + + message: str + + +event("notice", NoticePayload, doc="Informational one-liner for the session (capabilities refreshed).") + + +# ── turn stream ─────────────────────────────────────────────────────────────────────────────── + + +event("message.start", None, doc="A turn began streaming; no payload.") + + +class StreamDeltaPayload(Payload): + """``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.""" + + text: str + rendered: str | None = None + verbose: bool | None = None + + +event("message.delta", StreamDeltaPayload, doc="One streamed chunk of the assistant reply.") +event("reasoning.delta", StreamDeltaPayload, doc="One streamed chunk of the model's reasoning.") +event("reasoning.available", StreamDeltaPayload, doc="A completed reasoning block (non-streaming providers).") +event("thinking.delta", StreamDeltaPayload, doc="Legacy thinking-text chunk (thinking_callback).") + + +class MessageInterimPayload(Payload): + """``prompt_turn._interim_assistant_cb`` / ``agent_callbacks`` interim_assistant_callback.""" + + text: str + already_streamed: bool + + +event("message.interim", MessageInterimPayload, + doc="Interim assistant commentary (text beside tool calls) sealed as its own segment.") + + +class TurnStatus(WireEnum): + """``prompt_turn._result_status``.""" + + complete = "complete" + error = "error" + interrupted = "interrupted" + + +class ErrorSurface(Payload): + """``agent/error_surface.py::_surface`` — advisory {layer, code, retryable} (+ identity, + auth hint).""" + + layer: str + code: str + retryable: bool + provider: str | None = None + model: str | None = None + model_config = Payload.model_config | {"extra": "allow"} + + +class BillingBlock(Payload): + """``agent/billing_links.py::BillingBlock.to_dict`` (+ ``unverified`` from conversation_loop).""" + + provider: str + provider_label: str + model: str + billing_url: str | None = None + is_nous: bool + message: str + unverified: bool | None = None + + +class MessageCompletePayload(Payload): + """``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``).""" + + text: str | JsonValue = "" + usage: Usage | None = None + status: TurnStatus | None = None + reasoning: str | None = None + warning: str | None = None + response_previewed: bool | None = None + billing: BillingBlock | None = None + failure_reason: str | None = None + rendered: str | None = None + error: str | None = None + recoverable: bool | None = None + error_surface: ErrorSurface | None = None + partial: bool | None = None + + +event("message.complete", MessageCompletePayload, doc="The turn ended: final text, usage and outcome.") + + +class StatusUpdatePayload(Payload): + """``server._status_update`` and the direct emitters (goal / loop / heartbeat / process).""" + + kind: str + text: str + + +event("status.update", StatusUpdatePayload, doc="Transient status line (kind: status, lifecycle, compacting, goal, loop, heartbeat, process, …).") + + +class SessionUsagePayload(Payload): + """``server._start_usage_ticker``.""" + + usage: Usage + + +event("session.usage", SessionUsagePayload, doc="Mid-turn usage tick; message.complete carries the authoritative final usage.") + + +class SessionTitlePayload(Payload): + """``prompt_turn._invoke_agent`` ``_on_session_title`` hook.""" + + session_id: str + title: str + + +event("session.title", SessionTitlePayload, doc="Auto-titling renamed the session (``session_id`` is the stored key).") + + +class ReactionPayload(Payload): + """``agent_callbacks`` reaction_callback.""" + + kind: str + + +event("reaction", ReactionPayload, doc="Affection reaction detected in the user's message (hearts etc.).") + + +class ReviewSummaryPayload(Payload): + """``server`` background_review_callback.""" + + text: str + + +event("review.summary", ReviewSummaryPayload, doc="Background review of the last turn finished.") + + +# ── tools ───────────────────────────────────────────────────────────────────────────────────── + + +class ToolStartPayload(Payload): + """``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.""" + + tool_id: str + name: str + context: str | None = None + args: dict[str, JsonValue] | None = None + args_text: str | None = None + preview: str | None = None + + +event("tool.start", ToolStartPayload, doc="A tool call began (stable id + full args).") + + +class ToolCompletePayload(Payload): + """``tool_progress._on_tool_complete``; ``todos``/``revision`` merged in for the todo tools.""" + + tool_id: str + name: str + args: dict[str, JsonValue] + duration_s: float | None = None + result: JsonValue = None + summary: str | None = None + result_text: str | None = None + inline_diff: str | None = None + todos: list[JsonValue] | None = None + revision: int | None = None + + +event("tool.complete", ToolCompletePayload, doc="A tool call finished: parsed result, summary, optional diff / todo snapshot.") + + +class ToolGeneratingPayload(Payload): + """``agent_callbacks`` tool_gen_callback.""" + + name: str + + +event("tool.generating", ToolGeneratingPayload, doc="The model is emitting a tool call's arguments.") + + +class ToolOutputRiskPayload(Payload): + """``tool_progress._progress_output_risk``.""" + + tool_id: str + name: str + risk: str + findings: list[str] + redacted: bool + + +event("tool.output_risk", ToolOutputRiskPayload, doc="Tool output was classified as risky (prompt-injection / secret findings).") + + +class TodoUpdatedPayload(Payload): + """``tool_progress._normalize_todo_state`` — full task snapshot.""" + + todos: list[JsonValue] + revision: int + + +event("todo.updated", TodoUpdatedPayload, doc="Full todo snapshot after a todo tool ran.") + + +# ── notifications ───────────────────────────────────────────────────────────────────────────── + + +class NotificationShowPayload(Payload): + """``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.""" + + text: str + level: str + kind: str + ttl_ms: int | None = None + key: str | None = None + id: str | None = None + + +class NotificationClearPayload(Payload): + key: str + + +event("notification.show", NotificationShowPayload, doc="Show / replace a keyed out-of-band notice (toast or status bar).") +event("notification.clear", NotificationClearPayload, doc="Withdraw the notice with this key.") + + +class TipShowPayload(Payload): + """``tools/tip_tool.py``.""" + + selector: str + text: str + title: str | None = None + side: str | None = None + + +event("tip.show", TipShowPayload, doc="Point at a desktop element with a one-line tip bubble.") + + +# ── session lifecycle ───────────────────────────────────────────────────────────────────────── + + +# SessionLiveInfo is a Result (it is also the ``info`` of create/resume/activate); the registry only +# needs ``model_validate`` and the generator renders one TS type either way. +event("session.info", SessionLiveInfo, # type: ignore[arg-type] + doc="Live session settings snapshot (``server._session_info``); also the ``info`` of create/resume/activate.") + + +class ResumePhaseStatus(WireEnum): + loading = "loading" + complete = "complete" + failed = "failed" + + +class SessionResumeProgressPayload(Payload): + """``server._hydrate_resume_history``.""" + + phase: str + status: ResumePhaseStatus + message_count: int | None = None + message: str | None = None + + +event("session.resume_progress", SessionResumeProgressPayload, doc="Deferred resume hydration progress.") + + +class SessionReclaimedPayload(Payload): + """``session_lifecycle._announce_session_reclaimed`` (broadcast).""" + + session_id: str + stored_session_id: str + reason: str # idle_timeout | lru_evict | ws_orphan_reap + + +event("session.reclaimed", SessionReclaimedPayload, doc="The backend reclaimed a live session out from under its clients.") + + +class SessionControlSnapshot(OpenPayload): + """``methods_session_control._snapshot_control``; goal / loop / heartbeat sub-objects are the + allow-listed state-file projections (owned by hermes_cli.goals / loops / heartbeat).""" + + goal: dict[str, JsonValue] | None = None + loop: dict[str, JsonValue] | None = None + heartbeat: dict[str, JsonValue] | None = None + revision: str = "" + updated_at: float = 0 + + +class SessionControlUpdatePayload(Payload): + control: SessionControlSnapshot + + +event("session.control.update", SessionControlUpdatePayload, doc="Persisted goal / loop / heartbeat state changed.") + + +class BillingStepUpVerificationPayload(Payload): + """``methods_session`` billing.step_up on_verification.""" + + verification_url: str + user_code: str + + +event("billing.step_up.verification", BillingStepUpVerificationPayload, + doc="Device-flow URL + code for the billing scope step-up; the client opens the browser.") + + +# ── side agents (methods_prompt._spawn_side_agent) ──────────────────────────────────────────── + + +class SideAgentCompletePayload(Payload): + """``methods_prompt._spawn_side_agent``: ``{task_id, **extra, text}``; btw adds ``question``.""" + + task_id: str + text: str + question: str | None = None + + +event("background.complete", SideAgentCompletePayload, doc="A /background side agent finished.") +event("btw.complete", SideAgentCompletePayload, doc="A /btw side question was answered.") +event("preview.restart.complete", SideAgentCompletePayload, doc="The hidden preview-restart agent finished.") + + +class PreviewRestartProgressPayload(Payload): + """``methods_prompt`` restart body + ``agent_callbacks._preview_restart_callbacks``.""" + + task_id: str + text: str + level: str | None = None + + +event("preview.restart.progress", PreviewRestartProgressPayload, doc="Progress line from the preview-restart agent.") + + +# ── subagents (tool_progress._progress_subagent) ────────────────────────────────────────────── + + +class SubagentOutputTailEntry(Payload): + """``tools/delegate_tool_results.py::_extract_output_tail`` row.""" + + tool: str + preview: str + is_error: bool + + +class SubagentEventPayload(Payload): + """``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.""" + + goal: str + task_count: int + task_index: int + subagent_id: str | None = None + parent_id: str | None = None + child_session_id: str | None = None + delegation_id: str | None = None + depth: int | None = None + model: str | None = None + tool_count: int | None = None + toolsets: list[str] | None = None + input_tokens: int | None = None + output_tokens: int | None = None + reasoning_tokens: int | None = None + api_calls: int | None = None + files_read: list[str] | None = None + files_written: list[str] | None = None + output_tail: list[SubagentOutputTailEntry] | None = None + tool_name: str | None = None + text: str | None = None + status: SubagentStatus | None = None + summary: str | None = None + duration_seconds: float | None = None + tool_preview: str | None = None + + +for _name, _doc in ( + ("subagent.spawn_requested", "delegate_task accepted a child goal (before the child starts)."), + ("subagent.start", "A delegated child started running."), + ("subagent.progress", "Batched tool-name progress from a child."), + ("subagent.thinking", "A child's reasoning chunk."), + ("subagent.tool", "A child called a tool."), + ("subagent.complete", "A child finished (status + observability rollup)."), +): + event(_name, SubagentEventPayload, doc=_doc) + + +# ── MoA ─────────────────────────────────────────────────────────────────────────────────────── + + +class MoaReferencePayload(Payload): + """``tool_progress._progress_moa_reference``.""" + + label: str + text: str + index: int | None = None + count: int | None = None + + +class MoaAggregatingPayload(Payload): + aggregator: str + + +class MoaProgressPayload(Payload): + label: str + refs_done: int + refs_total: int + + +class MoaPhasePayload(Payload): + phase: str + refs_done: int | None = None + refs_total: int | None = None + aggregator: str | None = None + + +event("moa.reference", MoaReferencePayload, doc="One MoA reference model's output.") +event("moa.aggregating", MoaAggregatingPayload, doc="The MoA aggregator started.") +event("moa.progress", MoaProgressPayload, doc="MoA reference fan-out progress (n/total).") +event("moa.phase", MoaPhasePayload, doc="MoA phase transition (currently only ``aggregator``).") + + +# ── desktop GUI (tools/desktop_ui emitters) ────────────────────────────────────────────────── + + +class PreviewOpenPayload(Payload): + """``tools/open_preview_tool.py``.""" + + url: str + label: str = "" + + +class PreviewClosePayload(Payload): + """``tools/preview_tool.py`` / ``tools/close_preview_tool.py``; ``url`` '' closes every tab.""" + + url: str = "" + + +event("preview.open", PreviewOpenPayload, doc="Open a URL / file in the desktop preview pane.") +event("preview.close", PreviewClosePayload, doc="Close the preview pane or one tab.") + + +class LayoutApplyPayload(OpenPayload): + """``tools/apply_layout_tool.py``.""" + + preset: str + + +class PaneRevealPayload(OpenPayload): + """``tools/focus_pane_tool.py``.""" + + pane: str + + +event("layout.apply", LayoutApplyPayload, doc="Apply a named desktop layout preset.") +event("pane.reveal", PaneRevealPayload, doc="Focus / reveal a named desktop pane.") + + +class MessageReaction(Payload): + """``hermes_state_messages.set_message_reaction`` row.""" + + emoji: str + author: str + at: float | None = None + model_config = Payload.model_config | {"extra": "allow"} + + +class MessageReactionPayload(Payload): + """``tools/react_to_message_tool.py``.""" + + row_id: int + reactions: list[MessageReaction] + role: str + + +event("message.reaction", MessageReactionPayload, doc="The agent reacted to a message; paint it live.") + + +class TerminalOutputPayload(Payload): + """``session_notifications`` process_registry.on_output.""" + + process_id: str + chunk: str + + +class TerminalClosePayload(Payload): + process_id: str + + +event("agent.terminal.output", TerminalOutputPayload, doc="Output chunk from an agent-owned background process.") +event("terminal.close", TerminalClosePayload, doc="An agent-owned background process closed.") + + +class BrowserProgressPayload(Payload): + """``methods_browser`` announce(); ``level``: info | warn | error.""" + + message: str + level: str + + +event("browser.progress", BrowserProgressPayload, doc="Browser (CDP) connect / install progress line.") + + +# ── browser controller (gateway/browser_control_broker frames re-enveloped as events) ───────── + + +class BrowserControllerCommandPayload(Payload): + """``gateway/browser_control_broker.py`` FRAME_COMMAND params.""" + + command_id: str + action: str + arguments: dict[str, JsonValue] + controller_id: str | None = None + browser_profile_id: str | None = None + tool_call_id: str | None = None + + +class BrowserControllerCancelPayload(Payload): + """``gateway/browser_control_broker.py::_cancel_frame``.""" + + command_id: str + tool_call_id: str | None = None + + +event("browser.controller.command", BrowserControllerCommandPayload, doc="Dispatch one browser action to the attached controller.") +event("browser.controller.cancel", BrowserControllerCancelPayload, doc="Withdraw a pending controller command.") + + +# ── voice ───────────────────────────────────────────────────────────────────────────────────── + + +event("voice.interrupted", None, doc="Barge-in: the spoken interjection interrupted the turn; no payload.") + + +class VoiceStatusPayload(Payload): + """``methods_voice._vr_on_status``; states come from the recorder (idle / listening / transcribing …).""" + + state: str + + +class VoiceTranscriptPayload(Payload): + """``methods_voice._vr_transcript`` / ``_deliver_fd_transcript`` / typed stop phrase in methods_prompt.""" + + text: str | None = None + stop_phrase: bool | None = None + typed: bool | None = None + no_speech_limit: bool | None = None + + +class WakeDetectedPayload(Payload): + """``methods_voice`` wake detector ``_on_detect``.""" + + phrase: str + profile: str | None = None + start_new_session: bool + + +event("voice.status", VoiceStatusPayload, doc="Voice recorder state changed.") +event("voice.transcript", VoiceTranscriptPayload, doc="A voice capture produced text (or a stop phrase / silence limit).") +event("wake.detected", WakeDetectedPayload, doc="A wake phrase fired.") + + +# ── pets ────────────────────────────────────────────────────────────────────────────────────── + + +class PetChangedPayload(OpenPayload): + """``change_watcher._pet_changed_payload`` — ``pet.info.meta``-shaped; ``{enabled: false}`` when off.""" + + enabled: bool + slug: str | None = None + displayName: str | None = None # noqa: N815 - wire key + scale: float | None = None + spritesheetRevision: str | None = None # noqa: N815 - wire key + + +class PetGenerateProgressPayload(OpenPayload): + """``methods_session`` pet.generate: token-only init frame, then one per draft.""" + + token: str + count: int + index: int | None = None + dataUri: str | None = None # noqa: N815 - wire key + + +class PetHatchProgressPayload(OpenPayload): + """``methods_session`` pet.hatch ``_on_progress``: ``{event, detail}`` or the parsed row form.""" + + event: str + detail: str | None = None + state: str | None = None + done: str | None = None + total: str | None = None + + +event("pet.changed", PetChangedPayload, doc="The active pet / its spritesheet changed (watcher).") +event("pet.generate.progress", PetGenerateProgressPayload, doc="Pet base-draft generation progress.") +event("pet.hatch.progress", PetHatchProgressPayload, doc="Pet hatch (row drawing) progress.") + + +# ── change watcher signals (payload is {} today) ───────────────────────────────────────────── + + +class ChangeSignalPayload(OpenPayload): + """``change_watcher._CHANGE_WATCHES`` payload fn — ``{}`` for every watch except pet.changed.""" + + +event("cron.changed", ChangeSignalPayload, doc="cron/jobs.json moved; refetch the cron list.") +event("sessions.changed", ChangeSignalPayload, doc="state.db moved; refetch the session list.") +event("platforms.changed", ChangeSignalPayload, doc="gateway_state.json moved; refetch platform status.") +event("pairing.changed", ChangeSignalPayload, doc="Pairing state moved; refetch pairing.") +event("bot_relay.outbox.pending", ChangeSignalPayload, doc="A bot-relay outbox envelope is queued; drain it.") + + +__all__ = [ + "BillingBlock", "BillingStepUpVerificationPayload", "BrowserControllerCancelPayload", + "BrowserControllerCommandPayload", "BrowserProgressPayload", "ChangeSignalPayload", "ErrorPayload", + "ErrorSurface", "GatewayReadyPayload", "LayoutApplyPayload", "MessageCompletePayload", + "MessageInterimPayload", "MessageReaction", "MessageReactionPayload", "MoaAggregatingPayload", + "MoaPhasePayload", "MoaProgressPayload", "MoaReferencePayload", "NoticePayload", + "NotificationClearPayload", "NotificationShowPayload", "OpenPayload", "PaneRevealPayload", + "PetChangedPayload", "PetGenerateProgressPayload", "PetHatchProgressPayload", "PreviewClosePayload", + "PreviewOpenPayload", "PreviewRestartProgressPayload", "ReactionPayload", "ResumePhaseStatus", + "ReviewSummaryPayload", "SessionControlSnapshot", "SessionControlUpdatePayload", + "SessionReclaimedPayload", "SessionResumeProgressPayload", "SessionTitlePayload", "SessionUsagePayload", + "SetupReadyPayload", "SideAgentCompletePayload", "SkinPayload", "StatusUpdatePayload", + "StreamDeltaPayload", "SubagentEventPayload", "SubagentOutputTailEntry", "TerminalClosePayload", + "TerminalOutputPayload", "TipShowPayload", "TodoUpdatedPayload", "ToolCompletePayload", + "ToolGeneratingPayload", "ToolOutputRiskPayload", "ToolStartPayload", "TurnStatus", "VoiceStatusPayload", + "VoiceTranscriptPayload", "WakeDetectedPayload", +] diff --git a/tui_gateway/contracts/groups_bot_relay.py b/tui_gateway/contracts/groups_bot_relay.py index 940b608ea4..1204365f5f 100644 --- a/tui_gateway/contracts/groups_bot_relay.py +++ b/tui_gateway/contracts/groups_bot_relay.py @@ -1 +1,646 @@ -"""Contracts: groups_bot_relay (authored by the contract worker).""" +"""Hosted Group Chat rooms (``groups.*``), cross-connection bot relay (``bot_relay.*``) and the +dashboard browser controller (``browser.controller.*``). + +Handlers: ``tui_gateway/methods_groups.py``, ``tui_gateway/methods_bot_relay.py``, +``tui_gateway/methods_browser_control.py``. Room / event / page shapes are produced by +``gateway/hosted_rooms.py`` (``_room_from_row`` / ``_event_from_row`` / ``read_events``) and +``gateway/hosted_room_replicas.py``; the RoomLink catalog by ``gateway/hosted_room_peer.py``. +""" + +from __future__ import annotations + +from .base import JsonValue, Params, Result, WireEnum +from .common import OkResult, OpenModel, ProfileParams +from .registry import method + +# ── shared room shapes ──────────────────────────────────────────────────────────────────────── + + +class RoomMember(OpenModel): + """One roster row (``hosted_room_discussion.validate_roster``); legacy rooms may carry + pre-normalisation rows, so the set stays open.""" + + member_id: str | None = None + profile: str | None = None + handle: str | None = None + display_name: str | None = None + target: dict[str, JsonValue] | None = None + + +class RoomActor(Result): + kind: str + id: str + + +class RoomEvent(Result): + """``gateway/hosted_rooms.py::_event_from_row``.""" + + room_id: str + seq: int + event_id: str + kind: str + actor: RoomActor + authority_epoch: int | None = None + payload: dict[str, JsonValue] + created_at: float + idempotent: bool = False + + +class Room(Result): + """``gateway/hosted_rooms.py::_room_from_row`` plus the branch-only keys ``create`` (legacy + adoption), ``state`` (``authority_claim``) and ``rename`` (``event``) add.""" + + room_id: str + name: str + members: list[RoomMember] + authority_gateway_id: str + authority_epoch: int + revision: int + created_at: float + updated_at: float + idempotent: bool = False + disbanded_at: float | None = None + latest_seq: int | None = None + adopted: bool | None = None + claim_event: RoomEvent | None = None + authority_claim: RoomEvent | None = None + event: RoomEvent | None = None + + +class RoomAuthority(Result): + gateway_id: str + epoch: int + + +class RoomMemberInput(Params): + """A roster row as the client proposes it; ``validate_roster`` owns the exact rules.""" + + member_id: str | None = None + profile: str | None = None + handle: str | None = None + display_name: str | None = None + target: dict[str, JsonValue] | None = None + model_config = Params.model_config | {"extra": "allow"} + + +class RoomParams(ProfileParams): + """Any method addressed at one hosted room.""" + + room_id: str + + +# ── RoomLink catalog ────────────────────────────────────────────────────────────────────────── + + +class RoomExecutionPolicy(Result): + """``gateway/hosted_room_execution_policy.py::execution_policy_mapping``.""" + + version: int + target_profile: str + enabled_toolsets: list[str] + approval_mode: str + max_iterations: int + policy_digest: str + + +class RoomLinkEndpoint(Result): + """``GatewayRoomCatalog.endpoint_mapping``: ``url``/``transport_security`` when available, + ``reason`` when not.""" + + available: bool + url: str | None = None + transport_security: str | None = None + reason: str | None = None + + +class RoomLinkCatalog(Result): + """``gateway/hosted_room_peer.py::GatewayRoomCatalog.as_mapping``.""" + + installation_id: str + protocol_versions: list[int] + link_modes: list[str] + persistent_process: bool + text: bool + attachments: bool + execution_policy: RoomExecutionPolicy + catalog_digest: str + endpoint: RoomLinkEndpoint | None = None + + +class RoomLinkStatus(Result): + """``enabled`` with ``profile``/``catalog``/``endpoint``, or disabled with a ``reason``.""" + + enabled: bool + profile: str | None = None + catalog: RoomLinkCatalog | None = None + endpoint: RoomLinkEndpoint | None = None + reason: str | None = None + + +# ── groups.capabilities ─────────────────────────────────────────────────────────────────────── + + +class GroupsCapabilitiesParams(ProfileParams): + pass + + +class GroupsCapabilitiesResult(Result): + protocol_version: int + driver: bool + persistent_process: bool + authority_gateway_id: str + room_link: RoomLinkStatus + features: list[str] + methods: list[str] + max_log_limit: int + + +method("groups.capabilities", params=GroupsCapabilitiesParams, result=GroupsCapabilitiesResult, + doc="Describe the hosted-room protocol implemented by this gateway.") + + +# ── groups.list / create / state ────────────────────────────────────────────────────────────── + + +class GroupsListParams(ProfileParams): + include_disbanded: bool | None = None + limit: int | None = None + offset: int | None = None + + +class GroupsListResult(Result): + rooms: list[Room] + next_offset: int | None = None + + +method("groups.list", params=GroupsListParams, result=GroupsListResult, + doc="List rooms hosted by this gateway, most recently changed first.") + + +class GroupsCreateParams(ProfileParams): + room_id: str + name: str + members: list[RoomMemberInput] + # Ignored: authority is always this gateway's install identity (a client cannot spoof it). + authority_gateway_id: str | None = None + + +class GroupsCreateResult(Result): + room: Room + + +method("groups.create", params=GroupsCreateParams, result=GroupsCreateResult, + doc="Create a hosted room idempotently; authority is this gateway's stable install identity.") + + +class GroupsStateParams(RoomParams): + include_disbanded: bool | None = None + + +class PeerRouteStatus(Result): + room_id: str + member_id: str + status: str + + +class RoomDriverStatus(Result): + """``HostedRoomService.status(room_id)``; ``pending_actions`` rows are ``{kind: retry, task_id}`` + or the driver's approval action (``kind: approval`` + run/session/approval context).""" + + running: bool + working: bool + blocked: bool + counts: dict[str, int] + pending_actions: list[dict[str, JsonValue]] + peer_routes: list[PeerRouteStatus] + + +class GroupsStateResult(Result): + room: Room + driver_status: RoomDriverStatus | None = None + + +method("groups.state", params=GroupsStateParams, result=GroupsStateResult, + doc="One hosted room's replay cursor and fenced authority state, plus live driver status.") + + +# ── groups.send / rename / log ──────────────────────────────────────────────────────────────── + + +class GroupsSendParams(RoomParams): + event_id: str | None = None + payload: dict[str, JsonValue] + + +class GroupsSendResult(Result): + event: RoomEvent + client_event_id: str | None = None + accepted: bool = True + driver_started: bool = True + + +method("groups.send", params=GroupsSendParams, result=GroupsSendResult, + doc="Append one inert message.user event idempotently; the actor is server-owned.") + + +class GroupsRenameParams(RoomParams): + event_id: str + name: str + + +class GroupsRenameResult(Result): + room: Room + + +method("groups.rename", params=GroupsRenameParams, result=GroupsRenameResult, + doc="Rename one hosted room atomically with its replay event.") + + +class GroupsLogParams(RoomParams): + since_seq: int | None = None + limit: int | None = None + include_disbanded: bool | None = None + + +class GroupsLogResult(Result): + """``gateway/hosted_rooms.py::read_events`` page — also the ``page`` ``groups.replicate`` ingests.""" + + events: list[RoomEvent] + cursor: int + latest_seq: int + has_more: bool + authority: RoomAuthority + + +method("groups.log", params=GroupsLogParams, result=GroupsLogResult, + doc="A monotonic room-log delta after since_seq, bounded by count and page bytes.") + + +# ── groups.disband / stop / approve / retry ─────────────────────────────────────────────────── + + +class GroupsDisbandParams(RoomParams): + cancel_id: str | None = None + + +class RoomTombstone(Result): + room_id: str + disbanded_at: float + idempotent: bool + history_expired: bool | None = None + event: RoomEvent | None = None + + +class GroupsDisbandResult(Result): + tombstone: RoomTombstone + + +method("groups.disband", params=GroupsDisbandParams, result=GroupsDisbandResult, + doc="Permanently tombstone a hosted room id after stopping its work and revoking peer routes.") + + +class GroupsStopParams(RoomParams): + cancel_id: str | None = None + + +class GroupsStopResult(Result): + cancelled: int + + +method("groups.stop", params=GroupsStopParams, result=GroupsStopResult, + doc="Durably cancel queued or running work for one hosted room.") + + +class ApprovalChoice(WireEnum): + once = "once" + deny = "deny" + + +class GroupsApproveParams(RoomParams): + member_id: str + task_id: str + execution_generation: int + choice: ApprovalChoice + request_id: str + + +class GroupsApproveResult(Result): + """``result`` is the local ``approval.respond`` answer or the peer's run-action receipt.""" + + approved: bool = True + result: dict[str, JsonValue] + + +method("groups.approve", params=GroupsApproveParams, result=GroupsApproveResult, + doc="Resolve one exact pending approval raised by a local or peer room member.") + + +class GroupsRetryParams(RoomParams): + task_id: str + + +class RoomTaskReceipt(Result): + room_id: str + task_id: str + thread_id: str + turn_id: str + status: str + execution_generation: int + cancel_generation: int + + +class GroupsRetryResult(Result): + retried: bool = True + task: RoomTaskReceipt + + +method("groups.retry", params=GroupsRetryParams, result=GroupsRetryResult, + doc="Retry one indeterminate room task after explicit user confirmation.") + + +# ── replication / authority takeover ────────────────────────────────────────────────────────── + + +class GroupsReplicateParams(RoomParams): + room_name: str + members: list[RoomMemberInput] + page: dict[str, JsonValue] # a verbatim ``groups.log`` result + + +class GroupsReplicateResult(Result): + room_id: str + stored_seq: int + ingested: int + authority: RoomAuthority + caught_up: bool + + +method("groups.replicate", params=GroupsReplicateParams, result=GroupsReplicateResult, + doc="Persist one authority-stamped replay page into the local replica store; idempotent.") + + +class GroupsReplicaStateParams(RoomParams): + pass + + +class GroupsReplicaStateResult(Result): + room_id: str + name: str + members: list[RoomMember] + authority: RoomAuthority + last_seq: int + latest_seq: int + event_bytes: int + created_at: float + updated_at: float + + +method("groups.replica_state", params=GroupsReplicaStateParams, result=GroupsReplicaStateResult, + doc="The local replica's coverage and authority lineage for one room.") + + +class GroupsPromoteParams(RoomParams): + confirm: bool | None = None + reason: str | None = None + + +class GroupsPromoteResult(Result): + room_id: str + authority_gateway_id: str + authority_epoch: int + previous_gateway_id: str + previous_epoch: int + claim_seq: int + latest_seq: int + + +method("groups.promote", params=GroupsPromoteParams, result=GroupsPromoteResult, + doc="Continue a replicated room on this gateway at epoch + 1; requires confirm=true.") + + +class GroupsDemoteParams(RoomParams): + observed_gateway_id: str + observed_epoch: int + + +class GroupsDemoteResult(Result): + room_id: str + authority_gateway_id: str + authority_epoch: int + idempotent: bool + + +method("groups.demote", params=GroupsDemoteParams, result=GroupsDemoteResult, + doc="Fence this gateway's stale room authority against a proven newer epoch.") + + +# ── peer routes (RoomLink) ──────────────────────────────────────────────────────────────────── + + +class GroupsPeerInviteParams(ProfileParams): + room_id: str | None = None + home_install_id: str | None = None + authority_gateway_id: str | None = None + authority_epoch: int | None = None + member_id: str | None = None + grant_id: str | None = None + ttl_seconds: float | None = None + + +class GroupsPeerInviteResult(Result): + grant: str + target_profile: str + catalog: RoomLinkCatalog + endpoint: RoomLinkEndpoint + + +method("groups.peer.invite", params=GroupsPeerInviteParams, result=GroupsPeerInviteResult, + doc="Mint one target-issued room/profile grant for a prospective room home.") + + +class GroupsPeerRevokeParams(ProfileParams): + grant: str + + +class GroupsPeerRevokeResult(Result): + revoked: bool = True + + +method("groups.peer.revoke", params=GroupsPeerRevokeParams, result=GroupsPeerRevokeResult, + doc="Revoke one target-issued grant using its exact profile scope.") + + +class GroupsPeerRegisterParams(RoomParams): + member_id: str + target_url: str + target_profile: str + grant: str + catalog: dict[str, JsonValue] # a RoomLinkCatalog mapping; ``GatewayRoomCatalog.from_mapping`` is exact + cancellation_scope_id: str | None = None + trace_id: str | None = None + + +class GroupsPeerRegisterResult(Result): + registered: bool = True + mode: str + transport_security: str + target_install_id: str + target_profile: str + + +method("groups.peer.register", params=GroupsPeerRegisterParams, result=GroupsPeerRegisterResult, + doc="Register and probe one scoped peer route on the room home.") + + +# ── bot relay ───────────────────────────────────────────────────────────────────────────────── + + +class RelayAgentRow(Params): + """A roster row the Desktop pushes (``tools/bot_relay.py::_normalize_roster_row``); invalid + rows are dropped server-side, so the shape stays open.""" + + profile: str | None = None + handle: str | None = None + connection_id: str | None = None + connection_label: str | None = None + title: str | None = None + description: str | None = None + online: bool | None = None + model_config = Params.model_config | {"extra": "allow"} + + +class BotRelayRosterSyncParams(ProfileParams): + agents: list[RelayAgentRow] | None = None + + +class BotRelayRosterSyncResult(Result): + count: int + + +method("bot_relay.roster.sync", params=BotRelayRosterSyncParams, result=BotRelayRosterSyncResult, + doc="Replace this gateway's view of agents on other connections; answers the accepted row count.") + + +class BotRelayOutboxDrainParams(ProfileParams): + pass + + +class RelayEnvelope(OpenModel): + """``tools/bot_relay.py::enqueue_envelope``.""" + + id: str + created_at: int | float + from_profile: str + from_handle: str + target_connection: str + target_profile: str + target_handle: str + message: str + + +class BotRelayOutboxDrainResult(Result): + envelopes: list[RelayEnvelope] + + +method("bot_relay.outbox.drain", params=BotRelayOutboxDrainParams, result=BotRelayOutboxDrainResult, + doc="Atomically claim every pending cross-connection envelope queued on this gateway.") + + +class BotRelayDeliverParams(Params): + """``profile`` here is the TARGET profile on this gateway (also what the desktop route wrapper adds).""" + + profile: str + message: str + from_profile: str | None = None + from_handle: str | None = None + from_connection: str | None = None + + +class BotRelayDeliverResult(Result): + reply: str + + +method("bot_relay.deliver", params=BotRelayDeliverParams, result=BotRelayDeliverResult, + doc="Deliver a relayed DM into a Bot Chat on this gateway and return the one-turn reply (blocking).") + + +class BotRelayReplyParams(ProfileParams): + id: str + reply: str | None = None + error: str | None = None + reason: str | None = None + + +method("bot_relay.reply", params=BotRelayReplyParams, result=OkResult, + doc="Write a relayed reply and/or typed error for an envelope so the sender-side waiter resolves.") + + +# ── browser controller ──────────────────────────────────────────────────────────────────────── + + +class BrowserControllerParams(Params): + """Every controller call names the session the controller is attached to.""" + + session_id: str + + +class BrowserControllerRegisterParams(BrowserControllerParams): + controller_id: str + browser_profile_id: str + capabilities: list[str] | None = None + protocol_version: JsonValue | None = None # checked exactly by the handler (an int today) + # Ignored: the principal is derived from the server-minted identity, never client-supplied. + principal_id: str | None = None + + +class ControllerScope(Result): + principal_id: str + profile_id: str + session_id: str + controller_id: str + browser_profile_id: str + transport_family: str + capabilities: list[str] + + +class BrowserControllerRegisterResult(Result): + scope: ControllerScope + + +method("browser.controller.register", params=BrowserControllerRegisterParams, + result=BrowserControllerRegisterResult, + doc="Attach this connection as the browser controller for one session; fails closed (4403).") + + +class BrowserControllerResultParams(BrowserControllerParams): + command_id: str + ok: JsonValue | None = None # only the exact ``true`` counts as success + result: JsonValue | None = None + error: JsonValue | None = None + + +class BrowserControllerResultResult(Result): + accepted: bool + + +method("browser.controller.result", params=BrowserControllerResultParams, + result=BrowserControllerResultResult, + doc="Deliver one command result to the broker; accepted is false for unknown or settled command ids.") + + +method("browser.controller.heartbeat", params=BrowserControllerParams, result=OkResult, + doc="Acknowledge a heartbeat only for this transport's own attached controller.") + + +class BrowserControllerDetachResult(Result): + detached: bool = True + + +method("browser.controller.detach", params=BrowserControllerParams, result=BrowserControllerDetachResult, + doc="Hard-detach only the controller owned by this authenticated transport.") + + +__all__ = [ + "GroupsLogResult", "RelayEnvelope", "Room", "RoomAuthority", "RoomEvent", "RoomLinkCatalog", + "RoomMember", "RoomMemberInput", +] diff --git a/tui_gateway/contracts/profiles_vault_complete_foreign_subagents.py b/tui_gateway/contracts/profiles_vault_complete_foreign_subagents.py index d2ed6283df..ddc40c8943 100644 --- a/tui_gateway/contracts/profiles_vault_complete_foreign_subagents.py +++ b/tui_gateway/contracts/profiles_vault_complete_foreign_subagents.py @@ -1 +1,635 @@ -"""Contracts: profiles_vault_complete_foreign_subagents (authored by the contract worker).""" +"""Contracts for ``methods_profiles``, ``methods_vault``, ``methods_complete``, +``methods_session_foreign`` and ``methods_subagents``. + +Profiles are the ws twin of the dashboard's ``/api/profiles``; the vault handlers are the +Desktop's Settings → Credential Vault door (metadata only — a secret never appears in a result); +completions feed the composer popovers; ``session.foreign.*`` browses Claude Code / Codex +histories on the serving backend; ``subagent.*`` is the session-scoped roster of live children. +""" + +from __future__ import annotations + +from typing import Literal + +from pydantic import Field + +from .base import JsonValue, Params, Result, WireEnum +from .common import OpenModel, ProfileParams, SessionParams, SubagentStatus +from .registry import method + +# ── completions / paste / model keys (methods_complete) ─────────────────────────────────────── + + +class CompletionItem(Result): + """One popover row; ``kind`` rides only on slash completions (command vs skill).""" + + text: str + display: str = "" + meta: str = "" + kind: str | None = None + + +class CompletionItemsResult(Result): + items: list[CompletionItem] = Field(default_factory=list) + + +class CompletePathParams(ProfileParams): + """``word`` is the token under the cursor (``@`` prefix = context reference); ``cwd`` / + ``session_id`` pick the directory the listing resolves against.""" + + word: str | None = None + cwd: str | None = None + session_id: str | None = None + + +method("complete.path", params=CompletePathParams, result=CompletionItemsResult, + doc="Path / @-reference completions for the composer (files, folders, profiles, plugin providers).") + + +class CompleteSlashParams(Params): + text: str | None = None + + +class CompleteSlashResult(Result): + """``replace_from`` is the column the accepted item replaces from.""" + + items: list[CompletionItem] = Field(default_factory=list) + replace_from: int | None = None + + +method("complete.slash", params=CompleteSlashParams, result=CompleteSlashResult, + doc="Ranked slash-command / skill completions for a ``/`` token.") + + +class PasteCollapseParams(Params): + text: str | None = None + + +class PasteCollapseResult(Result): + placeholder: str + path: str + lines: int + + +method("paste.collapse", params=PasteCollapseParams, result=PasteCollapseResult, + doc="Spill a large paste to a file and hand back the inline placeholder.") + + +class ModelProviderRow(OpenModel): + """One provider row of the shared inventory builder (``hermes_cli.inventory``); the closed + set of keys is owned there.""" + + # TODO(common): same shape as the ``model.options`` provider rows — consolidate. + slug: str + name: str = "" + is_current: bool = False + is_user_defined: bool | None = None + models: list[JsonValue] = Field(default_factory=list) + total_models: int | None = None + authenticated: bool | None = None + auth_type: str | None = None + key_env: str | None = None + warning: str | None = None + + +class ModelSaveKeyParams(Params): + slug: str + api_key: str + session_id: str | None = None + + +class ModelSaveKeyResult(Result): + provider: ModelProviderRow + + +method("model.save_key", params=ModelSaveKeyParams, result=ModelSaveKeyResult, + doc="Save an API key for a provider and return its refreshed inventory row.") + + +class ModelDisconnectParams(Params): + slug: str + session_id: str | None = None + + +class ModelDisconnectResult(Result): + slug: str + name: str + disconnected: bool + + +method("model.disconnect", params=ModelDisconnectParams, result=ModelDisconnectResult, + doc="Remove every credential (env keys and OAuth state) for a provider.") + + +# ── profiles (methods_profiles) ─────────────────────────────────────────────────────────────── + + +class ProfileSessionPreview(Result): + """Newest human-facing session of a profile (``_latest_profile_session_rows``).""" + + id: str + title: str = "" + preview: str = "" + started_at: float | int = 0 + last_active: float | int = 0 + message_count: int = 0 + + +class ProfileWorkerSession(Result): + """Newest kanban/tool worker row, so rosters can show a profile as working.""" + + id: str + source: str = "" + title: str = "" + last_active: float | int = 0 + + +class ProfileCanonicalSession(Result): + """The profile's "Bot Chat" registry row; ``resolved_id`` is the live compression tip.""" + + id: str + resolved_id: str + root_title: str = "" + title: str = "" + preview: str = "" + started_at: float | int = 0 + last_active: float | int = 0 + message_count: int = 0 + + +class ProfileRow(Result): + """One roster row; the session fields are present only with ``include_sessions``.""" + + name: str + path: str + is_default: bool = False + model: str | None = None + provider: str | None = None + description: str = "" + display_name: str = "" + skill_count: int = 0 + last_session: ProfileSessionPreview | None = None + worker_session: ProfileWorkerSession | None = None + canonical_session: ProfileCanonicalSession | None = None + ui_meta_revisions: dict[str, int] = Field(default_factory=dict) + ui_meta: dict[str, JsonValue] | None = None + has_avatar: bool = False + + +class ProfilesListParams(ProfileParams): + include_sessions: bool | str | None = None + + +class ProfilesListResult(Result): + """``bot_mode_protocol`` tells clients this backend injects the teammate protocol itself.""" + + profiles: list[ProfileRow] = Field(default_factory=list) + bot_mode_protocol: bool = True + + +method("profiles.list", params=ProfilesListParams, result=ProfilesListResult, + doc="Roster of profiles with previews so a client paints without N follow-up calls.") + + +class ProfilesCreateParams(ProfileParams): + """``clone_from`` omitted = fresh profile + bundled skills; ``mirror_credentials`` defaults on + so a headless bot has a provider.""" + + name: str + description: str | None = None + clone_from: str | None = None + clone_all: bool | str | None = None + clone_channels: bool | str | None = None + no_skills: bool | str | None = None + no_alias: bool | str | None = None + soul: str | None = None + model: str | None = None + provider: str | None = None + share_auth: bool | str | None = None + mirror_credentials: bool | str | None = None + + +class ProfileMirrored(Result): + """What was copied from the launch profile; ``auth`` is ``"shared"`` under ``share_auth``.""" + + env: bool = False + auth: bool | Literal["shared"] = False + model_inherited: bool = False + voice: bool = False + + +class ProfilesCreateResult(Result): + ok: bool = True + name: str + path: str + soul_written: bool = False + model_set: bool = False + mirrored: ProfileMirrored + + +method("profiles.create", params=ProfilesCreateParams, result=ProfilesCreateResult, + doc="Create a profile (ws twin of POST /api/profiles), mirroring launch credentials by default.") + + +class ProfileNameParams(ProfileParams): + name: str | None = None + + +class CapabilityEntry(Result): + name: str + enabled: bool = True + + +class ToolsetEntry(CapabilityEntry): + label: str = "" + description: str = "" + tool_count: int = 0 + + +class McpServerEntry(CapabilityEntry): + transport: str = "stdio" + + +class ProfileModelPin(Result): + provider: str = "" + default: str = "" + + +class ProfilesDescribeResult(Result): + """Editor snapshot; ``toolsets_pinned`` says whether ``tools.enabled_toolsets`` is explicit.""" + + name: str + description: str = "" + soul: str = "" + model: ProfileModelPin + skills: list[CapabilityEntry] = Field(default_factory=list) + toolsets: list[ToolsetEntry] = Field(default_factory=list) + toolsets_pinned: bool = False + mcp_servers: list[McpServerEntry] = Field(default_factory=list) + + +method("profiles.describe", params=ProfileNameParams, result=ProfilesDescribeResult, + doc="Everything the profile editor shows: soul, model pin, skills, toolsets, MCP servers.") + + +class ProfilesConfigureParams(ProfileParams): + """Sections are independent; ``ui_meta_expected_revisions`` is a per-key compare-and-swap.""" + + name: str | None = None + ui_meta: dict[str, JsonValue] | None = None + ui_meta_expected_revisions: dict[str, int] | None = None + soul: str | None = None + description: str | None = None + model: str | None = None + provider: str | None = None + confirm_expensive_model: bool | str | None = None + disabled_skills: list[str] | None = None + enabled_toolsets: list[str] | None = None + enabled_mcp_servers: list[str] | None = None + + +class UiMetaConflict(Result): + expected: JsonValue = None + actual: int = 0 + + +class ProfilesConfigureApplied(Result): + """Per-section outcome; only the sections the request carried are present.""" + + ui_meta: bool | None = None + ui_meta_revisions: dict[str, int] | None = None + ui_meta_conflicts: dict[str, UiMetaConflict] | None = None + soul: bool | None = None + description: bool | None = None + model: bool | None = None + skills: bool | None = None + toolsets: bool | None = None + mcp_servers: bool | None = None + + +class ProfilesConfigureResult(Result): + """``confirm_required`` mirrors ``config.set``: a guarded model pick wrote nothing yet.""" + + ok: bool + applied: ProfilesConfigureApplied + confirm_required: bool | None = None + confirm_message: str | None = None + + +method("profiles.configure", params=ProfilesConfigureParams, result=ProfilesConfigureResult, + doc="Editor Save: apply any subset of a profile's sections and report each one.") + + +class ProfilesSetAssetParams(ProfileParams): + """``data`` is a data URL or bare base64 (PNG/JPEG/WebP, sniffed); ``clear`` deletes instead.""" + + name: str | None = None + asset: str | None = None + data: str | None = None + clear: bool | str | None = None + + +class ProfilesSetAssetResult(Result): + ok: bool = True + asset: str + size: int = 0 + removed: int | None = None + + +method("profiles.set_asset", params=ProfilesSetAssetParams, result=ProfilesSetAssetResult, + doc="Store or clear a profile asset (avatar) atomically.") + + +class ProfilesGetAssetParams(ProfileParams): + name: str | None = None + asset: str | None = None + + +class ProfilesGetAssetResult(Result): + """Absent is ``found: false``, not an error.""" + + found: bool + mime: str | None = None + size: int | None = None + data: str | None = None + + +method("profiles.get_asset", params=ProfilesGetAssetParams, result=ProfilesGetAssetResult, + doc="A profile asset as a data URL.") + + +class OnboardingAnswers(Params): + """``tui_gateway/onboarding_personalization.py`` — the facts agreed during onboarding.""" + + name: str | None = None + context: str | None = None + theme: str | None = None + accent: str | None = None + layout: str | None = None + focus: list[str] | None = None + connectors: list[str] | None = None + # The onboarding store may carry extra UI-only keys; the writer ignores unknown ones. + model_config = Params.model_config | {"extra": "allow"} + + +class ProfilesRememberOnboardingParams(ProfileParams): + answers: OnboardingAnswers | None = None + + +class ProfilesRememberOnboardingResult(Result): + saved: bool = True + profile: str = "default" + target: str = "user" + + +method("profiles.remember_onboarding", params=ProfilesRememberOnboardingParams, + result=ProfilesRememberOnboardingResult, + doc="Write the onboarding facts into the default profile's user memory and confirm they landed.") + + +# ── vault (methods_vault) ───────────────────────────────────────────────────────────────────── + + +class VaultKind(WireEnum): + login = "login" + payment = "payment" + address = "address" + + +class VaultItem(Result): + """Metadata-only view (``VaultItemMeta.to_dict`` + ``backend``); never a secret.""" + + id: str + kind: str + label: str + origin: str | None = None + created_at: str = "" + identifier: str | None = None + identifier_type: str | None = None + has_otp: bool | None = None + backend: str + + +class VaultListResult(Result): + items: list[VaultItem] = Field(default_factory=list) + + +method("vault.list", params=ProfileParams, result=VaultListResult, + doc="Metadata-only listing across the local vault and every unlocked password manager.") + + +class VaultSource(Result): + name: str + display_name: str + enabled: bool + needs_unlock: bool + unlocked: bool + installed: bool + + +class VaultSourcesResult(Result): + sources: list[VaultSource] = Field(default_factory=list) + + +method("vault.sources", params=ProfileParams, result=VaultSourcesResult, + doc="Status of every login source (local vault + detected password managers).") + + +class VaultSourceSetParams(ProfileParams): + name: str | None = None + enabled: bool | None = None + + +class VaultSourceSetResult(Result): + name: str + enabled: bool + + +method("vault.source.set", params=VaultSourceSetParams, result=VaultSourceSetResult, + doc="Enable or disable an external password manager (disabling also locks it).") + + +class VaultUnlockParams(ProfileParams): + """The master password is consumed by the manager CLI and never stored or logged.""" + + name: str | None = None + password: str | None = None + + +class VaultUnlockResult(Result): + name: str + unlocked: bool = True + + +method("vault.unlock", params=VaultUnlockParams, result=VaultUnlockResult, + doc="Unlock a password manager for this session with its master password.") + + +class VaultLockParams(ProfileParams): + name: str | None = None + + +class VaultLockResult(Result): + locked: bool = True + + +method("vault.lock", params=VaultLockParams, result=VaultLockResult, + doc="Forget a manager's session token (every manager when no name is given).") + + +class VaultAddParams(ProfileParams): + """``secret`` goes straight into the encrypted store; the result carries only the new id.""" + + kind: VaultKind | None = None + label: str | None = None + origin: str | None = None + secret: dict[str, JsonValue] | None = None + + +class VaultAddResult(Result): + id: str + + +method("vault.add", params=VaultAddParams, result=VaultAddResult, + doc="Add a login / payment / address item to the local vault.") + + +class VaultRemoveParams(ProfileParams): + id: str | None = None + + +class VaultRemoveResult(Result): + removed: bool + + +method("vault.remove", params=VaultRemoveParams, result=VaultRemoveResult, + doc="Remove a local vault item by id.") + + +# ── foreign histories (methods_session_foreign) ─────────────────────────────────────────────── + + +class ForeignSource(WireEnum): + claude = "claude" + codex = "codex" + + +class ForeignSessionRow(Result): + """``hermes_cli/foreign_sessions_browser.py::list_foreign_sessions`` — ``id`` is an opaque + handle, never a path.""" + + id: str + source: ForeignSource + label: str + title: str = "" + cwd: str | None = None + mtime: float + turn_count: int = 0 + excerpt: str = "" + + +class SessionForeignListParams(ProfileParams): + source: ForeignSource | None = None + offset: int | None = None + limit: int | None = None + + +class SessionForeignListResult(Result): + """``unreadable`` counts logs on this page that failed to parse.""" + + sessions: list[ForeignSessionRow] = Field(default_factory=list) + next_offset: int | None = None + host: str + unreadable: int = 0 + + +method("session.foreign.list", params=SessionForeignListParams, result=SessionForeignListResult, + doc="One page of Claude Code / Codex sessions found on the serving backend.") + + +class ForeignTurn(Result): + role: str + content: str + + +class SessionForeignIdParams(ProfileParams): + id: str | None = None + + +class SessionForeignPreviewResult(Result): + """Bounded to the last 40 turns / 8000 chars each; ``already_imported`` is the local id.""" + + messages: list[ForeignTurn] = Field(default_factory=list) + total: int = 0 + truncated: bool = False + already_imported: str | None = None + cwd: str | None = None + + +method("session.foreign.preview", params=SessionForeignIdParams, result=SessionForeignPreviewResult, + doc="Preview a foreign session's tail before importing it.") + + +class SessionForeignImportResult(Result): + session_id: str + already_imported: bool = False + + +method("session.foreign.import", params=SessionForeignIdParams, result=SessionForeignImportResult, + doc="Import a foreign session into this profile's history (idempotent per origin).") + + +# ── subagents (methods_subagents) ───────────────────────────────────────────────────────────── + + +class SubagentSnapshot(Result): + """``methods_subagents._SUBAGENT_SNAPSHOT_FIELDS`` projection of one live child record.""" + + subagent_id: str + parent_id: str | None = None + depth: int | None = None + goal: str | None = None + delegation_id: str | None = None + model: str | None = None + started_at: float | None = None + status: SubagentStatus | None = None + tool_count: int | None = None + last_tool: str | None = None + accepting_steer: bool | None = None + + +class SubagentListResult(Result): + """``delegations`` is reserved for async delegation records and is currently always empty.""" + + subagents: list[SubagentSnapshot] = Field(default_factory=list) + delegations: list[dict[str, JsonValue]] = Field(default_factory=list) + + +method("subagent.list", params=SessionParams, result=SubagentListResult, + doc="Live children owned by this session (other sessions' children never leak).") + + +class SubagentIdParams(SessionParams): + subagent_id: str + + +class SubagentInterruptResult(Result): + found: bool + subagent_id: str + + +method("subagent.interrupt", params=SubagentIdParams, result=SubagentInterruptResult, + doc="Hard-interrupt one owned child; ``found`` is false when it already finished.") + + +class SubagentTailResult(Result): + """``available`` is false while the child has no live transcript yet (or it was cleaned up).""" + + subagent_id: str + available: bool = False + text: str = "" + truncated: bool = False + + +method("subagent.tail", params=SubagentIdParams, result=SubagentTailResult, + doc="Last 16KB of an owned child's live transcript.") diff --git a/tui_gateway/contracts/projects_pets.py b/tui_gateway/contracts/projects_pets.py index 51909f0783..d0d76aeb5a 100644 --- a/tui_gateway/contracts/projects_pets.py +++ b/tui_gateway/contracts/projects_pets.py @@ -1 +1,472 @@ -"""Contracts: projects_pets (authored by the contract worker).""" +"""Projects (``projects.*`` — per-profile multi-folder workspaces, repo discovery, sidebar tree) +and the pet mascot surface (``pet.*`` — gallery, sprite payloads, adopt/remove/rename). + +Every method here is profile-scoped: the desktop's ``projectParams`` / ``petRpc`` wrappers add +``profile`` so app-global remote mode reads the focused profile's ``projects.db`` / ``config.yaml``. +The pet wire predates the snake_case rule and travels camelCase (``displayName``, +``spritesheetBase64``); the field names below are those wire keys verbatim. +""" + +from __future__ import annotations + +from pydantic import Field + +from .base import JsonValue, Params, Result +from .common import OkResult, OpenModel, ProfileParams, StoredSessionRow +from .registry import method + +# ── projects: stored rows ───────────────────────────────────────────────────────────────────── + + +class ProjectFolder(Result): + """``hermes_cli/projects_db.py::ProjectFolder.to_dict``.""" + + path: str + label: str | None = None + is_primary: bool = False + added_at: int | None = None + + +class ProjectInfo(Result): + """``hermes_cli/projects_db.py::Project.to_dict`` — one stored project with its folders.""" + + id: str + slug: str + name: str + description: str | None = None + icon: str | None = None + color: str | None = None + board_slug: str | None = None + primary_path: str | None = None + archived: bool = False + created_at: int + folders: list[ProjectFolder] = Field(default_factory=list) + + +class ProjectsPayload(Result): + """``methods_projects._projects_payload``: every project (archived included) + the active id.""" + + projects: list[ProjectInfo] + active_id: str | None = None + + +class ProjectResult(Result): + project: ProjectInfo + + +class OptionalProjectResult(Result): + project: ProjectInfo | None = None + + +class ProjectIdParams(ProfileParams): + """Any method addressed at one stored project (``5062`` when the id resolves to nothing).""" + + id: str + + +method("projects.list", params=ProfileParams, result=ProjectsPayload, + doc="Every project of the profile (archived included) plus which one is active.") +method("projects.get", params=ProjectIdParams, result=ProjectResult, + doc="One stored project with its folders.") + + +class ProjectsCreateParams(ProfileParams): + """``use`` also activates the new project.""" + + name: str + folders: list[str] | None = None + slug: str | None = None + primary_path: str | None = None + description: str | None = None + icon: str | None = None + color: str | None = None + board_slug: str | None = None + use: bool = False + + +method("projects.create", params=ProjectsCreateParams, result=OptionalProjectResult, + doc="Create a project from a name + folders; duplicate primary paths are refused (5063).") + + +class ProjectsUpdateParams(ProjectIdParams): + """Absent keys are left untouched; ``''`` clears ``color`` / ``icon``.""" + + name: str | None = None + description: str | None = None + icon: str | None = None + color: str | None = None + board_slug: str | None = None + + +method("projects.update", params=ProjectsUpdateParams, result=ProjectResult, + doc="Patch a project's display fields; answers the refreshed project.") + + +class ProjectsAddFolderParams(ProjectIdParams): + path: str + label: str | None = None + is_primary: bool = False + + +method("projects.add_folder", params=ProjectsAddFolderParams, result=ProjectResult, + doc="Attach a folder to a project (optionally as its primary path).") + + +class ProjectFolderParams(ProjectIdParams): + path: str + + +method("projects.remove_folder", params=ProjectFolderParams, result=ProjectResult, + doc="Detach a folder from a project.") +method("projects.set_primary", params=ProjectFolderParams, result=ProjectResult, + doc="Make one attached folder the project's primary path.") + + +class ProjectsArchiveParams(ProjectIdParams): + restore: bool = False + + +method("projects.archive", params=ProjectsArchiveParams, result=ProjectsPayload, + doc="Archive (or with ``restore`` un-archive) a project; answers the full listing.") +method("projects.delete", params=ProjectIdParams, result=ProjectsPayload, + doc="Delete a project and its folders; answers the full listing.") + + +class ProjectsSetActiveParams(ProfileParams): + """No ``id`` (or null) clears the active project.""" + + id: str | None = None + + +class ActiveIdResult(Result): + active_id: str | None = None + + +method("projects.set_active", params=ProjectsSetActiveParams, result=ActiveIdResult, + doc="Switch (or clear) the active project for the profile.") + + +class ProjectsForCwdParams(ProfileParams): + """Absent ``cwd`` resolves the gateway's default completion cwd.""" + + cwd: str | None = None + + +class ProjectsForCwdResult(Result): + project: ProjectInfo | None = None + cwd: str + branch: str = "" + + +method("projects.for_cwd", params=ProjectsForCwdParams, result=ProjectsForCwdResult, + doc="Which project (if any) owns a directory, plus the resolved cwd and its git branch.") + + +# ── projects: repo discovery ────────────────────────────────────────────────────────────────── + + +class RepoDiscoveryPolicy(Result): + """``methods_projects._repo_discovery_policy`` — the effective ``desktop.repo_scan_*`` config.""" + + enabled: bool + roots: list[str] + exclude_paths: list[str] + + +class RepoDiscoveryPolicyParams(Params): + """The policy the desktop scanned under (short or ``repo_scan_*`` long keys both accepted).""" + + enabled: bool | None = None + roots: list[str] | None = None + exclude_paths: list[str] | None = None + repo_scan_enabled: bool | None = None + repo_scan_roots: list[str] | None = None + repo_scan_exclude_paths: list[str] | None = None + + +class DiscoveredRepo(Result): + """``methods_projects._discover_repos_payload`` row: a git root with session totals.""" + + root: str + label: str = "" + sessions: int = 0 + last_active: float = 0.0 + + +class ProjectsDiscoverReposParams(ProfileParams): + """``scan`` asks the host to walk the policy roots itself (remote-gateway desktop).""" + + scan: bool = False + + +class ProjectsDiscoverReposResult(Result): + repos: list[DiscoveredRepo] + discovery_policy: RepoDiscoveryPolicy | None = None + + +method("projects.discover_repos", params=ProjectsDiscoverReposParams, result=ProjectsDiscoverReposResult, + doc="Repos for the desktop overview: scanned-from-disk (cached) ∪ session-derived.") + + +class RecordRepoItem(Params): + root: str + label: str | None = None + + +class ProjectsRecordReposParams(ProfileParams): + """Repos as ``{root, label}`` objects or bare root strings; entries without a root are skipped.""" + + repos: list[RecordRepoItem | str] | None = None + discovery_policy: RepoDiscoveryPolicyParams | None = None + + +class ProjectsRecordReposResult(ProjectsDiscoverReposResult): + accepted: bool + + +method("projects.record_repos", params=ProjectsRecordReposParams, result=ProjectsRecordReposResult, + doc="Persist repo roots found by the client's (desktop-side) scan; return the merged list.") + + +# ── projects: sidebar tree ──────────────────────────────────────────────────────────────────── + + +class ProjectTreeSession(StoredSessionRow): + """``methods_projects._project_tree_row`` + ``project_tree.stamp_profile``: the minimal row the + sidebar renders, stamped with the profile it belongs to.""" + + profile: str | None = None + + +class ProjectTreeLane(Result): + """One branch / worktree / kanban lane inside a repo; ``sessions`` is empty unless hydrated.""" + + id: str + label: str + path: str | None = None + isMain: bool = False + isKanban: bool = False + sessions: list[ProjectTreeSession] = Field(default_factory=list) + + +class ProjectTreeRepo(Result): + id: str + label: str + path: str | None = None + groups: list[ProjectTreeLane] = Field(default_factory=list) + sessionCount: int = 0 + + +class ProjectTreeNode(Result): + """``project_tree._project_node`` — explicit, auto (git root) or the synthetic Home bucket.""" + + id: str + label: str + path: str | None = None + color: str | None = None + icon: str | None = None + isAuto: bool = False + isNoProject: bool = False + sessionCount: int = 0 + lastActive: float = 0.0 + totalTokens: int = 0 + totalCostUsd: float = 0.0 + repos: list[ProjectTreeRepo] = Field(default_factory=list) + previewSessions: list[ProjectTreeSession] = Field(default_factory=list) + + +class ProjectsTreeParams(ProfileParams): + preview_limit: int | None = None + session_limit: int | None = None + + +class ProjectsTreeResult(Result): + projects: list[ProjectTreeNode] + active_id: str | None = None + scoped_session_ids: list[str] = Field(default_factory=list) + + +method("projects.tree", params=ProjectsTreeParams, result=ProjectsTreeResult, + doc="Project → repo → lane overview with counts and a few preview sessions per project.") + + +class ProjectsProjectSessionsParams(ProfileParams): + project_id: str + session_limit: int | None = None + + +class ProjectsProjectSessionsResult(Result): + project: ProjectTreeNode | None = None + + +method("projects.project_sessions", params=ProjectsProjectSessionsParams, result=ProjectsProjectSessionsResult, + doc="Fully hydrated lanes for one project, from the same grouping as projects.tree.") + + +# ── pet: active mascot ──────────────────────────────────────────────────────────────────────── + + +class PetInfoParams(ProfileParams): + """``knownRevision``: the spritesheet revision the caller already holds (send-once bytes).""" + + knownRevision: str | None = None + + +class PetInfoResult(OpenModel): + """``server._pet_sprite_payload`` behind ``enabled``; every sprite field is absent when the pet + display is off, ``spritesheetBase64`` is elided when ``spritesheetUnchanged``.""" + + enabled: bool + slug: str | None = None + displayName: str | None = None + mime: str | None = None + spritesheetBase64: str | None = None + spritesheetRevision: str | None = None + spritesheetUnchanged: bool | None = None + frameW: int | None = None + frameH: int | None = None + framesPerState: int | None = None + framesByState: dict[str, int] | None = None + framesByRow: dict[str, int] | None = None + loopMs: int | None = None + scale: float | None = None + stateRows: list[str] | None = None + + +method("pet.info", params=PetInfoParams, result=PetInfoResult, + doc="Active pet for sprite renderers: spritesheet (base64) + frame geometry + state-row taxonomy.") + + +class PetInfoMetaResult(Result): + enabled: bool + slug: str | None = None + displayName: str | None = None + scale: float | None = None + spritesheetRevision: str | None = None + + +method("pet.info.meta", params=ProfileParams, result=PetInfoMetaResult, + doc="Cheap active-pet metadata used to avoid full payload refreshes.") + + +class PetCellsParams(ProfileParams): + """``graphics`` opts into the kitty payload when the TTY speaks it; ``cols`` overrides the width.""" + + state: str | None = None + cols: int | None = None + graphics: bool = False + + +class PetCellsResult(Result): + """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.""" + + enabled: bool + slug: str | None = None + displayName: str | None = None + state: str | None = None + cols: int | None = None + frameMs: float | None = None + frames: list[list[list[list[int]]]] | list[str] | None = None + scale: float | None = None + graphics: str | None = None + imageId: int | None = None + color: str | None = None + rows: int | None = None + placeholder: list[str] | None = None + + +method("pet.cells", params=PetCellsParams, result=PetCellsResult, + doc="Half-block cell frames (or a kitty placement) for one pet state.") + + +# ── pet: gallery / picker ───────────────────────────────────────────────────────────────────── + + +class PetGalleryParams(ProfileParams): + localOnly: bool = False + + +class PetGalleryEntry(Result): + slug: str + displayName: str + installed: bool + spritesheetUrl: str = "" + curated: bool | None = None + generated: bool = False + + +class PetGalleryResult(Result): + enabled: bool + active: str = "" + pets: list[PetGalleryEntry] = Field(default_factory=list) + + +method("pet.gallery", params=PetGalleryParams, result=PetGalleryResult, + doc="Petdex gallery + local install state (installed-only offline); localOnly skips the remote manifest.") + + +class PetSlugParams(ProfileParams): + slug: str + + +class PetSlugResult(Result): + ok: bool + slug: str + displayName: str | None = None + + +method("pet.select", params=PetSlugParams, result=PetSlugResult, + doc="Adopt a pet: install (if needed) + activate; writes display.pet.* to config.") +method("pet.remove", params=PetSlugParams, result=PetSlugResult, + doc="Uninstall a pet (delete its directory); if it was active, turn the display off.") + + +class PetRenameParams(PetSlugParams): + name: str + + +method("pet.rename", params=PetRenameParams, result=PetSlugResult, + doc="Rename a pet's display name + realign its slug/dir; follows the active slug in config.") + + +class PetExportResult(Result): + ok: bool + filename: str + zipBase64: str + + +method("pet.export", params=PetSlugParams, result=PetExportResult, + doc="Export an installed pet as a re-importable .zip.") + + +class PetThumbParams(PetSlugParams): + """``url``: spritesheet source for a not-yet-installed pet.""" + + url: str | None = None + + +class PetThumbResult(Result): + ok: bool + slug: str + dataUri: str | None = None + + +method("pet.thumb", params=PetThumbParams, result=PetThumbResult, + doc="Idle-frame PNG data URI for the picker (desktop CSP breaks CDN ).") + +method("pet.disable", params=ProfileParams, result=OkResult, + doc="Turn the pet display off from the desktop picker.") + + +class PetScaleParams(ProfileParams): + scale: JsonValue = None # number or numeric string; a non-number answers 4004 + + +class PetScaleResult(Result): + ok: bool + scale: float + + +method("pet.scale", params=PetScaleParams, result=PetScaleResult, + doc="Persist display.pet.scale (clamped to engine bounds) from the desktop slider.") diff --git a/tui_gateway/contracts/prompt_voice.py b/tui_gateway/contracts/prompt_voice.py index afe74c6718..e080dda1c9 100644 --- a/tui_gateway/contracts/prompt_voice.py +++ b/tui_gateway/contracts/prompt_voice.py @@ -1 +1,548 @@ -"""Contracts: prompt_voice (authored by the contract worker).""" +"""Prompt submission, attachments, side agents, approvals, batch-clarify locks (``methods_prompt.py``) +and voice / wake-word control (``methods_voice.py``). + +``profile`` rides on every method here: the desktop routes session-scoped calls through +``requestForOwnedSession`` / ``requestForBot`` / ``requestGatewayForProfile``, which stamp it. +""" + +from __future__ import annotations + +from pydantic import Field + +from .base import JsonValue, Params, Result, WireEnum +from .common import OpenModel, SessionParams +from .registry import method + +# ── prompt.submit ───────────────────────────────────────────────────────────────────────────── + + +class ClientSurface(WireEnum): + """Where the user typed this turn; anything else is treated as the plain app window.""" + + hud = "hud" + voice_live = "voice-live" + + +class PromptSubmitParams(SessionParams): + """``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``).""" + + text: JsonValue = "" + display_kind: str | None = None # only "hidden" is honoured; anything else renders as a user row + interrupted: bool | None = None # client-side barge-in: the turn's model message carries the note + queued: bool | None = None # client queue drain — the busy path must hold it, never redirect/steer + surface: str | None = None # a ClientSurface value; unknown values clear the surface + voice_context: str | None = None # recent spoken transcript, model input only (voice-live) + truncate_before_user_ordinal: int | None = None + truncate_before_row_id: int | None = None + truncate_before_message_id: str | None = None + confirm_truncate: bool | None = None + confirm_empty_truncate: bool | None = None + rebind_survivor_row_ids: list[int] | None = None + # In-process only: injected by the hosted-room / bot-relay handlers, never accepted from a + # client (a client dict for ``_turn_author`` answers 4124). Excluded from the rendered wire. + hosted_task: JsonValue | None = Field(default=None, exclude=True, alias="_hosted_task") + turn_author: JsonValue | None = Field(default=None, exclude=True, alias="_turn_author") + hosted_terminal_callback: JsonValue | None = Field( + default=None, exclude=True, alias="_hosted_terminal_callback") + + +class PromptSubmitStatus(WireEnum): + streaming = "streaming" + queued = "queued" + steered = "steered" + redirected = "redirected" + + +class PromptSubmitResult(Result): + """``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.""" + + status: PromptSubmitStatus | None = None + voice_stopped: bool | None = None + survivor_user_row_ids: list[int | None] | None = None + survivor_row_id_map: dict[str, int | None] | None = None + turn_isolation: bool | None = None + + +method("prompt.submit", params=PromptSubmitParams, result=PromptSubmitResult, + doc="Send a user turn to a live session; busy sessions queue / steer / redirect instead of refusing.") + + +# ── attachments ─────────────────────────────────────────────────────────────────────────────── + + +class ImageMeta(Result): + """``tui_gateway/server.py::_image_meta`` — dimensions when PIL can open the file.""" + + name: str | None = None + width: int | None = None + height: int | None = None + token_estimate: int | None = None + + +class AttachedImageResult(ImageMeta): + """``methods_prompt.py::_attached_image_result``: the image is queued for the next turn.""" + + attached: bool + path: str | None = None + count: int | None = None + remainder: str | None = None + text: str | None = None + bytes: int | None = None + message: str | None = None # clipboard.paste: why nothing was attached + + +class ClipboardPasteParams(SessionParams): + pass + + +method("clipboard.paste", params=ClipboardPasteParams, result=AttachedImageResult, + doc="Save the host clipboard image into the session and queue it for the next turn.") + + +class ImageAttachParams(SessionParams): + path: str # a host path, optionally followed by remainder text (drop syntax accepted) + + +method("image.attach", params=ImageAttachParams, result=AttachedImageResult, + doc="Queue a gateway-visible image file for the next turn.") + + +class ImageAttachBytesParams(SessionParams): + """``content_base64`` (or the ``data`` alias) carries the bytes; ``filename`` / ``ext`` only hint + the extension — magic bytes decide.""" + + content_base64: str | None = None + data: str | None = None + filename: str | None = None + ext: str | None = None + + +method("image.attach_bytes", params=ImageAttachBytesParams, result=AttachedImageResult, + doc="Queue an image uploaded as base64 (remote client); reply mirrors image.attach.") + + +class PdfAttachParams(SessionParams): + """Host ``path`` or base64 ``content_base64`` / ``data``; ``first_page`` / ``last_page`` bound the + render (per-call page cap enforced server-side).""" + + path: str | None = None + content_base64: str | None = None + data: str | None = None + filename: str | None = None + first_page: int | None = None + last_page: int | None = None + + +class PdfPage(ImageMeta): + path: str + page: int + + +class PdfAttachResult(Result): + attached: bool + filename: str + pages_attached: int + pages: list[PdfPage] + count: int + text: str + + +method("pdf.attach", params=PdfAttachParams, result=PdfAttachResult, + doc="Render a PDF's pages to PNG and queue them as images for the next turn.") + + +class FileAttachParams(SessionParams): + """``path`` when the file is gateway-visible, else ``data_url`` carries the bytes; ``name`` labels + an uploaded file.""" + + path: str | None = None + data_url: str | None = None + name: str | None = None + + +class FileAttachResult(Result): + attached: bool + name: str + path: str + ref_path: str + ref_text: str + uploaded: bool + + +method("file.attach", params=FileAttachParams, result=FileAttachResult, + doc="Stage a non-image file into the session workspace and hand back its @file: ref.") + + +class ImageDetachParams(SessionParams): + path: str + + +class ImageDetachResult(Result): + detached: bool + count: int + + +method("image.detach", params=ImageDetachParams, result=ImageDetachResult, + doc="Drop a queued image before the turn is sent.") + + +class InputDetectDropParams(SessionParams): + text: str | None = None + + +class InputDetectDropResult(ImageMeta): + """``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.""" + + matched: bool + is_image: bool | None = None + path: str | None = None + count: int | None = None + text: str | None = None + + +method("input.detect_drop", params=InputDetectDropParams, result=InputDetectDropResult, + doc="Recognise a terminal file drop pasted into the composer and turn it into an attachment.") + + +# ── side agents ─────────────────────────────────────────────────────────────────────────────── + + +class SideAgentParams(SessionParams): + text: str + + +class TaskIdResult(Result): + """The side agent runs detached; its answer lands on the parent session as an event carrying + this ``task_id``.""" + + task_id: str + + +method("prompt.background", params=SideAgentParams, result=TaskIdResult, + doc="Run a task on a fresh agent in the background; the answer arrives as background.complete.") +method("prompt.btw", params=SideAgentParams, result=TaskIdResult, + doc="Side question over a snapshot of the live conversation; the answer arrives as btw.complete.") + + +class PreviewRestartParams(SessionParams): + url: str + cwd: str | None = None + context: str | None = None # the preview pane's console output + + +method("preview.restart", params=PreviewRestartParams, result=TaskIdResult, + doc="Spawn a hidden agent that brings the desktop preview's dev server back up.") + + +# ── batch clarify locks / proxied request answers ───────────────────────────────────────────── + + +class ClarifyLockParams(Params): + request_id: str + question_id: str + answer: JsonValue = "" # non-string answers are JSON-encoded server-side + profile: str | None = None + + +class ClarifyLockStatus(WireEnum): + ok = "ok" + expired = "expired" + + +class ClarifyLockResult(Result): + """``remaining`` lists the qids still unanswered; the lock that empties it resolves the request. + ``expired``: the wait already ended (timeout / cancel) — not an error.""" + + status: ClarifyLockStatus + remaining: list[str] | None = None + + +method("clarify.lock", params=ClarifyLockParams, result=ClarifyLockResult, + doc="Lock one answer of a batch clarify request (editable until every question is locked).") + + +class RequestAnswerParams(Params): + id: str # the open server→client request id + result: dict[str, JsonValue] + profile: str | None = None + + +class RequestAnswerResult(Result): + status: ClarifyLockStatus + + +method("request.answer", params=RequestAnswerParams, result=RequestAnswerResult, + doc="Answer an open server→client request from a client that never received the frame.") + + +# ── approvals ───────────────────────────────────────────────────────────────────────────────── + + +class PendingApproval(OpenModel): + """One unresolved ``tools/approval.py`` gateway queue entry (snapshot of its ``data``); the key + set is owned by the approval tool, so it stays open.""" + + request_id: str | None = None + command: str | None = None + description: str | None = None + pattern_key: str | None = None + pattern_keys: list[str] | None = None + allow_permanent: bool | None = None + allow_session: bool | None = None + smart_denied: bool | None = None + choices: list[str] | None = None + tool_name: str | None = None + + +class ApprovalPendingParams(SessionParams): + pass + + +class ApprovalPendingResult(Result): + approvals: list[PendingApproval] + + +method("approval.pending", params=ApprovalPendingParams, result=ApprovalPendingResult, + doc="Replay the approvals still waiting on this session (reconnect / polling).") + + +class ApprovalReceivedParams(SessionParams): + request_id: str + + +class ApprovalReceivedResult(Result): + acknowledged: bool + + +method("approval.received", params=ApprovalReceivedParams, result=ApprovalReceivedResult, + doc="Tell the backend the card is on screen, so its timeout clock starts.") + + +class ApprovalRespondParams(SessionParams): + """``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.""" + + choice: str | None = None # default "deny" + all: bool | None = None + request_id: str | None = None + + +class ApprovalRespondResult(Result): + resolved: int # how many pending approvals this decision unblocked + + +method("approval.respond", params=ApprovalRespondParams, result=ApprovalRespondResult, + doc="Deliver the user's decision on a dangerous command (falls back to durable identity on a stale sid).") + + +# ── voice ───────────────────────────────────────────────────────────────────────────────────── + + +class VoiceToggleAction(WireEnum): + status = "status" + on = "on" + off = "off" + tts = "tts" + + +class VoiceToggleParams(Params): + action: VoiceToggleAction = VoiceToggleAction.status + profile: str | None = None + + +class VoiceToggleResult(Result): + """``methods_voice.py::_voice_status_payload`` (+ the requirements probe on ``status``, the spoken + stop hint on ``on``).""" + + enabled: bool + record_key: str + tts: bool + stop_hint: str | None = None + available: bool | None = None + audio_available: bool | None = None + stt_available: bool | None = None + details: str | None = None + + +method("voice.toggle", params=VoiceToggleParams, result=VoiceToggleResult, + doc="/voice parity: report, flip voice mode on/off, or toggle speech output.") + + +class VoiceRecordAction(WireEnum): + start = "start" + stop = "stop" + + +class VoiceRecordParams(Params): + action: VoiceRecordAction = VoiceRecordAction.start + session_id: str | None = None # where voice.transcript / voice.status events are addressed + profile: str | None = None + + +class VoiceRecordStatus(WireEnum): + recording = "recording" + stopped = "stopped" + busy = "busy" + + +class VoiceRecordResult(Result): + status: VoiceRecordStatus + reason: str | None = None # "wake_owned" when another surface holds the mic + + +method("voice.record", params=VoiceRecordParams, result=VoiceRecordResult, + doc="VAD-bounded push-to-talk; the transcript arrives as a voice.transcript event.") + + +class VoiceTtsParams(Params): + text: str + profile: str | None = None + + +class VoiceTtsResult(Result): + status: str # "speaking" + + +method("voice.tts", params=VoiceTtsParams, result=VoiceTtsResult, + doc="Speak text through the backend TTS engine (barge-in aware).") + + +# ── wake word ───────────────────────────────────────────────────────────────────────────────── + + +class WakeStartParams(Params): + """``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.""" + + surface: str | None = None + persist: bool | None = None + client_capture: bool | None = None + session_id: str | None = None # session the wake.detected event is addressed to + profile: str | None = None + + +class WakeStartResult(Result): + """``started: false`` carries ``reason`` (unavailable / disabled / disabled_for_surface / owned); + ``sample_rate`` / ``frame_length`` describe the PCM frames the armed detector expects.""" + + started: bool + reason: str | None = None + hint: str | None = None + phrase: str | None = None + provider: str | None = None + owner_surface: str | None = None + enabled_persisted: bool | None = None + capture: str | None = None + sample_rate: int | None = None + frame_length: int | None = None + + +method("wake.start", params=WakeStartParams, result=WakeStartResult, + doc="Arm the wake-word listener for the calling surface; refusals explain why.") + + +class WakeStopParams(Params): + persist: bool | None = None + profile: str | None = None + + +class WakeOwnerResult(Result): + """``methods_voice.py::_owner_result`` — ``reason: "not_owner"`` when the caller does not hold + the listener.""" + + reason: str | None = None + + +class WakeStopResult(WakeOwnerResult): + stopped: bool + disabled_persisted: bool + + +method("wake.stop", params=WakeStopParams, result=WakeStopResult, + doc="Stop this surface's listener; persist also writes wake_word.enabled: false.") + + +class WakeControlParams(Params): + profile: str | None = None + + +class WakePauseResult(WakeOwnerResult): + paused: bool + + +method("wake.pause", params=WakeControlParams, result=WakePauseResult, + doc="Release the mic (e.g. while the desktop's browser captures audio).") + + +class WakeResumeResult(WakeOwnerResult): + resumed: bool + + +method("wake.resume", params=WakeControlParams, result=WakeResumeResult, + doc="Reclaim the mic after a pause; no-op if the listener isn't armed.") + + +class WakeStatusParams(Params): + surface: str | None = None + client_capture: bool | None = None + profile: str | None = None + + +class WakeInputDevice(OpenModel): + """``tools/wake_word.py::_describe_input_device`` — PortAudio diagnostics for the configured mic.""" + + selector: int | str | None = None + name: str | None = None + error: str | None = None + max_input_channels: int | None = None + default_samplerate: float | None = None + hostapi_index: int | None = None + hostapi: str | None = None + + +class WakeStatusResult(Result): + """``enabled`` is config truth; ``listening`` is this caller's armed detector; ``audio_silent`` + means armed but deaf (see ``hint``).""" + + listening: bool + owned_by_caller: bool + owner_surface: str | None = None + phrase: str + provider: str + configured_surface: str + input_device: WakeInputDevice + available: bool + hint: str + enabled: bool + audio_silent: bool + capture: str + local_input_available: bool + sample_rate: int + frame_length: int + + +method("wake.status", params=WakeStatusParams, result=WakeStatusResult, + doc="Everything a client needs to draw the wake-word state and decide whether to (re)arm.") + + +class WakeFeedParams(Params): + """``pcm`` (or the ``pcm_b64`` alias): base64 int16 mono little-endian, 16 kHz only.""" + + pcm: str | None = None + pcm_b64: str | None = None + sample_rate: int | None = None + profile: str | None = None + + +class WakeFeedResult(WakeOwnerResult): + fed: bool # false with reason "empty" / "not_owner" + + +method("wake.feed", params=WakeFeedParams, result=WakeFeedResult, + doc="Push client-captured PCM into the armed detector (mic-less remote backends).") diff --git a/tui_gateway/contracts/sessions.py b/tui_gateway/contracts/sessions.py index c4ee836668..2a546fffdf 100644 --- a/tui_gateway/contracts/sessions.py +++ b/tui_gateway/contracts/sessions.py @@ -1 +1,680 @@ -"""Contracts: sessions (authored by the contract worker).""" +"""Session lifecycle contracts (``tui_gateway/methods_session.py``): create / resume / activate / +close, the live-session snapshot those share, history + compression + undo, mid-turn corrections, +listing/browsing stored rows, spawn-tree snapshots, event replay and the stateless one-shot LLM call. +""" + +from __future__ import annotations + +from pydantic import Field + +from .base import JsonValue, Params, Result, WireEnum +from .common import OpenModel, ProfileParams, SessionLiveInfo, SessionParams, TranscriptMessage, Usage +from .registry import method + + +# ── shared live-session snapshot ────────────────────────────────────────────────────────────── + + +class OpenRequestEntry(Result): + """One unanswered server→client request (``server_requests.Request.snapshot``); the reconnecting + client re-delivers it to its request handlers.""" + + id: str + method: str + params: dict[str, JsonValue] + + +class InflightTurn(Result): + """``session_auto_continue._inflight_snapshot``: the live (or retained failed) turn a reconnecting + client rebuilds its bubbles from.""" + + assistant: str = "" + streaming: bool = False + user: str = "" + corrections: list[str] | None = None + correction_offsets: list[int] | None = None + error: str | None = None + status: str | None = None + recoverable: bool | None = None + error_surface: dict[str, JsonValue] | None = None + + +class QueuedPrompt(Result): + user: str + + +class TodoState(Result): + """``tool_progress._normalize_todo_state``: the authoritative todo snapshot.""" + + todos: list[dict[str, JsonValue]] + revision: int + + +class AutoContinue(Result): + """A crash-interrupted turn was scheduled to continue right after this resume.""" + + attempt: int + interrupted_at: float + + +class PendingApproval(OpenModel): # TODO(common): twin of server_requests.ApprovalRequestParams minus session_id + """``server._approval_request_payload`` for the oldest unresolved approval (command redacted).""" + + request_id: str | None = None + command: str | None = None + description: str | None = None + choices: list[str] | None = None + allow_permanent: bool | None = None + allow_session: bool | None = None + smart_denied: bool | None = None + tool_name: str | None = None + + +class LiveSessionStatus(WireEnum): + idle = "idle" + starting = "starting" + waiting = "waiting" + working = "working" + streaming = "streaming" # lazy watch window whose child run is active + resuming = "resuming" # deferred hydration in flight + + +class LiveSessionSnapshot(Result): + """Union of ``server._live_session_payload``, ``methods_session._resume_response`` and the + live-unpersisted resume path; keys only some paths produce are optional.""" + + session_id: str + message_count: int + messages: list[TranscriptMessage] + info: SessionLiveInfo + stored_session_id: str | None = None + resumed: str | None = None + session_key: str | None = None + messages_omitted: bool | None = None + hydrating: bool | None = None + running: bool | None = None + turn_started_at: float | None = None + started_at: float | None = None + status: str | None = None # a LiveSessionStatus value + inflight: InflightTurn | None = None + queued: QueuedPrompt | None = None + pending_approval: PendingApproval | None = None + open_requests: list[OpenRequestEntry] | None = None + todo_state: TodoState | None = None + auto_continue: AutoContinue | None = None + + +# ── session.create ──────────────────────────────────────────────────────────────────────────── + + +class SeedMessage(Params): + """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.""" + + role: str + content: str | None = None + text: str | None = None + display_kind: str | None = None + + +class SessionCreateParams(ProfileParams): + cols: int | None = None + source: str | None = None + cwd: str | None = None + messages: list[SeedMessage] | None = None + parent_session_id: str | None = None + title: str | None = None + model: str | None = None + provider: str | None = None + reasoning_effort: str | None = None + fast: bool | None = None # presence is the contract: omitted inherits, true pins priority, false pins normal + close_on_disconnect: bool = False + hidden: bool = False + room_plumbing: bool = False + follow_profile_config: bool = False + + +class SessionCreateResult(Result): + session_id: str + stored_session_id: str + message_count: int + messages: list[TranscriptMessage] + info: SessionLiveInfo + + +method("session.create", params=SessionCreateParams, result=SessionCreateResult, + doc="Mint a live session (agent builds after the reply); a DB row appears on the first prompt unless seeded.") + + +# ── session.resume / activate ───────────────────────────────────────────────────────────────── + + +class SessionResumeParams(SessionParams): + """``session_id`` is the STORED id (or an exact title); the reply's ``session_id`` is the runtime id.""" + + cols: int | None = None + source: str | None = None + lazy: bool = False + defer_history: bool = False + omit_messages: bool = False + eager_build: bool = False + close_on_disconnect: bool = False + + +class SessionResumeResult(LiveSessionSnapshot): + pass + + +method("session.resume", params=SessionResumeParams, result=SessionResumeResult, + doc="Attach to a stored session: reuse it if live here, else lazy / deferred / cold / eager rebuild.") + + +class SessionActivateParams(SessionParams): + cols: int | None = None # sent by the desktop; the handler keeps the session's current width + omit_messages: bool = False + + +class SessionActivateResult(LiveSessionSnapshot): + pass + + +method("session.activate", params=SessionActivateParams, result=SessionActivateResult, + doc="Attach the frontend to a live session without closing the previously focused one.") + + +# ── listing ─────────────────────────────────────────────────────────────────────────────────── + + +class SessionListParams(ProfileParams): + title: str | None = None # exact-title lookup (title as identity); windowless + limit: int | None = None + include_hidden: bool = False + + +class SessionListRow(Result): + """``methods_session._session_row_summary``; ``resolved_id`` only on a title lookup that followed a + compression lineage to its tip.""" + + id: str + resolved_id: str | None = None + title: str = "" + preview: str = "" + started_at: float = 0 + message_count: int = 0 + source: str = "" + + +class SessionListResult(Result): + sessions: list[SessionListRow] + + +method("session.list", params=SessionListParams, result=SessionListResult, + doc="Human-facing stored sessions, most recent first (sub-agent / kanban sources denied).") + + +class SessionMostRecentParams(ProfileParams): + pass + + +class SessionMostRecentResult(Result): + session_id: str | None + title: str | None = None + started_at: float | None = None + source: str | None = None + + +method("session.most_recent", params=SessionMostRecentParams, result=SessionMostRecentResult, + doc="Most recent human-facing session; errors fold into a null session_id.") + + +class SessionActiveListParams(ProfileParams): + current_session_id: str | None = None + + +class SessionActiveItem(Result): + """``server._session_live_item``.""" + + current: bool + id: str + last_active: float + message_count: int + model: str + preview: str + session_key: str + started_at: float + status: LiveSessionStatus + title: str + + +class SessionActiveListResult(Result): + sessions: list[SessionActiveItem] + + +method("session.active_list", params=SessionActiveListParams, result=SessionActiveListResult, + doc="Live sessions in this process, insertion order (not a DB browser).") + + +# ── stored-row mutation ─────────────────────────────────────────────────────────────────────── + + +class SessionDeleteParams(SessionParams): + """``session_id`` is the STORED id.""" + + +class SessionDeleteResult(Result): + deleted: str + + +method("session.delete", params=SessionDeleteParams, result=SessionDeleteResult, + doc="Delete a stored session + transcripts; refused while it is live here.") + + +class SessionTitleParams(SessionParams): + title: str | None = None # absent: read; present: set (non-empty) + + +class SessionTitleResult(Result): + title: str + session_key: str | None = None + pending: bool | None = None # True: no row yet, applied on the first turn + + +method("session.title", params=SessionTitleParams, result=SessionTitleResult, + doc="Read or set a live session's title; a title set before the row exists is queued.") + + +class SessionSetHiddenParams(Params): + """``session_id`` is a live runtime id first, else a stored id / key / title.""" + + session_id: str + hidden: bool = True + profile: str | None = None + + +class SessionSetHiddenResult(Result): + hidden: bool + session_key: str + + +method("session.set_hidden", params=SessionSetHiddenParams, result=SessionSetHiddenResult, + doc="Set/clear hidden (out of the default list, still resumable by its owner) on a session + lineage.") + + +class SessionWorkspaceMoveParams(ProfileParams): + session_key: str + cwd: str + + +class SessionWorkspaceMoveResult(Result): + cwd: str + branch: str | None = None + git_repo_root: str | None = None + + +method("session.workspace.move", params=SessionWorkspaceMoveParams, result=SessionWorkspaceMoveResult, + doc="Re-home a stored session's workspace; git identity is replaced and a live agent follows.") + + +class SessionCwdSetParams(SessionParams): + cwd: str + + +class SessionCwdSetResult(SessionLiveInfo): + """The refreshed ``session.info`` view (full agent view, or the lazy shape).""" + + +method("session.cwd.set", params=SessionCwdSetParams, result=SessionCwdSetResult, + doc="Change a live, idle session's working directory.") + + +# ── live-session lifecycle ──────────────────────────────────────────────────────────────────── + + +class SessionCloseParams(SessionParams): + pass + + +class SessionCloseResult(Result): + closed: bool # False when the runtime id was already gone + + +method("session.close", params=SessionCloseParams, result=SessionCloseResult, + doc="Tear down a live session (its stored row stays resumable).") + + +class SessionBranchParams(SessionParams): + name: str | None = None + count: int | None = None # keep only the first N rows of the source history + + +class SessionBranchResult(Result): + session_id: str + stored_session_id: str + title: str + parent: str + message_count: int + messages: list[TranscriptMessage] + info: SessionLiveInfo + + +method("session.branch", params=SessionBranchParams, result=SessionBranchResult, + doc="Fork a live session into a new stored child that shares the parent's history so far.") + + +class SessionUndoParams(SessionParams): + pass + + +class SessionUndoResult(Result): + removed: int + + +method("session.undo", params=SessionUndoParams, result=SessionUndoResult, + doc="Drop the last user turn (and everything after it) from an idle session.") + + +class SessionSaveParams(SessionParams): + pass + + +class SessionSaveResult(Result): + """Under turn isolation the compute host's result passes through verbatim.""" + + file: str | None = None + model_config = Result.model_config | {"extra": "allow"} + + +method("session.save", params=SessionSaveParams, result=SessionSaveResult, + doc="Export the transcript to ~/.hermes/sessions/saved (classic /save).") + + +class SessionStatusParams(SessionParams): + pass + + +class SessionStatusResult(Result): + output: str + + +method("session.status", params=SessionStatusParams, result=SessionStatusResult, + doc="Rendered /status text for the session.") + + +class SessionHistoryParams(SessionParams): + pass + + +class SessionHistoryResult(Result): + count: int + messages: list[TranscriptMessage] + + +method("session.history", params=SessionHistoryParams, result=SessionHistoryResult, + doc="The durable display transcript (ancestors included, row ids attached).") + + +class SessionUsageParams(SessionParams): + pass + + +class SessionUsageResult(Usage): + credits_lines: list[str] | None = None + + +method("session.usage", params=SessionUsageParams, result=SessionUsageResult, + doc="Token / context / cost counters for the session (+ Nous credit lines when available).") + + +class SessionContextBreakdownParams(SessionParams): + pass + + +class ContextCategory(Result): + color: str + id: str + label: str + tokens: int + + +class SessionContextBreakdownResult(Result): + """``agent.context_breakdown.compute_session_context_breakdown`` (empty categories before the agent builds).""" + + categories: list[ContextCategory] + context_max: int + context_percent: int + context_used: int + estimated_total: int + context_estimated: bool + context_source: str + model: str + + +method("session.context_breakdown", params=SessionContextBreakdownParams, result=SessionContextBreakdownResult, + doc="Cursor-style split of the context window by category.") + + +# ── compression ─────────────────────────────────────────────────────────────────────────────── + + +class CompressionSummary(OpenModel): + """``agent.manual_compression_feedback.summarize_manual_compression``.""" + + noop: bool = False + aborted: bool = False + refused_would_grow: bool | None = None + fallback_used: bool | None = None + headline: str = "" + token_line: str = "" + note: str | None = None + + +class SessionCompressParams(SessionParams): + focus_topic: str | None = None + + +class SessionCompressResult(Result): + """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``.""" + + status: str | None = None # compressed | aborted | pending + removed: int | None = None + before_messages: int | None = None + after_messages: int | None = None + before_tokens: int | None = None + after_tokens: int | None = None + summary: CompressionSummary | None = None + usage: Usage | None = None + info: SessionLiveInfo | None = None + messages: list[TranscriptMessage] | None = None + compressed: bool | None = None + lock_held: bool | None = None + message: str | None = None + turn_isolation: bool | None = None + host_ack: dict[str, JsonValue] | None = None + model_config = Result.model_config | {"extra": "allow"} + + +method("session.compress", params=SessionCompressParams, result=SessionCompressResult, + doc="Manual /compress of an idle session, optionally focused on a topic.") + + +# ── interrupt / steer / redirect ────────────────────────────────────────────────────────────── + + +class SessionInterruptParams(SessionParams): + expected_hosted_task_id: str | None = None # only interrupt if this hosted task is the running one + + +class InterruptStatus(WireEnum): + interrupted = "interrupted" + not_interrupted = "not_interrupted" + + +class SessionInterruptResult(Result): + status: InterruptStatus + interrupted: bool | None = None + turn_isolation: bool | None = None + + +method("session.interrupt", params=SessionInterruptParams, result=SessionInterruptResult, + doc="Stop the running turn (and streaming TTS); retires the crash-recovery marker.") + + +class CorrectionStatus(WireEnum): + queued = "queued" + redirected = "redirected" + rejected = "rejected" + + +class SessionCorrectionParams(SessionParams): + text: str + + +class SessionCorrectionResult(Result): + status: CorrectionStatus + text: str + + +method("session.steer", params=SessionCorrectionParams, result=SessionCorrectionResult, + doc="Inject text into the next tool result without interrupting the turn.") +method("session.redirect", params=SessionCorrectionParams, result=SessionCorrectionResult, + doc="Redirect the active turn (queued for the next turn while the agent is still building).") + + +# ── spawn trees ─────────────────────────────────────────────────────────────────────────────── + + +class SpawnTreeSaveParams(ProfileParams): + subagents: list[dict[str, JsonValue]] + session_id: str | None = None # stored key; "default" when absent + started_at: float | None = None + finished_at: float | None = None + label: str | None = None + + +class SpawnTreeSaveResult(Result): + path: str + session_id: str + + +method("spawn_tree.save", params=SpawnTreeSaveParams, result=SpawnTreeSaveResult, + doc="Persist a finished delegation tree snapshot under the session's spawn-trees dir.") + + +class SpawnTreeListParams(ProfileParams): + session_id: str | None = None + cross_session: bool = False + limit: int | None = None + + +class SpawnTreeEntry(OpenModel): + """Index row (``server._append_spawn_tree_index``) or a legacy file scan.""" + + path: str + session_id: str | None = None + started_at: float | None = None + finished_at: float | None = None + label: str = "" + count: int = 0 + + +class SpawnTreeListResult(Result): + entries: list[SpawnTreeEntry] + + +method("spawn_tree.list", params=SpawnTreeListParams, result=SpawnTreeListResult, + doc="Saved spawn-tree snapshots, newest first.") + + +class SpawnTreeLoadParams(ProfileParams): + path: str + + +class SpawnTreeLoadResult(Result): + """The snapshot file as written by ``spawn_tree.save`` (open: the file is the contract).""" + + session_id: str | None = None + started_at: float | None = None + finished_at: float | None = None + label: str | None = None + subagents: list[dict[str, JsonValue]] = Field(default_factory=list) + model_config = Result.model_config | {"extra": "allow"} + + +method("spawn_tree.load", params=SpawnTreeLoadParams, result=SpawnTreeLoadResult, + doc="Read one saved spawn-tree snapshot (path must be under the spawn-trees root).") + + +# ── terminal / event replay ─────────────────────────────────────────────────────────────────── + + +class TerminalResizeParams(SessionParams): + cols: int | None = None + + +class TerminalResizeResult(Result): + cols: int + + +method("terminal.resize", params=TerminalResizeParams, result=TerminalResizeResult, + doc="Record the client's column width for server-side rendering.") + + +class SessionEventsSinceParams(SessionParams): + last_seen: int | None = None + + +class SessionEventsSinceResult(Result): + events: list[dict[str, JsonValue]] # recorded event frames' ``params`` objects + latest_seq: int + truncated: bool + count: int + epoch: str + open_requests: list[OpenRequestEntry] + + +method("session.events.since", params=SessionEventsSinceParams, result=SessionEventsSinceResult, + doc="Replay events after a seq watermark on WS reconnect; truncated means refetch state.") + + +class SessionEventsStatsParams(ProfileParams): + pass + + +class SessionEventsStatsResult(Result): + """``event_replay.replay_stats``.""" + + sessions: int + events: int + bytes: int + max_per_session: int + max_bytes_per_session: int + max_bytes_process: int + + +method("session.events.stats", params=SessionEventsStatsParams, result=SessionEventsStatsResult, + doc="Replay-buffer occupancy telemetry (ops/debug).") + + +# ── one-shot LLM ────────────────────────────────────────────────────────────────────────────── + + +class LlmOneshotParams(ProfileParams): + """Needs a ``template`` or ``instructions`` / ``input``; a live ``session_id`` lends its model.""" + + template: str | None = None + instructions: str | None = None + input: str | None = None + variables: dict[str, JsonValue] | None = None + task: str | None = None + temperature: float | None = None + max_tokens: int | None = None + session_id: str | None = None + + +class LlmOneshotResult(Result): + text: str + + +method("llm.oneshot", params=LlmOneshotParams, result=LlmOneshotResult, + doc="Stateless one-shot LLM completion (titles, ideas) on the session's or the task backend.") diff --git a/tui_gateway/contracts/tools_commands.py b/tui_gateway/contracts/tools_commands.py index 6e72f0a99b..5e636f1b09 100644 --- a/tui_gateway/contracts/tools_commands.py +++ b/tui_gateway/contracts/tools_commands.py @@ -1 +1,530 @@ -"""Contracts: tools_commands (authored by the contract worker).""" +"""Contracts: system / process / slash-command / rollback / cron / browser / config RPCs +(handlers in ``tui_gateway/methods_tools.py``, browser helpers in ``methods_browser.py``). + +Several results here are pass-throughs of dicts another module owns (``tools/process_registry.py``, +``tools/checkpoint_manager.py``, ``tools/cronjob_tools.py``): those declare every key the producer is +known to emit plus ``extra="allow"`` so a new upstream key never trips the strict gate. +""" + +from __future__ import annotations + +from pydantic import Field + +from .base import JsonValue, Params, Result, WireEnum +from .registry import method + + +class _Open(Result): + """A pass-through row whose closed set is owned by another module.""" + + model_config = Result.model_config | {"extra": "allow"} + + +# ── system.battery ──────────────────────────────────────────────────────────────────────────── + + +class BatteryCategory(WireEnum): + """``agent/battery.py::battery_category`` colour bucket.""" + + good = "good" + warn = "warn" + bad = "bad" + critical = "critical" + dim = "dim" + + +class SystemBatteryParams(Params): + profile: str | None = None + + +class SystemBatteryResult(Result): + available: bool + percent: int | None = None + plugged: bool | None = None + category: BatteryCategory = BatteryCategory.dim + + +method("system.battery", params=SystemBatteryParams, result=SystemBatteryResult, + doc="Host battery for the status bar; always resolves, ``available: false`` when unreadable.") + + +# ── process.* / agents.list ─────────────────────────────────────────────────────────────────── + + +class ProcessStopParams(Params): + session_id: str | None = None + profile: str | None = None + + +class ProcessStopResult(Result): + killed: int + + +method("process.stop", params=ProcessStopParams, result=ProcessStopResult, + doc="Kill every background process in the registry (``/stop``), answering the count killed.") + + +class AgentsListParams(Params): + profile: str | None = None + + +class AgentProcessRow(Result): + session_id: str + command: str + status: str + uptime: int + + +class AgentsListResult(Result): + processes: list[AgentProcessRow] = Field(default_factory=list) + + +method("agents.list", params=AgentsListParams, result=AgentsListResult, + doc="Registry-wide background process summary for ``/agents``.") + + +class ProcessListParams(Params): + session_id: str + profile: str | None = None + + +class ProcessEntry(_Open): + """``tools/process_registry.py::list_sessions`` row plus the gateway's ``output_tail``.""" + + session_id: str + command: str = "" + cwd: str | None = None + pid: int | None = None + owner_task_id: str | None = None + started_at: str | None = None + uptime_seconds: int | None = None + status: str = "running" + output_preview: str = "" + output_tail: str | None = None + session_scoped: bool | None = None + watch_patterns: list[str] | None = None + watch_hit: bool | None = None + notify_on_complete: bool | None = None + exit_code: int | None = None + detached: bool | None = None + + +class ProcessListResult(Result): + processes: list[ProcessEntry] = Field(default_factory=list) + + +method("process.list", params=ProcessListParams, result=ProcessListResult, + doc="Background processes owned by the caller's session (desktop status stack poll).") + + +class ProcessKillParams(Params): + session_id: str + process_id: str + profile: str | None = None + + +class ProcessKillStatus(WireEnum): + killed = "killed" + already_exited = "already_exited" + not_found = "not_found" + error = "error" + + +class ProcessKillResult(_Open): + """``tools/process_registry.py::kill_process`` snapshot; ``error`` rides on the failure statuses.""" + + status: ProcessKillStatus + session_id: str | None = None + command: str | None = None + exit_code: int | None = None + completion_reason: str | None = None + termination_source: str | None = None + output: str | None = None + error: str | None = None + + +method("process.kill", params=ProcessKillParams, result=ProcessKillResult, + doc="Kill one background process the caller's session owns and return its output snapshot.") + + +# ── shell.exec / cli.exec ───────────────────────────────────────────────────────────────────── + + +class ShellExecParams(Params): + command: str + profile: str | None = None + + +class ShellExecResult(Result): + stdout: str + stderr: str + code: int + + +method("shell.exec", params=ShellExecParams, result=ShellExecResult, + doc="Run a safe (non-dangerous) shell command captured for ``!cmd`` / inline substitution.") + + +class CliExecParams(Params): + argv: list[str] + timeout: int | None = None + profile: str | None = None + + +class CliExecResult(Result): + blocked: bool + code: int + output: str + hint: str | None = None + + +method("cli.exec", params=CliExecParams, result=CliExecResult, + doc="Run ``hermes `` non-interactively and capture its output; ``blocked`` explains a refusal.") + + +# ── command catalog / resolve / dispatch / slash.exec ───────────────────────────────────────── + + +class CommandsCatalogParams(Params): + session_id: str | None = None + profile: str | None = None + + +class ArgumentMode(WireEnum): + options = "options" + text = "text" + mixed = "mixed" + + +class CommandCatalogMeta(Result): + argument_mode: ArgumentMode | None = None + desktop: str | None = None + + +class CommandCategory(Result): + name: str + pairs: list[list[str]] = Field(default_factory=list) + + +class SkillCatalogEntry(Result): + usage: int = 0 + origin: str = "local" + + +class CommandsCatalogResult(Result): + pairs: list[list[str]] = Field(default_factory=list) + sub: dict[str, list[str]] = Field(default_factory=dict) + canon: dict[str, str] = Field(default_factory=dict) + commands: dict[str, CommandCatalogMeta] = Field(default_factory=dict) + categories: list[CommandCategory] = Field(default_factory=list) + skills: dict[str, SkillCatalogEntry] = Field(default_factory=dict) + skill_count: int = 0 + warning: str = "" + + +method("commands.catalog", params=CommandsCatalogParams, result=CommandsCatalogResult, + doc="Categorized slash metadata (registry, quick, plugin, skill) for completion menus.") + + +class CommandResolveParams(Params): + name: str | None = None + profile: str | None = None + + +class CommandResolveResult(Result): + canonical: str + description: str + category: str + + +method("command.resolve", params=CommandResolveParams, result=CommandResolveResult, + doc="Canonical registry command for a name or alias.") + + +class DispatchType(WireEnum): + """``apps/shared/src/slash.ts::parseCommandDispatch`` branches on this.""" + + exec = "exec" + alias = "alias" + plugin = "plugin" + send = "send" + skill = "skill" + prefill = "prefill" + + +class CommandDispatchParams(Params): + name: str + arg: str | None = None + session_id: str | None = None + profile: str | None = None + + +class CommandDispatchResult(Result): + """One structured directive: ``exec``/``plugin`` carry ``output``; ``alias`` a ``target``; + ``send``/``prefill``/``skill`` a ``message`` (UIs render ``display``, never ``message``).""" + + type: DispatchType + output: str | None = None + target: str | None = None + message: str | None = None + notice: str | None = None + display: str | None = None + name: str | None = None + status: str | None = None + + +method("command.dispatch", params=CommandDispatchParams, result=CommandDispatchResult, + doc="Run a quick/plugin/bundle/skill/built-in slash command and answer a structured directive.") + + +class SlashExecParams(Params): + session_id: str + command: str + profile: str | None = None + + +class SlashExecResult(Result): + """Plain worker/plugin text in ``output`` (+ ``warning``), or — when the command was rerouted to + ``command.dispatch`` — that method's directive fields with ``type`` set.""" + + output: str | None = None + warning: str | None = None + type: DispatchType | None = None + target: str | None = None + message: str | None = None + notice: str | None = None + display: str | None = None + name: str | None = None + status: str | None = None + + +method("slash.exec", params=SlashExecParams, result=SlashExecResult, + doc="Execute a slash command against the session's slash worker (or a live/plugin shortcut).") + + +# ── insights.get / config.show ──────────────────────────────────────────────────────────────── + + +class InsightsGetParams(Params): + days: int | None = None + profile: str | None = None + + +class InsightsGetResult(Result): + days: int + sessions: int + messages: int + + +method("insights.get", params=InsightsGetParams, result=InsightsGetResult, + doc="Session/message counts over the last ``days`` for the (optionally scoped) profile store.") + + +class ConfigShowParams(Params): + profile: str | None = None + + +class ConfigSection(Result): + title: str + rows: list[list[str]] = Field(default_factory=list) + + +class ConfigShowResult(Result): + model_config = Result.model_config | {"extra": "allow"} + + sections: list[ConfigSection] = Field(default_factory=list) + + +method("config.show", params=ConfigShowParams, result=ConfigShowResult, + doc="Masked, display-ready config summary (model / agent / environment rows).") + + +# ── rollback.* ──────────────────────────────────────────────────────────────────────────────── + + +class RollbackListParams(Params): + session_id: str + profile: str | None = None + + +class RollbackCheckpoint(Result): + hash: str = "" + timestamp: str = "" + message: str = "" + + +class RollbackListResult(Result): + enabled: bool + checkpoints: list[RollbackCheckpoint] = Field(default_factory=list) + + +method("rollback.list", params=RollbackListParams, result=RollbackListResult, + doc="Checkpoints for the session's cwd; ``enabled: false`` when checkpointing is off.") + + +class RollbackRestoreParams(Params): + session_id: str + hash: str + file_path: str | None = None + profile: str | None = None + + +class RollbackRestoreResult(_Open): + """``tools/checkpoint_manager.py::restore`` outcome; ``history_removed`` is added for a full + (non-file) restore that also rewound the live transcript.""" + + success: bool + restored_to: str | None = None + reason: str | None = None + directory: str | None = None + file: str | None = None + restored_files: list[str] | None = None + skipped_user_edits: list[str] | None = None + skipped_oversize: list[str] | None = None + failed_deletes: list[str] | None = None + history_removed: int | None = None + error: str | None = None + debug: JsonValue | None = None + + +method("rollback.restore", params=RollbackRestoreParams, result=RollbackRestoreResult, + doc="Restore the working tree (or one file) to a checkpoint by hash or 1-based index.") + + +class RollbackDiffParams(Params): + session_id: str + hash: str + profile: str | None = None + + +class RollbackDiffResult(Result): + stat: str = "" + diff: str = "" + rendered: str | None = None + + +method("rollback.diff", params=RollbackDiffParams, result=RollbackDiffResult, + doc="Diff between a checkpoint and the working tree, with an ANSI rendering sized to the TUI.") + + +# ── cron.manage ─────────────────────────────────────────────────────────────────────────────── + + +class CronAction(WireEnum): + list = "list" + add = "add" + remove = "remove" + pause = "pause" + resume = "resume" + + +class CronManageParams(Params): + action: CronAction = CronAction.list + name: str | None = None + include_disabled: bool | str | None = None + schedule: str | None = None + prompt: str | None = None + repeat: int | str | None = None + continuity: bool | str | None = None + deliver: str | None = None + profile: str | None = None + + +class CronJobRow(_Open): + """``tools/cronjob_job_args.py::_format_job``.""" + + job_id: str + name: str = "" + skill: str | None = None + skills: list[str] = Field(default_factory=list) + prompt_preview: str = "" + model: str | None = None + provider: str | None = None + base_url: str | None = None + schedule: str = "?" + repeat: int | str | None = None + deliver: str | None = None + next_run_at: str | None = None + last_run_at: str | None = None + last_status: str | None = None + last_delivery_error: str | None = None + last_delivery_unverified: bool | None = None + last_fire_error: str | None = None + last_error: str | None = None + enabled: bool = True + state: str | None = None + paused_at: str | None = None + paused_reason: str | None = None + workdir: str | None = None + script: str | None = None + reasoning_effort: str | None = None + monitor_script: str | None = None + monitor_url: str | None = None + monitor_state: JsonValue | None = None + no_agent: bool | None = None + enabled_toolsets: list[str] | None = None + continuity: bool | None = None + context_from: list[str] | None = None + attach_to_session: bool | None = None + + +class CronRemovedJob(Result): + id: str + name: str = "" + schedule: str | None = None + + +class CronManageResult(_Open): + """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``.""" + + success: bool | None = None + error: str | None = None + count: int | None = None + jobs: list[CronJobRow] | None = None + scoped: str | None = None + gateway_running: bool | None = None + warning: str | None = None + job_id: str | None = None + name: str | None = None + skill: str | None = None + skills: list[str] | None = None + schedule: str | None = None + repeat: int | str | None = None + deliver: str | None = None + next_run_at: str | None = None + job: CronJobRow | None = None + message: str | None = None + guidance: JsonValue | None = None + removed_job: CronRemovedJob | None = None + + +method("cron.manage", params=CronManageParams, result=CronManageResult, + doc="List/add/remove/pause/resume cron jobs in the (optionally profile-scoped) cron store.") + + +# ── browser.manage ──────────────────────────────────────────────────────────────────────────── + + +class BrowserAction(WireEnum): + status = "status" + connect = "connect" + disconnect = "disconnect" + + +class BrowserManageParams(Params): + action: BrowserAction = BrowserAction.status + url: str | None = None + session_id: str | None = None + profile: str | None = None + + +class BrowserManageResult(Result): + connected: bool + url: str | None = None + messages: list[str] | None = None + + +method("browser.manage", params=BrowserManageParams, result=BrowserManageResult, + doc="Inspect, attach to, or drop the CDP browser the tools use; ``messages`` narrate a connect.") diff --git a/tui_gateway/contracts/tools_mcp_plugins.py b/tui_gateway/contracts/tools_mcp_plugins.py index fa8f4f4f73..e648867f89 100644 --- a/tui_gateway/contracts/tools_mcp_plugins.py +++ b/tui_gateway/contracts/tools_mcp_plugins.py @@ -1 +1,629 @@ -"""Contracts: tools_mcp_plugins (authored by the contract worker).""" +"""Tools / toolsets / MCP servers / plugins / skills / learning graph / reload contracts +(``tui_gateway/methods_tools.py``). + +Every ``mcp.servers.*``, ``mcp.catalog``, ``skills.manage`` and ``plugins.manage`` handler runs under +``_profile_scoped_rpc`` and the desktop routes them via ``requestGatewayForProfile`` / +``requestForBot``, so all of them accept the optional ``profile`` key. +""" + +from __future__ import annotations + +from pydantic import Field + +from .base import JsonValue, Params, Result, WireEnum +from .common import OpenModel, ProfileParams, SessionLiveInfo +from .registry import method + + +class _SessionScoped(Params): + """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.""" + + session_id: str | None = None + + +# ── tools / toolsets ────────────────────────────────────────────────────────────────────────── + + +class ToolsetRow(Result): + """One row of ``methods_tools._toolset_rows``; ``tools`` only when the caller asked for them + (``tools.list``).""" + + name: str + description: str + tool_count: int + enabled: bool + tools: list[str] | None = None + + +class ToolsetsListResult(Result): + toolsets: list[ToolsetRow] + + +method("tools.list", params=_SessionScoped, result=ToolsetsListResult, + doc="Every toolset with its resolved tool names, flagged against the session's (or config's) enabled set.") + +method("toolsets.list", params=_SessionScoped, result=ToolsetsListResult, + doc="Toolset summaries (no tool names) for the desktop Toolsets tab.") + + +class ToolShowRow(Result): + name: str + description: str + + +class ToolShowSection(Result): + name: str + tools: list[ToolShowRow] + + +class ToolsShowResult(Result): + sections: list[ToolShowSection] + total: int + + +method("tools.show", params=_SessionScoped, result=ToolsShowResult, + doc="The /tools listing grouped by toolset, including tools deferred behind the tool_search bridge.") + + +class ToolsAction(WireEnum): + enable = "enable" + disable = "disable" + + +class ToolsConfigureParams(Params): + """``names`` are toolset keys or ``server:tool`` MCP targets; with ``session_id`` the live session's + profile is authoritative and its agent is rebuilt.""" + + action: ToolsAction + names: list[str] + session_id: str | None = None + profile: str | None = None + + +class ToolsConfigureResult(Result): + changed: list[str] + enabled_toolsets: list[str] + info: SessionLiveInfo | None = None + missing_servers: list[str] + reset: bool + unknown: list[str] + + +method("tools.configure", params=ToolsConfigureParams, result=ToolsConfigureResult, + doc="Persist a toolset / MCP enable-disable change and rebuild the session agent so it takes effect now.") + + +# ── reload ──────────────────────────────────────────────────────────────────────────────────── + + +class ReloadEnvParams(Params): + pass + + +class ReloadEnvResult(Result): + updated: int + + +method("reload.env", params=ReloadEnvParams, result=ReloadEnvResult, + doc="Re-read ~/.hermes/.env (CLI /reload parity); built agents keep their pool until /new.") + + +class ReloadMcpParams(Params): + """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).""" + + session_id: str | None = None + confirm: bool = False + always: bool = False + rev: str | None = None + + +class ReloadMcpStatus(WireEnum): + confirm_required = "confirm_required" + reloaded = "reloaded" + + +class ReloadMcpResult(Result): + status: ReloadMcpStatus + message: str | None = None + loaded_rev: str | None = None + coalesced: bool | None = None + turn_isolation: bool | None = None + host_ack: JsonValue | None = None + + +method("reload.mcp", params=ReloadMcpParams, result=ReloadMcpResult, + doc="Tear down and rediscover MCP servers for every live session (prompt cache is invalidated).") + + +# ── skills ──────────────────────────────────────────────────────────────────────────────────── + + +class SkillsAction(WireEnum): + list = "list" + search = "search" + install = "install" + browse = "browse" + inspect = "inspect" + + +class SkillsManageParams(ProfileParams): + """``query`` is the search text / hub identifier / browse page (digits); ``page`` / ``page_size`` + apply to ``browse``.""" + + action: SkillsAction = SkillsAction.list + query: str | None = None + page: int | None = None + page_size: int | None = None + + +class SkillHubHit(Result): + name: str + description: str + + +class SkillBrowseItem(OpenModel): + """``hermes_cli.skills_hub.browse_skills`` row.""" + + name: str = "" + description: str = "" + source: str = "" + trust: str | None = None + identifier: str | None = None + + +class SkillInspectInfo(OpenModel): + """``hermes_cli.skills_hub.inspect_skill``; ``{}`` when the identifier resolves nowhere.""" + + name: str | None = None + description: str | None = None + source: str | None = None + identifier: str | None = None + tags: list[str] | None = None + skill_md_preview: str | None = None + + +class SkillsManageResult(Result): + """Shape follows the action: ``list`` → ``skills`` (category → names); ``search`` → ``results``; + ``install`` → ``installed`` + ``name``; ``browse`` → ``items`` + paging; ``inspect`` → ``info``.""" + + skills: dict[str, list[str]] | None = None + results: list[SkillHubHit] | None = None + installed: bool | None = None + name: str | None = None + items: list[SkillBrowseItem] | None = None + page: int | None = None + total_pages: int | None = None + total: int | None = None + info: SkillInspectInfo | None = None + + +method("skills.manage", params=SkillsManageParams, result=SkillsManageResult, + doc="Skills hub backend: list the profile's skills or search / browse / inspect / install from the hub.") + + +class SkillsReloadParams(Params): + pass + + +class SkillCommandRef(Result): + name: str + description: str = "" + + +class SkillsReloadDiff(OpenModel): + """``agent.skill_commands.reload_skills``.""" + + added: list[SkillCommandRef] = Field(default_factory=list) + removed: list[SkillCommandRef] = Field(default_factory=list) + unchanged: list[str] = Field(default_factory=list) + total: int = 0 + commands: int = 0 + + +class SkillsReloadResult(Result): + output: str + result: SkillsReloadDiff + + +method("skills.reload", params=SkillsReloadParams, result=SkillsReloadResult, + doc="Re-scan skill dirs; the pre-rendered ``output`` is what /reload-skills prints.") + + +# ── learning graph (/journey) ───────────────────────────────────────────────────────────────── + + +class LearningFramesParams(Params): + cols: int | None = None + rows: int | None = None + frames: int | None = None + + +class LearningFrame(Result): + """``agent.learning_graph_render.render_graph`` projection; ``grid`` rows are lists of + ``[text, styleKey, alpha?, hexOverride?]`` runs.""" + + reveal: float + date: str + visible: int + grid: list[list[JsonValue]] + labels: list[dict[str, JsonValue]] = Field(default_factory=list) + + +class LearningLegendItem(Result): + glyph: str + label: str + style: str | None = None + color: str | None = None + + +class LearningNodeRow(Result): + id: str + glyph: str + label: str + fullLabel: str # noqa: N815 — wire key from learning_graph_render._bucket_rows + meta: str + body: str + style: str + + +class LearningBucketRow(Result): + index: int + label: str + date: str + skills: int + memories: int + total: int + category: str | None = None + color: str | None = None + nodes: list[LearningNodeRow] + + +class LearningAxis(Result): + start: str + end: str + + +class LearningFramesResult(Result): + frames: list[LearningFrame] + legend: list[LearningLegendItem] + categories: list[LearningLegendItem] + buckets: list[LearningBucketRow] + summary: list[str] + axis: LearningAxis + count: int + cols: int + rows: int + + +method("learning.frames", params=LearningFramesParams, result=LearningFramesResult, + doc="Pre-render the /journey timeline (frames + legend/summary) so the TUI walks it locally.") + + +class LearningNodeParams(Params): + id: str | None = None + + +class LearningEditParams(LearningNodeParams): + content: str | None = None + + +class LearningMutationResult(Result): + """``agent.learning_mutations`` — ``ok: false`` carries the reason in ``message``.""" + + ok: bool + message: str | None = None + + +class LearningDetailResult(LearningMutationResult): + kind: str | None = None + id: str | None = None + label: str | None = None + content: str | None = None + + +method("learning.detail", params=LearningNodeParams, result=LearningDetailResult, + doc="Node content (SKILL.md or memory chunk) for an edit prefill.") + +method("learning.delete", params=LearningNodeParams, result=LearningMutationResult, + doc="Archive a skill (restorable via curator) or remove a memory chunk.") + +method("learning.edit", params=LearningEditParams, result=LearningMutationResult, + doc="Rewrite a node's content (SKILL.md or memory chunk).") + + +# ── MCP catalog + per-profile server lifecycle ──────────────────────────────────────────────── + + +class McpCatalogEntry(Result): + name: str + description: str + installed: bool + enabled: bool + requires: list[str] + transport: str + + +class McpCatalogResult(Result): + servers: list[McpCatalogEntry] + + +method("mcp.catalog", params=ProfileParams, result=McpCatalogResult, + doc="Curated MCP presets with per-profile installed/enabled state and the env keys each needs.") + + +class McpServerSummary(Result): + """``tui_gateway/mcp_rpc_helpers.summarize_server`` — a server's config without secret values.""" + + name: str + transport: str + url: str | None = None + command: str | None = None + args: list[str] + env: list[str] + auth: str | None = None + oauth_tokens_present: bool | None = None + enabled: bool + tools: JsonValue | None = None + + +class McpServersListResult(Result): + servers: list[McpServerSummary] + + +method("mcp.servers.list", params=ProfileParams, result=McpServersListResult, + doc="Configured MCP servers for the (scoped) profile, secrets redacted to env-key names.") + + +class McpRuntimeStatus(WireEnum): + connected = "connected" + disabled = "disabled" + connecting = "connecting" + failed = "failed" + configured = "configured" + + +class McpServerRuntimeRow(Result): + """Safe projection of ``tools.mcp_tool_discovery.get_mcp_status`` rows.""" + + name: str + transport: str + tools: int + connected: bool + disabled: bool + status: McpRuntimeStatus + + +class McpServersStatusResult(Result): + servers: list[McpServerRuntimeRow] + checked_at: int + + +method("mcp.servers.status", params=ProfileParams, result=McpServersStatusResult, + doc="Cached runtime state per configured server; never connects, probes, or starts auth.") + + +class McpServerNameParams(ProfileParams): + name: str + + +class McpServersAddParams(McpServerNameParams): + """``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.""" + + preset: str | None = None + config: dict[str, JsonValue] | None = None + bearer_token: str | None = None + + +class McpServersAddResult(Result): + ok: bool + name: str + server: McpServerSummary + + +method("mcp.servers.add", params=McpServersAddParams, result=McpServersAddResult, + doc="Add a server to the profile's config from a catalog preset and/or an explicit config.") + + +class McpServersSetApiKeyParams(McpServerNameParams): + value: str + env_var: str | None = None + + +class McpServersSetApiKeyResult(Result): + ok: bool + name: str + env_var: str + server: McpServerSummary + + +method("mcp.servers.set_api_key", params=McpServersSetApiKeyParams, result=McpServersSetApiKeyResult, + doc="Store a credential in the profile's .env and reference it from the server config (header or env).") + + +class McpProbeTool(Result): + name: str + description: str + + +class McpServersTestResult(Result): + """``ok: false`` carries ``error``; ``prompts`` / ``resources`` are only counted on success.""" + + ok: bool + tools: list[McpProbeTool] + error: str | None = None + prompts: int | None = None + resources: int | None = None + oauth_needed: bool + oauth_tokens_present: bool | None = None + + +method("mcp.servers.test", params=McpServerNameParams, result=McpServersTestResult, + doc="Connect, list tools, disconnect — an OAuth server with no token on disk is reported as not ok.") + + +class McpServersRemoveResult(Result): + ok: bool + removed: bool + + +method("mcp.servers.remove", params=McpServerNameParams, result=McpServersRemoveResult, + doc="Drop a server from the profile's config.yaml.") + + +class McpOauthStartParams(McpServerNameParams): + """With ``client_redirect_uri`` the CLIENT hosts the loopback and relays the code via + ``mcp.servers.oauth.callback``.""" + + client_redirect_uri: str | None = None + + +class McpOauthStartResult(Result): + ok: bool + session_id: str + auth_url: str + flow: str + + +method("mcp.servers.oauth.start", params=McpOauthStartParams, result=McpOauthStartResult, + doc="Begin a PKCE OAuth flow; the client opens auth_url and polls mcp.servers.oauth.poll.") + + +class McpOauthFlowParams(McpServerNameParams): + """``session_id`` is the OAuth flow id returned by ``oauth.start`` (not a gateway session).""" + + session_id: str + + +class McpOauthPollStatus(WireEnum): + pending = "pending" + approved = "approved" + error = "error" + + +class McpOauthPollResult(Result): + ok: bool + status: McpOauthPollStatus + session_id: str | None = None + error_message: str | None = None + auth_url: str | None = None + tools: list[McpProbeTool] | None = None + + +method("mcp.servers.oauth.poll", params=McpOauthFlowParams, result=McpOauthPollResult, + doc="Poll a flow; approved persists tokens for the profile and returns the probed tools.") + + +class McpOauthCancelResult(Result): + ok: bool + status: str | None = None + error_message: str | None = None + + +method("mcp.servers.oauth.cancel", params=McpOauthFlowParams, result=McpOauthCancelResult, + doc="Cancel a flow owned by the resolved profile, waking its callback worker.") + + +class McpOauthCallbackParams(McpOauthFlowParams): + code: str | None = None + state: str | None = None + error: str | None = None + + +class McpOauthCallbackResult(Result): + ok: bool + session_id: str | None = None + error_message: str | None = None + + +method("mcp.servers.oauth.callback", params=McpOauthCallbackParams, result=McpOauthCallbackResult, + doc="Relay a client-captured redirect into a client_redirect_uri flow.") + + +# ── plugins ─────────────────────────────────────────────────────────────────────────────────── + + +class PluginsListParams(Params): + pass + + +class LegacyPluginRow(Result): + name: str + version: str + enabled: bool + + +class PluginsListResult(Result): + plugins: list[LegacyPluginRow] + + +method("plugins.list", params=PluginsListParams, result=PluginsListResult, + doc="Loaded plugin manager entries (legacy flat view); the Plugins Hub uses plugins.manage list.") + + +class PluginsAction(WireEnum): + list = "list" + toggle = "toggle" + install = "install" + update = "update" + + +class PluginsManageParams(ProfileParams): + """``toggle``: ``key``/``name`` + ``enable``; ``install``: ``identifier``/``repo`` or ``catalog_name`` + (+ ``force``, ``enable``, ``ref``); ``update``: ``name``.""" + + action: PluginsAction = PluginsAction.list + key: str | None = None + name: str | None = None + enable: bool | None = None + identifier: str | None = None + repo: str | None = None + catalog_name: str | None = None + force: bool | None = None + ref: str | None = None + + +class AgentPluginRow(Result): + """``methods_tools._plugin_rows`` + ``plugins_cmd_catalog.catalog_row_fields`` provenance.""" + + name: str + key: str + version: str + description: str + source: str + status: str + portable: bool + install_dir: str + has_desktop_half: bool + catalog_name: str | None = None + catalog_tier: str | None = None + installed_sha: str | None = None + catalog_sha: str | None = None + update_available: bool | None = None + pinned_sha: str | None = None + + +class PluginsManageResult(Result): + """``list`` → ``plugins`` + counts; ``toggle`` → ``ok``/``unchanged``/``name``/``plugin``; + ``install`` → ``hermes_cli.plugins_cmd.dashboard_install_plugin``'s ok payload; ``update`` → + ``ok``/``unchanged``/``sha``.""" + + plugins: list[AgentPluginRow] | None = None + user_count: int | None = None + bundled_count: int | None = None + ok: bool | None = None + unchanged: bool | None = None + name: str | None = None + plugin: AgentPluginRow | None = None + plugin_name: str | None = None + warnings: list[str] | None = None + missing_env: list[str] | None = None + after_install_path: str | None = None + enabled: bool | None = None + sha: str | None = None + + +method("plugins.manage", params=PluginsManageParams, result=PluginsManageResult, + doc="Plugins Hub backend: list installed plugins, toggle, git-install or re-pin a catalog install.")