Kokoro Engine
September 18, 2026 · View on GitHub
Version: 2.1 Last updated: 2026-09-13 Transport: Tauri IPC (
invoke) + Tauri events (emit/listen) Source of truth:src-tauri/src/lib.rsfor registered commands,src/lib/kokoro-bridge.tsfor frontend bridge wrappers Related doc: architecture.md
Table of contents
- Scope
- Calling convention
- Data types
- Command reference
- Event reference
- Custom protocols
- Error handling
- Bridge reference
- Compatibility notes
- Authenticated generic webhook
Scope
This document describes the current IPC surface of Kokoro Engine.
It covers:
- commands registered in
src-tauri/src/lib.rs - bridge wrappers exported from
src/lib/kokoro-bridge.ts - public backend/bridge events and selected cross-window frontend events
- custom URI schemes used by MODs, Live2D, and instance-owned character assets
It does not try to explain internal architecture. Use architecture.md for that.
2.1 command coverage supplement
The following commands were added after the original 2.0 inventory. Their serialized request and response shapes are defined by Rust command signatures and, where a wrapper exists, src/lib/kokoro-bridge.ts. They remain subject to the calling and error conventions in this document.
| Area | Commands |
|---|---|
| System | check_latest_release |
| Chat and profile | is_chat_busy, get_user_profile_settings, set_user_persona |
| Character activation | prepare_character_activation, commit_character_activation, get_committed_character_runtime |
| Character catalog | list_character_templates, instantiate_character_template, duplicate_character, restore_character_defaults, reconcile_character_template, apply_character_template_reconciliation, create_character_with_avatar, update_character_with_avatar |
| Character registry | list_registry_entries, install_character_from_registry, install_character_from_url, remove_character_package |
| Conversations | edit_conversation_message |
| Memory operations | run_dream_now, get_dreaming_summary, list_dream_jobs, list_dream_proposals, approve_dream_proposal, reject_dream_proposal |
| Memory embedding and observability | get_memory_embedding_model_status, download_memory_embedding_model, set_memory_upgrade_config, get_memory_upgrade_config, get_memory_observability_summary, get_latest_memory_write_event, get_latest_memory_retrieval_log, get_latest_memory_retrieval_eval_summary |
| LLM | test_llm_connection, list_anthropic_models, get_llama_cpp_status |
| Vision | list_vision_screens, set_vision_text_input_focused |
| Native audio stream | process_audio_chunk, complete_audio_stream, discard_audio_stream, snapshot_audio_stream, prune_audio_buffer |
| MOD lifecycle and registry | update_mod, remove_mod, install_mod_from_registry, install_mod_from_url |
| Unified Bot layer | get_bot_config, save_bot_config, respond_qq_authorization, start_bot_platform, stop_bot_platform, get_bot_status |
| Pet window | toggle_pet_window |
This supplement makes the document inventory complete for the 171 unique frontend-invoked command names registered as of 2026-09-13. npm run check:ipc is the required automated consistency check; code remains authoritative if this narrative reference falls behind.
Calling convention
Commands
Frontend code calls backend commands with invoke:
import { invoke } from "@tauri-apps/api/core";
const info = await invoke("get_engine_info");
Most commands return Result<T, String> at the IPC boundary.
Events
Backend code pushes events with emit. Frontend code listens with listen.
import { listen } from "@tauri-apps/api/event";
const off = await listen("chat-turn-delta", (event) => {
console.log(event.payload);
});
Naming
- Rust command names use
snake_case. - Bridge wrappers use
camelCase. - Event names stay in the backend string form, such as
chat-turn-delta.
Data types
This section lists the types that are part of the public bridge surface.
EngineInfo
interface EngineInfo {
name: string;
version: string;
platform: string;
}
SystemStatus
interface SystemStatus {
engine_running: boolean;
active_modules: string[];
memory_usage_mb: number;
}
CharacterState
interface CharacterState {
name: string;
current_cue: string;
mood: number;
is_speaking: boolean;
}
Note: mood is a legacy numeric runtime signal used by the current bridge, not the old emotion system.
ChatResponse
interface ChatResponse {
text: string;
cue: string;
mood_delta: number;
}
Note: mood_delta is still part of the public bridge surface, but it should be treated as runtime state adjustment rather than an emotion subsystem API.
ChatRequest
interface ChatRequest {
message: string;
api_key?: string;
endpoint?: string;
model?: string;
allow_image_gen?: boolean;
images?: string[];
character_id?: string;
hidden?: boolean;
client_request_id?: string;
regenerate?: boolean;
conversation_id?: string | null;
}
interface StreamChatResponse {
conversation_id: string;
user_message_id?: number | null;
assistant_message_id?: number | null;
client_request_id?: string | null;
status?: "completed" | "cancelled" | string | null;
}
FailureEvent
interface FailureEventContext {
deny_kind?: "hook_denied" | "policy_denied" | "fail_closed" | "pending_approval" | "execution_error";
approval_status?: "requested" | "approved" | "rejected";
[key: string]: unknown;
}
interface FailureEvent {
event_id: string;
timestamp: string;
domain: string;
stage: string;
code: string;
message: string;
retryable: boolean;
trace_id: string;
conversation_id?: string | null;
turn_id?: string | null;
character_id?: string | null;
context?: FailureEventContext | null;
}
The Rust failure payload includes the four nullable correlation/context keys. The bridge keeps them optional for compatibility, accepts the legacy string form from the raw chat-failure event, and normalizes the callback passed to onChatFailure to FailureEvent. Non-object context values are normalized to null by the bridge.
ChatTurnAcknowledgedEvent
interface ChatTurnAcknowledgedEvent {
turn_id?: string;
client_request_id?: string | null;
}
The current stream_chat backend always emits both keys as non-null strings. The optional and nullable markers preserve compatibility with older frontend event payloads.
ChatTurnStartEvent
interface ChatTurnStartEvent {
turn_id: string;
client_request_id?: string | null;
conversation_id?: string | null;
user_message_id?: number | null;
}
The current backend always emits all four keys: turn_id and client_request_id are strings, while conversation_id and user_message_id may be null. The bridge retains optional markers on the correlation fields for compatibility.
ChatTurnFinishEvent
interface ChatTurnFinishEvent {
turn_id: string;
status: "completed" | "error" | "cancelled";
client_request_id?: string | null;
conversation_id?: string | null;
assistant_message_id?: number | null;
}
The current backend always emits all five keys: client_request_id is a string, and the conversation and assistant-message IDs may be null. The bridge retains optional markers on the correlation fields for compatibility.
ChatTurnTextCompleteEvent
interface ChatTurnTextCompleteEvent {
turn_id: string;
text: string;
translation_pending: boolean;
translation?: string | null;
}
The current backend always emits translation as either a string or null; older payloads may omit it. The bridge mirrors that runtime contract as translation?: string | null while retaining the optional marker for compatibility.
ContextSettings
interface ContextSettings {
strategy: "window" | "summary";
max_message_chars: number;
}
LlmConfig
interface LlmProviderConfig {
id: string;
provider_type: string;
enabled: boolean;
supports_native_tools: boolean;
api_key?: string;
api_key_env?: string;
base_url?: string;
model?: string;
extra?: Record<string, unknown>;
}
interface LlmConfig {
active_provider: string;
system_provider?: string;
system_model?: string;
providers: LlmProviderConfig[];
presets?: LlmPreset[];
}
TtsConfig
interface TtsConfig {
provider_id?: string;
api_key?: string;
endpoint?: string;
model?: string;
voice?: string;
speed?: number;
pitch?: number;
emotion?: string;
}
TtsSystemConfig
interface TtsSystemConfig {
default_provider?: string | null;
cache: {
enabled: boolean;
max_entries: number;
ttl_secs: number;
};
queue: {
max_concurrent: number;
};
providers: ProviderConfigData[];
}
VisionConfig
interface VisionConfig {
vlm_enabled: boolean;
auto_vision_enabled: boolean;
vision_context_history_mode: "latest" | "full";
capture_interval_secs: number;
change_threshold: number;
display_id?: string | null;
vlm_region?: { x: number; y: number; width: number; height: number } | null;
proactive_vision_enabled: boolean;
vlm_provider: string;
vlm_base_url: string | null;
vlm_model: string;
vlm_api_key: string | null;
camera_enabled: boolean;
camera_device_id: string | null;
}
ImageGenSystemConfig
interface ImageGenSystemConfig {
default_provider?: string;
enabled: boolean;
providers: ImageGenProviderConfig[];
}
ImageGenParams
interface ImageGenParams {
prompt: string;
negative_prompt?: string;
size?: string;
quality?: string;
style?: string;
n: number;
}
ImageGenResult
interface ImageGenResult {
image_url: string;
prompt: string;
provider_id: string;
}
SttConfig
interface SttConfig {
active_provider: string;
language?: string;
auto_send: boolean;
continuous_listening: boolean;
wake_word_enabled: boolean;
wake_word?: string;
providers: SttProviderConfig[];
}
SenseVoiceLocalModelStatus
interface SenseVoiceLocalModelStatus {
installed: boolean;
download_instructions_url: string;
recommended_model_id: string;
download_url: string;
install_dir: string;
model_path: string;
tokens_path: string;
}
SenseVoiceLocalDownloadProgress
interface SenseVoiceLocalDownloadProgress {
stage: "downloading" | "extracting" | "complete" | "ready" | string;
message: string;
downloaded_bytes: number;
total_bytes: number | null;
}
MemoryEmbeddingModelDownloadProgress
interface MemoryEmbeddingModelDownloadProgress {
stage: string;
message: string;
current_file: string;
file_index: number;
file_count: number;
downloaded_bytes: number;
total_bytes: number | null;
}
Known stage values are checking, downloading, complete, verifying, and ready; consumers must tolerate additional string values.
ToolSettings
interface ToolSettings {
max_tool_rounds: number;
enabled_tools: Record<string, boolean>;
max_permission_level: "safe" | "elevated";
blocked_risk_tags: ("read" | "write" | "external" | "sensitive")[];
}
ActionInfo
interface ActionInfo {
id: string;
name: string;
source: "builtin" | "mcp";
server_name?: string;
description: string;
parameters: { name: string; description: string; required: boolean }[];
needs_feedback: boolean;
risk_tags: ("read" | "write" | "external" | "sensitive")[];
permission_level: "safe" | "elevated";
}
ActionResult
interface ActionResult {
success: boolean;
message: string;
data?: unknown;
}
McpServerConfig
interface McpServerConfig {
name: string;
type?: string;
command?: string;
args?: string[];
env?: Record<string, string>;
url?: string;
enabled: boolean;
}
McpServerStatus
interface McpServerStatus {
name: string;
enabled: boolean;
connected: boolean;
tool_count: number;
server_version: string | null;
status: "connected" | "connecting" | "disconnected";
error: string | null;
}
Conversation
interface Conversation {
id: string;
character_id: string;
title: string;
topic: string;
pinned_state: string;
created_at: string;
updated_at: string;
}
LoadedConversation
interface LoadedConversation {
topic: string;
pinned_state: string;
messages: ConversationMessage[];
}
MemoryRecord
interface MemoryRecord {
id: number;
content: string;
created_at: number;
importance: number;
tier: string;
memory_type: string;
entity_key: string | null;
status: string;
confidence: number;
first_seen_at: number;
last_seen_at: number;
evidence_count: number;
}
ListMemoriesResponse
interface ListMemoriesResponse {
memories: MemoryRecord[];
total: number;
}
Live2dModelInfo
interface Live2dModelInfo {
name: string;
path: string;
}
Live2dModelProfile
interface Live2dModelProfile {
version: number;
model_path: string;
available_expressions: string[];
available_motion_groups: Record<string, number>;
available_hit_areas: string[];
cue_map: Record<string, Live2dCueBinding>;
semantic_cue_map: Record<string, string>;
}
ModManifest
interface ModManifest {
id: string;
name: string;
version: string;
description: string;
engine_version?: string;
layout?: string;
theme?: string;
components?: Record<string, string>;
scripts?: string[];
permissions?: string[];
entry?: string;
ui_entry?: string;
}
ModThemeJson
interface ModThemeJson {
id?: string;
name?: string;
variables: Record<string, string>;
assets?: {
fonts?: string[];
background?: string;
noise_texture?: string;
[key: string]: string | string[] | undefined;
};
animations?: Record<string, {
initial?: Record<string, number | string>;
animate?: Record<string, number | string>;
exit?: Record<string, number | string>;
transition?: Record<string, number | string>;
}>;
}
TelegramConfig
interface TelegramConfig {
enabled: boolean;
bot_token?: string;
bot_token_env?: string;
allowed_chat_ids: number[];
send_voice_reply: boolean;
character_id?: string;
}
WebhookMessageRequest
interface WebhookMessageRequest {
text?: string;
message?: string; // legacy alias for text
image?: string; // URL or base64 payload
images?: string[]; // URLs or base64 payloads
image_base64?: string;
image_mime_type?: string; // defaults to image/jpeg for raw base64
audio_base64?: string; // raw or data: base64 payload
audio_format?: string; // ogg, mp3, wav, webm, or m4a
character_id?: string;
conversation_id?: string;
conversation_type?: "private" | "group" | "channel";
user_id?: string;
source?: string;
}
text takes precedence over message. A request may contain text, image
media, audio, or any combination. Audio is transcribed by the configured STT
service before the request is sent to the LLM. An image-only request uses the
placeholder The user sent an image: when no caption is supplied.
WebhookReply
interface WebhookReply {
reply: string;
translation?: string;
images?: Array<{
prompt: string;
mime_type: string;
file_name: string;
data_base64: string;
}>;
audio?: {
mime_type: string;
file_name: string;
data_base64: string;
};
}
TelegramStatus
interface TelegramStatus {
running: boolean;
enabled: boolean;
has_token: boolean;
}
BackupStats
interface BackupStats {
memories: number;
conversations: number;
messages: number;
configs: number;
}
ExportResult
interface ExportResult {
path: string;
size_bytes: number;
stats: BackupStats;
}
BackupManifest
interface BackupManifest {
version: string;
created_at: string;
app_version: string;
}
ImportPreview
interface ImportPreview {
manifest: BackupManifest;
has_database: boolean;
has_configs: boolean;
config_files: string[];
stats: BackupStats;
/** Character instances stored in the backup; empty for pre-SQLite-character backups. */
characters: BackupCharacterSummary[];
}
interface BackupCharacterSummary {
id: string;
name: string;
memory_count: number;
conversation_count: number;
}
ImportOptions
Character instance ids are generated per machine, so a backup never reuses a
local id. character_merges routes the rows of a backup character into an
existing local instance, ignored_characters leaves them out of the restore
entirely, and every character that appears in neither list is imported as a new
instance. All ids are validated before the first live row is touched; a character
cannot be merged and ignored at the same time.
interface ImportOptions {
import_database: boolean;
import_configs: boolean;
conflict_strategy: "skip" | "overwrite";
character_merges?: CharacterMerge[];
ignored_characters?: string[];
}
interface CharacterMerge {
/** Character id as stored inside the backup. */
imported_id: string;
/** Existing local character that receives the imported rows. */
target_id: string;
}
ImportResult
interface ImportResult {
imported_memories: number;
imported_conversations: number;
imported_configs: number;
imported_characters: number;
/** Characters whose rows were routed into an existing local instance. */
merged_characters?: number;
/** Characters whose rows were left out of the restore. */
ignored_characters?: number;
/** Memories dropped by the skip strategy because they violate the local schema. */
skipped_memories?: number;
characters_json?: string;
debug_log?: string[];
}
CharacterRecord
interface CharacterRecord {
id: string;
name: string;
persona: string;
user_nickname: string;
source_format: string;
created_at: number;
updated_at: number;
template_id?: string | null;
template_version?: string | null;
template_snapshot_json?: string | null;
description?: string;
avatar_path?: string | null;
greeting?: string;
greeting_consumed_at?: number | null;
greeting_message_id?: number | null;
example_dialogue?: string;
runtime_profile_json?: string;
user_modified_at?: number | null;
}
AutoBackupConfig
interface AutoBackupConfig {
enabled: boolean;
backup_dir: string;
interval_days: number;
auto_cleanup: boolean;
keep_days: number;
}
Command reference
The tables below list the current IPC commands. The Bridge column shows whether src/lib/kokoro-bridge.ts exports a wrapper for the command.
System
| Command | Bridge | Request | Response | Notes |
|---|---|---|---|---|
get_engine_info | getEngineInfo | none | EngineInfo | Returns app metadata. |
get_system_status | getSystemStatus | none | SystemStatus | Returns runtime status. |
set_window_size | setWindowSize | width: number, height: number | void | Stores the current UI size for image generation. |
Character
| Command | Bridge | Request | Response | Notes |
|---|---|---|---|---|
get_character_state | getCharacterState | none | CharacterState | Returns the current character state. |
play_cue | playCue | cue: string | CharacterState | Updates the active cue. |
send_message | sendMessage | message: string | ChatResponse | Legacy non-streaming chat entry point. |
Database
| Command | Bridge | Request | Response | Notes |
|---|---|---|---|---|
init_db | initDb | none | string | Initializes the SQLite database. |
test_vector_store | testVectorStore | none | DbTestResult | Smoke test for memory storage. |
Context
| Command | Bridge | Request | Response | Notes |
|---|---|---|---|---|
set_persona | setPersona | prompt: string | void | Sets the system prompt. |
set_character_name | setCharacterName | name: string | void | Sets the character display name. |
set_active_character_id | setActiveCharacterId | id: string | void | Persists the active character id. |
set_user_name | setUserName | name: string | void | Sets the user name used in prompts. |
set_response_language | setResponseLanguage | language: string | void | Sets assistant response language. |
set_user_language | setUserLanguage | language: string | void | Sets user language. |
set_jailbreak_prompt | setJailbreakPrompt | prompt: string | void | Persists the jailbreak prompt. |
get_jailbreak_prompt | getJailbreakPrompt | none | string | Returns the current jailbreak prompt. |
set_proactive_enabled | setProactiveEnabled | enabled: boolean | void | Enables or disables proactive messages. |
get_proactive_enabled | getProactiveEnabled | none | boolean | Returns proactive toggle state. |
set_memory_enabled | setMemoryEnabled | enabled: boolean | void | Enables or disables memory persistence. |
get_memory_enabled | getMemoryEnabled | none | boolean | Returns memory toggle state. |
clear_history | clearHistory | none | void | Clears conversation history. |
delete_last_messages | deleteLastMessages | count: number, expectedConversationId?: string | null | void | Deletes the last visible messages. Skipped (no-op) when expectedConversationId does not match the backend's current conversation, preventing stale deletes after a conversation switch. |
get_context_settings | getContextSettings | none | ContextSettings | Returns chat context strategy settings. |
set_context_settings | setContextSettings | settings: ContextSettings | void | Saves chat context strategy settings. |
end_session | none | request: EndSessionRequest | void | Generates a summary in the background and clears history. |
LLM management
| Command | Bridge | Request | Response | Notes |
|---|---|---|---|---|
get_llm_config | getLlmConfig | none | LlmConfig | Returns the active LLM config. |
save_llm_config | saveLlmConfig | config: LlmConfig | void | Saves the active LLM config. |
get_codex_runtime_status | getCodexRuntimeStatus | none | CodexRuntimeInfo | Detects a local Codex CLI; does not read Codex credentials. |
list_codex_runtime_models | listCodexRuntimeModels | none | string[] | Queries the Codex app-server model/list RPC. |
list_ollama_models | listOllamaModels | baseUrl: string | OllamaModelInfo[] | Lists models from an Ollama server. |
Chat
| Command | Bridge | Request | Response | Notes |
|---|---|---|---|---|
stream_chat | streamChat | request: ChatRequest | StreamChatResponse | Streaming chat entry point. Emits turn events and returns persisted message identifiers/status. |
cancel_chat_turn | cancelChatTurn | turnId: string, reason?: string | void | Cancels an in-flight turn. |
approve_tool_approval | approveToolApproval | approvalRequestId: string | void | Approves a pending tool execution. |
reject_tool_approval | rejectToolApproval | approvalRequestId: string, reason?: string | void | Rejects a pending tool execution. |
TTS
| Command | Bridge | Request | Response | Notes |
|---|---|---|---|---|
synthesize | synthesize | text: string, config: TtsConfig | void | Streams audio through TTS events. |
list_tts_providers | listTtsProviders | none | ProviderStatus[] | Lists configured TTS providers. |
list_tts_voices | listTtsVoices | none | VoiceProfile[] | Lists available voices. |
get_tts_provider_status | getTtsProviderStatus | providerId: string | ProviderStatus | null | Returns one provider's status. |
clear_tts_cache | clearTtsCache | none | void | Clears the synthesis cache. |
get_tts_config | getTtsConfig | none | TtsSystemConfig | Returns the TTS system config. |
save_tts_config | saveTtsConfig | config: TtsSystemConfig | void | Saves the TTS system config. |
list_gpt_sovits_models | listGptSovitsModels | installPath: string | GptSovitsModels | Lists GPT-SoVITS models. |
Mod system
| Command | Bridge | Request | Response | Notes |
|---|---|---|---|---|
list_mods | listMods | none | ModManifest[] | Lists discovered mods. |
load_mod | loadMod | modId: string | ModManifest | Loads and activates a mod. |
install_mod | installMod | filePath: string | ModManifest | Installs a mod archive. |
get_mod_theme | getModTheme | none | ModThemeJson | null | Returns the active mod theme override. |
get_mod_layout | getModLayout | none | unknown | null | Returns the active mod layout override. |
dispatch_mod_event | dispatchModEvent | event: string, payload: unknown | void | Sends an event into the active mod. |
unload_mod | unloadMod | none | void | Unloads the active mod. |
Live2D
| Command | Bridge | Request | Response | Notes |
|---|---|---|---|---|
import_live2d_zip | importLive2dZip | zipPath: string | string | Imports a Live2D archive. |
import_live2d_folder | importLive2dFolder | modelJsonPath: string | string | Imports a Live2D folder from a model JSON path. |
export_live2d_model | exportLive2dModel | modelPath: string, exportPath: string | string | Exports a Live2D model. |
list_live2d_models | listLive2dModels | none | Live2dModelInfo[] | Lists installed models. |
delete_live2d_model | deleteLive2dModel | modelName: string | void | Deletes a model. |
rename_live2d_model | renameLive2dModel | modelPath: string, newName: string | string | Renames a model. |
get_live2d_model_profile | getLive2dModelProfile | modelPath: string | Live2dModelProfile | Returns the cue/profile mapping. |
save_live2d_model_profile | saveLive2dModelProfile | profile: Live2dModelProfile | Live2dModelProfile | Saves the profile and returns the merged profile. |
set_active_live2d_model | setActiveLive2dModel | modelPath: string | null | void | Sets the active model. |
Image generation
| Command | Bridge | Request | Response | Notes |
|---|---|---|---|---|
generate_image | generateImage | prompt: string, providerId?: string | ImageGenResult | Bridge wrapper only exposes prompt and provider selection. The backend builds the rest from config and window size state. |
get_imagegen_config | getImageGenConfig | none | ImageGenSystemConfig | Returns image generation config. |
save_imagegen_config | saveImageGenConfig | config: ImageGenSystemConfig | void | Saves image generation config. |
test_sd_connection | testSdConnection | baseUrl: string | string[] | Returns Stable Diffusion model names from the server. |
Vision
| Command | Bridge | Request | Response | Notes |
|---|---|---|---|---|
start_vision_watcher | none | none | void | Starts the background watcher. |
stop_vision_watcher | none | none | void | Stops the background watcher. |
capture_screen_now | captureScreenNow | none | string | Captures the screen and returns a description. |
upload_vision_image | uploadVisionImage | fileBytes: number[], filename: string | string | Uploads an image to the vision server. |
get_vision_config | getVisionConfig | none | VisionConfig | Returns the vision watcher config. |
save_vision_config | saveVisionConfig | config: VisionConfig | void | Saves config and starts/stops the watcher. |
Memory
| Command | Bridge | Request | Response | Notes |
|---|---|---|---|---|
list_memories | listMemories | request: { character_id: string; limit: number; offset: number } | ListMemoriesResponse | Lists memories for one character. |
update_memory | updateMemory | request: { id: number; content: string; importance: number } | void | Updates a memory record. |
delete_memory | deleteMemory | request: { id: number } | void | Deletes a memory record. |
update_memory_tier | updateMemoryTier | request: { id: number; tier: string } | void | Updates the memory tier. |
Characters
| Command | Bridge | Request | Response | Notes |
|---|---|---|---|---|
list_characters | listCharacters | none | CharacterRecord[] | Lists stored characters. |
create_character | createCharacter | request: CharacterRecord | void | Creates a character row. |
update_character | updateCharacter | request: Omit<CharacterRecord, "created_at"> | void | Updates a character row. |
delete_character | deleteCharacter | id: string | void | Deletes a character row. |
Conversation
| Command | Bridge | Request | Response | Notes |
|---|---|---|---|---|
list_conversations | listConversations | request: { character_id: string } | Conversation[] | Lists conversations for one character. |
load_conversation | loadConversation | request: { id: string } | LoadedConversation | Loads a conversation. |
update_conversation_state | updateConversationState | request: { id: string; topic?: string; pinned_state?: string } | void | Updates topic or pinned state. |
delete_conversation | deleteConversation | request: { id: string } | void | Deletes a conversation. |
create_conversation | createConversation | none | string | Creates a new conversation id. |
rename_conversation | renameConversation | request: { id: string; title: string } | void | Renames a conversation. |
list_character_ids | listCharacterIds | none | string[] | Lists known character ids. |
STT
| Command | Bridge | Request | Response | Notes |
|---|---|---|---|---|
transcribe_audio | transcribeAudio | audioBytes: number[], format: string | string | Transcribes one audio clip. |
get_stt_config | getSttConfig | none | SttConfig | Returns STT config. |
save_stt_config | saveSttConfig | config: SttConfig | void | Saves STT config. |
transcribe_wake_word_audio | none | samples: Vec<f32> | string | Short one-shot transcription for wake-word detection. |
start_native_mic | none | auto_stop_on_silence?: boolean | void | Starts the native microphone worker. |
stop_native_mic | none | none | void | Stops the native microphone worker. |
start_native_wake_word | none | wake_word: string, trigger_on_speech?: boolean | void | Starts the native wake-word worker. |
stop_native_wake_word | none | none | void | Stops the native wake-word worker. |
get_sensevoice_local_status | getSenseVoiceLocalStatus | none | SenseVoiceLocalModelStatus | Returns the recommended local SenseVoice status. |
download_sensevoice_local_model | downloadSenseVoiceLocalModel | none | SenseVoiceLocalModelStatus | Downloads the recommended local model. |
Actions
| Command | Bridge | Request | Response | Notes |
|---|---|---|---|---|
list_actions | listActions | none | ActionInfo[] | Lists all actions. |
list_builtin_tools | listBuiltinTools | none | ActionInfo[] | Lists only builtin tools. |
execute_action | executeAction | name: string, args: Record<string, string>, characterId?: string | ActionResult | Executes one action. |
get_tool_settings | getToolSettings | none | ToolSettings | Returns tool settings. |
save_tool_settings | saveToolSettings | settings: ToolSettings | void | Saves tool settings. |
approve_tool_approval | approveToolApproval | approvalRequestId: string | void | Approval flow for pending tools. |
reject_tool_approval | rejectToolApproval | approvalRequestId: string, reason?: string | void | Approval flow for pending tools. |
MCP
| Command | Bridge | Request | Response | Notes |
|---|---|---|---|---|
list_mcp_servers | listMcpServers | none | McpServerStatus[] | Lists configured servers with live status. |
add_mcp_server | addMcpServer | config: McpServerConfig | void | Adds a server and connects in background. |
remove_mcp_server | removeMcpServer | name: string | void | Removes a server. |
refresh_mcp_tools | refreshMcpTools | none | void | Rebuilds the tool registry from connected servers. |
reconnect_mcp_server | reconnectMcpServer | name: string | void | Reconnects one server. |
toggle_mcp_server | toggleMcpServer | name: string, enabled: boolean | void | Enables or disables a server. |
Telegram
| Command | Bridge | Request | Response | Notes |
|---|---|---|---|---|
get_telegram_config | getTelegramConfig | none | TelegramConfig | Returns Telegram config. |
save_telegram_config | saveTelegramConfig | config: TelegramConfig | void | Saves Telegram config. |
start_telegram_bot | startTelegramBot | none | void | Starts the bot. |
stop_telegram_bot | stopTelegramBot | none | void | Stops the bot. |
get_telegram_status | getTelegramStatus | none | TelegramStatus | Returns runtime bot status. |
Backup and restore
| Command | Bridge | Request | Response | Notes |
|---|---|---|---|---|
export_data | exportData | exportPath: string, charactersJson?: string | ExportResult | Exports database and configs into a .kokoro archive. |
preview_import | previewImport | filePath: string | ImportPreview | Reads archive metadata without importing. |
import_data | importData | filePath: string, options: ImportOptions | ImportResult | Imports data from a .kokoro archive. |
get_auto_backup_config | getAutoBackupConfig | none | AutoBackupConfig | Returns auto backup config. |
save_auto_backup_config | saveAutoBackupConfig | config: AutoBackupConfig | void | Saves auto backup config. |
run_auto_backup_now | runAutoBackupNow | none | string | Runs a backup immediately. |
Authenticated generic webhook
The optional generic webhook is served by the Bot HTTP runtime. Its endpoint
defaults to http://127.0.0.1:8787/webhook/message and can be changed in the
Webhook settings. It must be enabled before requests are accepted.
Requests are limited to 4 MiB; larger bodies are rejected before authentication
and JSON parsing.
When a bearer token is configured, clients must send:
Authorization: Bearer <configured-token>
Content-Type: application/json
The character selection order is request character_id, configured Webhook
default character, then the active Kokoro character. Blank values are ignored;
no provider credentials or filesystem paths are accepted in the request.
Private and group sessions are isolated per character before persistence. A
private request maps user_id (falling back to conversation_id or source)
to private:<identity>. A group or channel request maps
conversation_id (falling back to source or user_id) to
group:<identity>. The resulting identity is scoped to the resolved character
and reused on subsequent requests.
Successful requests return WebhookReply with HTTP 200. Missing or invalid
JSON, invalid base64, and requests without text or media return HTTP 400 with
{"error":"..."}. Missing or invalid bearer credentials return HTTP 401
with the same JSON error shape. LLM, STT, or other runtime failures return HTTP
500.
Example text request:
curl -X POST http://127.0.0.1:8787/webhook/message \
-H "Authorization: Bearer $KOKORO_WEBHOOK_TOKEN" \
-H "Content-Type: application/json" \
-d '{"text":"Hello Kokoro","user_id":"astrbot-user-1","conversation_type":"private"}'
Example group image request:
{
"text": "What do you see?",
"images": ["https://example.test/photo.png"],
"conversation_type": "group",
"conversation_id": "astrbot-group-7",
"character_id": "kokoro"
}
Commands registered in Rust but not exposed by the bridge
These commands exist in src-tauri/src/lib.rs, but src/lib/kokoro-bridge.ts does not export wrappers for them yet.
| Command | Module | Notes |
|---|---|---|
end_session | context | Summarizes the current session in the background. |
start_vision_watcher | vision | Starts the background vision loop. |
stop_vision_watcher | vision | Stops the background vision loop. |
transcribe_wake_word_audio | stt | One-shot wake-word transcription. |
start_native_mic | stt | Starts the native microphone worker. |
stop_native_mic | stt | Stops the native microphone worker. |
start_native_wake_word | stt | Starts the wake-word worker. |
stop_native_wake_word | stt | Stops the wake-word worker. |
show_pet_window | pet | Shows the floating pet window. |
hide_pet_window | pet | Hides the floating pet window. |
set_pet_drag_mode | pet | Toggles pet drag mode. |
get_pet_config | pet | Returns pet window config. |
save_pet_config | pet | Saves pet window config. |
move_pet_window | pet | Moves the pet window. |
resize_pet_window | pet | Resizes the pet window. |
show_bubble_window | pet | Shows the speech bubble window. |
update_bubble_text | pet | Updates the bubble text. |
hide_bubble_window | pet | Hides the speech bubble window. |
toggle_pet_window | pet | Toggles the floating pet window. |
process_audio_chunk | stt::stream | Appends data to a native audio stream. |
complete_audio_stream | stt::stream | Completes and transcribes a native audio stream. |
discard_audio_stream | stt::stream | Discards a native audio stream. |
snapshot_audio_stream | stt::stream | Returns an audio-stream snapshot. |
prune_audio_buffer | stt::stream | Prunes buffered native audio. |
check_latest_release | system | Checks release metadata. |
update_mod | mods | Updates an installed MOD. |
remove_mod | mods | Removes an installed MOD package. |
install_mod_from_url | mods | Installs an untrusted MOD URL after the caller's confirmation flow. |
Event reference
Chat events
| Event | Payload | Emitted by | Bridge wrapper |
|---|---|---|---|
chat-typing | TypingParams | chat.rs | none |
chat-turn-start | ChatTurnStartEvent | chat.rs | onChatTurnStart |
chat-turn-delta | { turn_id: string; delta: string; ... } | chat.rs | onChatTurnDelta |
chat-turn-finish | ChatTurnFinishEvent | chat.rs | onChatTurnFinish |
chat-turn-translation | { turn_id: string; translation: string } | chat.rs | onChatTurnTranslation |
chat-turn-tool | ToolTraceItem-style payload | chat.rs | onChatTurnTool |
chat-cue | { cue: string; source?: string } | chat.rs, mods/manager.rs | onChatCue |
chat-imagegen | { prompt: string } | actions/builtin.rs | onChatImageGen |
chat-error | string | chat.rs | onChatError |
chat-warning | string | chat.rs | onChatWarning |
chat-failure | FailureEvent | string | chat.rs | onChatFailure |
chat-turn-acknowledged | ChatTurnAcknowledgedEvent | chat.rs | onChatTurnAcknowledged |
chat-turn-text-complete | ChatTurnTextCompleteEvent | chat.rs | onChatTurnTextComplete |
TTS events
| Event | Payload | Emitted by | Bridge wrapper |
|---|---|---|---|
tts:start | { text: string } | tts/manager.rs | none |
tts:audio | { data: number[] } | tts/manager.rs | none |
tts:end | { text: string } | tts/manager.rs | none |
tts:browser-delegate | { text: string; voice?: string; speed?: number; pitch?: number } | tts/manager.rs | none |
Vision events
| Event | Payload | Emitted by | Bridge wrapper |
|---|---|---|---|
vision-status | "active" | "inactive" | vision/watcher.rs | none |
vision-observation | string | { summary: string; captured_at?: string; source?: string } | vision/watcher.rs | onVisionObservation |
camera-observation | string | listener only; producer is not present in tracked sources | onCameraObservation |
proactive-trigger | { trigger: string; instruction: string; idle_seconds?: number } | vision/watcher.rs, ai/heartbeat.rs | none |
STT events
| Event | Payload | Emitted by | Bridge wrapper |
|---|---|---|---|
stt:sensevoice-local-progress | SenseVoiceLocalDownloadProgress | commands/stt.rs | onSenseVoiceLocalProgress |
stt:mic-volume | { volume: number; rms: number } | stt/mic.rs | none |
stt:mic-auto-stop | () | stt/mic.rs | none |
stt:wake-word-detected | string | stt/wake_word.rs | none |
stt:wake-word-error | string | stt/wake_word.rs | none |
Idle and proactive events
| Event | Payload | Emitted by | Bridge wrapper |
|---|---|---|---|
idle-behavior | { behavior: unknown } | ai/heartbeat.rs | none |
Live2D and MOD events
| Event | Payload | Emitted by | Bridge wrapper |
|---|---|---|---|
live2d-profile-updated | Live2dModelProfile-style payload | commands/live2d.rs | none |
live2d-model-selection-updated | Live2dSelectionEvent | frontend/runtime | none |
character-runtime-committed | CommittedCharacterRuntime | character activation | none |
pet-config-updated | PetConfig | pet settings/window | none |
qq-authorization-request / qq-authorization-expired | QQAuthorizationRequest | qqbot/runtime.rs | none |
qq-authorization-approved | authorization result payload | commands/bot.rs | none |
mod:theme-override | ModThemeJson | mods/manager.rs | onModThemeOverride |
mod:layout-override | unknown | mods/manager.rs | onModLayoutOverride |
mod:components-register | Record<string, string> | mods/manager.rs | onModComponentsRegister |
mod:ui-message | { component: string; payload: unknown } | mods/manager.rs | onModUiMessage |
mod:unload | () | mods/manager.rs | onModUnload |
mod:script-event | { event: string; payload: unknown } | mods/api.ts bridge path | onModScriptEvent |
Image generation events
| Event | Payload | Emitted by | Bridge wrapper |
|---|---|---|---|
imagegen:done | ImageGenResult | chat.rs | onImageGenDone |
imagegen:error | string | chat.rs | onImageGenError |
Telegram events
| Event | Payload | Emitted by | Bridge wrapper |
|---|---|---|---|
telegram:chat-sync | { role: string; text: string; translation?: string } | telegram/bot.rs | onTelegramChatSync |
Backup and memory events
| Event | Payload | Emitted by | Bridge wrapper |
|---|---|---|---|
memory:updated | string | actions/builtin.rs | none |
memory:embedding-model-progress | MemoryEmbeddingModelDownloadProgress | commands/memory.rs | onMemoryEmbeddingModelProgress |
pet-window-closed | () | commands/pet.rs | none |
bubble-text-update | string | commands/pet.rs | none |
toggle-chat-input | () | lib.rs | none |
Custom protocols
mod://
Serves MOD assets from the installed mods/ directory.
- HTML files are served with the MOD SDK injected automatically.
- Path traversal is blocked.
- The response sets a strict Content Security Policy.
- CORS is limited to the app origin.
Example:
<img src="mod://example-mod/assets/icon.png" />
<script src="mod://example-mod/index.js"></script>
live2d://
Serves Live2D runtime assets from {app_data_dir}/live2d_models/.
- Path traversal is blocked.
- The protocol resolves files relative to the app data directory.
- It supports the runtime file layout expected by pixi-live2d-display.
Example:
live2d://localhost/my-model/runtime/model3.json
character-instance-resource://
Serves the managed PNG avatar owned by a character instance from {app_data_dir}/character-instance-resources/<instance_id>/avatar.png.
- The canonical reference is
character-instance-resource://<instance_id>/avatar.png. - On Windows WebView2 it is mapped to
http://character-instance-resource.localhost/<instance_id>/avatar.png. - The instance ID must contain 1–128 ASCII letters, digits, hyphens, or underscores, and the only accepted relative path is
avatar.png. - The handler rejects a redirected resource root and canonicalizes the requested file to enforce containment within that root.
- Successful responses use
Content-Type: image/png,Cache-Control: no-store, andAccess-Control-Allow-Origin: *.
Example:
<img src="character-instance-resource://example-character/avatar.png" />
Error handling
IPC error shape
Most commands return Result<T, String> at the IPC boundary.
The backend uses KokoroError internally.
KokoroError serializes as:
{
code: string;
message: string;
}
If serialization fails, the backend falls back to a plain string.
Common failures
| Command | Error | Condition |
|---|---|---|
send_message | Message cannot be empty | Blank message input |
stream_chat | API Key is required | Missing API key for direct API calls |
synthesize | No TTS provider available | No provider is configured |
synthesize | Provider {id} not found | Selected provider does not exist |
run_auto_backup_now | Backup directory not set | Auto backup directory is empty |
load_conversation | NotFound-style error | Conversation id does not exist |
Frontend pattern
try {
await streamChat({
message: "Hello",
api_key: "sk-...",
});
} catch (error) {
console.error("command failed", error);
}
If you want structured handling, use parseKokoroError from kokoro-bridge.ts.
Bridge reference
src/lib/kokoro-bridge.ts is the typed frontend entry point.
Exported command wrappers
- system:
getEngineInfo,getSystemStatus,setWindowSize - character:
getCharacterState,playCue - database:
initDb,testVectorStore,sendMessage - context:
setPersona,setCharacterName,setActiveCharacterId,setUserName,setResponseLanguage,setUserLanguage,setJailbreakPrompt,getJailbreakPrompt,setProactiveEnabled,getProactiveEnabled,clearHistory,setMemoryEnabled,getMemoryEnabled,getContextSettings,setContextSettings,deleteLastMessages - llm/chat:
getLlmConfig,saveLlmConfig,getCodexRuntimeStatus,listCodexRuntimeModels,listOllamaModels,streamChat,cancelChatTurn,approveToolApproval,rejectToolApproval - mod/live2d/imagegen/vision/memory/stt/actions/mcp/telegram/backup/characters: see the command tables above
Exported event wrappers
- chat:
onChatError,onChatWarning,onChatFailure,onChatTurnStart,onChatTurnAcknowledged,onChatTurnDelta,onChatTurnTextComplete,onChatTurnFinish,onChatTurnTranslation,onChatCue,onChatTurnTool - mod:
onModThemeOverride,onModLayoutOverride,onModComponentsRegister,onModUiMessage,onModUnload,onModScriptEvent - imagegen:
onChatImageGen,onImageGenDone,onImageGenError - vision:
onVisionObservation,onCameraObservation - STT/memory:
onSenseVoiceLocalProgress,onMemoryEmbeddingModelProgress - telegram:
onTelegramChatSync
Bridge-only helpers
These are local TypeScript helpers and not IPC commands:
fetchModelshasPinnedConversationStategetConversationDisplayTitleparseKokoroErrorsafeInvokeisKokoroErrorCode
Compatibility notes
Old entries removed from the previous spec
The following items in the old document no longer match the current code and should not be treated as current API:
- old
ChatRequestshape without image support - old
ToolSettingsshape without permission/risk controls - old TTS / STT / ImageGen / MCP return types that no longer match the bridge
- old quick reference entries that returned
Uint8Arrayfor streaming APIs - other legacy entries that were removed during the bridge cleanup and are no longer exported by
src/lib/kokoro-bridge.ts
Bridge coverage
Not every backend command has a bridge wrapper yet. The command tables above mark those gaps explicitly.
Event coverage
Some events are emitted by the backend but do not yet have dedicated bridge helpers. That is intentional. The backend event string is still the contract.
Appendix
Backend modules used by this document
src-tauri/src/lib.rssrc-tauri/src/commands/*.rssrc-tauri/src/tts/manager.rssrc-tauri/src/vision/watcher.rssrc-tauri/src/stt/*.rssrc-tauri/src/mods/*.rssrc-tauri/src/ai/*.rssrc/lib/kokoro-bridge.tssrc/core/types/mod.ts