/** * Tauri Commands * * Helper functions for invoking Tauri commands from the frontend. */ import { isTauri as coreIsTauri, invoke } from '@tauri-apps/api/core'; import { injectOpenClawContext } from '../lib/ai/openclaw-injector'; // Check if we're running in Tauri export const isTauri = (): boolean => { // Tauri v2: prefer the official runtime check over window globals. return coreIsTauri(); }; /** * Exchange a login token for a session token */ export async function exchangeToken( backendUrl: string, token: string ): Promise<{ sessionToken: string; user: object }> { if (!isTauri()) { throw new Error('Not running in Tauri'); } return await invoke('exchange_token', { backendUrl, token }); } /** * Get the current authentication state from Rust */ export async function getAuthState(): Promise<{ is_authenticated: boolean; user: object | null }> { if (!isTauri()) { return { is_authenticated: false, user: null }; } return await invoke('get_auth_state'); } /** * Get the session token from secure storage */ export async function getSessionToken(): Promise { if (!isTauri()) { return null; } return await invoke('get_session_token'); } /** * Logout and clear session */ export async function logout(): Promise { if (!isTauri()) { return; } await invoke('logout'); } /** * Store session in secure storage */ export async function storeSession(token: string, user: object): Promise { if (!isTauri()) { return; } await invoke('store_session', { token, user }); } /** * Show the main window */ export async function showWindow(): Promise { if (!isTauri()) { return; } await invoke('show_window'); } /** * Hide the main window */ export async function hideWindow(): Promise { if (!isTauri()) { return; } await invoke('hide_window'); } /** * Toggle window visibility */ export async function toggleWindow(): Promise { if (!isTauri()) { return; } await invoke('toggle_window'); } /** * Check if window is visible */ export async function isWindowVisible(): Promise { if (!isTauri()) { return true; // In browser, window is always visible } return await invoke('is_window_visible'); } /** * Minimize the window */ export async function minimizeWindow(): Promise { if (!isTauri()) { return; } await invoke('minimize_window'); } /** * Maximize or unmaximize the window */ export async function maximizeWindow(): Promise { if (!isTauri()) { return; } await invoke('maximize_window'); } /** * Close the window (minimizes to tray on macOS) */ export async function closeWindow(): Promise { if (!isTauri()) { return; } await invoke('close_window'); } /** * Set the window title */ export async function setWindowTitle(title: string): Promise { if (!isTauri()) { document.title = title; return; } await invoke('set_window_title', { title }); } // --- Memory Commands --- /** * Initialise the TinyHumans memory client in Rust with the user's JWT token * (sourced from `authSlice.token` in Redux). Call this after login and after * Redux Persist rehydration. */ export async function syncMemoryClientToken(token: string): Promise { console.debug( '[memory] syncMemoryClientToken: entry (token_present=%s, is_tauri=%s)', !!token, isTauri() ); if (!isTauri() || !token) { console.debug('[memory] syncMemoryClientToken: exit — skipped (not Tauri or empty token)'); return; } try { console.debug( '[memory] syncMemoryClientToken: payload → init_memory_client { jwtToken: }', token.length ); await invoke('init_memory_client', { jwtToken: token }); console.info('[memory] syncMemoryClientToken: exit — ok'); } catch (err) { console.warn('[memory] syncMemoryClientToken: exit — error:', err); } } export interface MemoryDebugDocument { documentId: string; namespace: string; title?: string; raw: unknown; } export async function memoryListDocuments(namespace?: string): Promise { if (!isTauri()) { throw new Error('Not running in Tauri'); } return await invoke('memory_list_documents', { namespace }); } export async function memoryListNamespaces(): Promise { if (!isTauri()) { throw new Error('Not running in Tauri'); } return await invoke('memory_list_namespaces'); } export async function memoryDeleteDocument( documentId: string, namespace: string ): Promise { if (!isTauri()) { throw new Error('Not running in Tauri'); } return await invoke('memory_delete_document', { documentId, namespace }); } export async function memoryQueryNamespace( namespace: string, query: string, maxChunks?: number ): Promise { if (!isTauri()) { throw new Error('Not running in Tauri'); } return await invoke('memory_query_namespace', { namespace, query, maxChunks }); } export async function memoryRecallNamespace( namespace: string, maxChunks?: number ): Promise { if (!isTauri()) { throw new Error('Not running in Tauri'); } return await invoke('memory_recall_namespace', { namespace, maxChunks }); } // --- OpenHuman Commands --- export type DoctorSeverity = 'Ok' | 'Warn' | 'Error'; export type ModelProbeOutcome = 'Ok' | 'Skipped' | 'AuthOrAccess' | 'Error'; export type IntegrationStatus = 'Available' | 'Active' | 'ComingSoon'; export type IntegrationCategory = | 'Chat' | 'AiModel' | 'Productivity' | 'MusicAudio' | 'SmartHome' | 'ToolsAutomation' | 'MediaCreative' | 'Social' | 'Platform'; export type ModelRefreshSource = 'Live' | 'CacheFresh' | 'CacheStaleFallback'; export type ServiceState = 'Running' | 'Stopped' | 'NotInstalled' | { Unknown: string }; export type HardwareTransport = 'Native' | 'Serial' | 'Probe' | 'None'; export interface CommandResponse { result: T; logs: string[]; } export interface SkillSnapshot { skill_id: string; name: string; status: unknown; tools: Array<{ name: string; description: string; input_schema?: unknown }>; error?: string | null; state?: Record; } export interface DoctorReport { items: { severity: DoctorSeverity; category: string; message: string }[]; summary: { ok: number; warnings: number; errors: number }; } export interface ModelProbeReport { entries: { provider: string; outcome: ModelProbeOutcome; message?: string | null }[]; summary: { ok: number; skipped: number; auth_or_access: number; errors: number }; } export interface IntegrationInfo { name: string; description: string; category: IntegrationCategory; status: IntegrationStatus; setup_hints: string[]; } export interface ModelRefreshResult { provider: string; models: string[]; source: ModelRefreshSource; cache_age_secs?: number | null; warnings: string[]; } export interface MigrationStats { from_sqlite: number; from_markdown: number; imported: number; skipped_unchanged: number; renamed_conflicts: number; } export interface MigrationReport { source_workspace: string; target_workspace: string; dry_run: boolean; stats: MigrationStats; warnings: string[]; } export interface DiscoveredDevice { name: string; detail?: string | null; device_path?: string | null; transport: HardwareTransport; } export interface HardwareIntrospect { path: string; vid?: number | null; pid?: number | null; board_name?: string | null; architecture?: string | null; memory_map_note: string; } export interface ServiceStatus { state: ServiceState; unit_path?: string | null; label: string; details?: string | null; } export interface AgentServerStatus { running: boolean; url: string; } export interface ConfigSnapshot { config: Record; workspace_dir: string; config_path: string; } export interface ModelSettingsUpdate { api_key?: string | null; api_url?: string | null; default_provider?: string | null; default_model?: string | null; default_temperature?: number | null; } export interface MemorySettingsUpdate { backend?: string | null; auto_save?: boolean | null; embedding_provider?: string | null; embedding_model?: string | null; embedding_dimensions?: number | null; } export interface GatewaySettingsUpdate { host?: string | null; port?: number | null; require_pairing?: boolean | null; allow_public_bind?: boolean | null; } export interface RuntimeSettingsUpdate { kind?: string | null; reasoning_enabled?: boolean | null; } export interface BrowserSettingsUpdate { enabled?: boolean | null; } export interface RuntimeFlags { browser_allow_all: boolean; log_prompts: boolean; } export interface TunnelConfig { provider: string; cloudflare?: { token: string } | null; tailscale?: { funnel?: boolean; hostname?: string | null } | null; ngrok?: { auth_token: string; domain?: string | null } | null; custom?: { start_command: string; health_url?: string | null; url_pattern?: string | null; } | null; } export async function openhumanGetConfig(): Promise> { if (!isTauri()) { throw new Error('Not running in Tauri'); } return await invoke('openhuman_get_config'); } export async function openhumanUpdateModelSettings( update: ModelSettingsUpdate ): Promise> { if (!isTauri()) { throw new Error('Not running in Tauri'); } return await invoke('openhuman_update_model_settings', { update }); } export async function openhumanUpdateMemorySettings( update: MemorySettingsUpdate ): Promise> { if (!isTauri()) { throw new Error('Not running in Tauri'); } return await invoke('openhuman_update_memory_settings', { update }); } export async function openhumanUpdateGatewaySettings( update: GatewaySettingsUpdate ): Promise> { if (!isTauri()) { throw new Error('Not running in Tauri'); } return await invoke('openhuman_update_gateway_settings', { update }); } export async function openhumanUpdateTunnelSettings( tunnel: TunnelConfig ): Promise> { if (!isTauri()) { throw new Error('Not running in Tauri'); } return await invoke('openhuman_update_tunnel_settings', { tunnel }); } export async function openhumanUpdateRuntimeSettings( update: RuntimeSettingsUpdate ): Promise> { if (!isTauri()) { throw new Error('Not running in Tauri'); } return await invoke('openhuman_update_runtime_settings', { update }); } export async function openhumanUpdateBrowserSettings( update: BrowserSettingsUpdate ): Promise> { if (!isTauri()) { throw new Error('Not running in Tauri'); } return await invoke('openhuman_update_browser_settings', { update }); } export async function openhumanGetRuntimeFlags(): Promise> { if (!isTauri()) { throw new Error('Not running in Tauri'); } return await invoke('openhuman_get_runtime_flags'); } export async function openhumanSetBrowserAllowAll( enabled: boolean ): Promise> { if (!isTauri()) { throw new Error('Not running in Tauri'); } return await invoke('openhuman_set_browser_allow_all', { enabled }); } export async function openhumanAgentChat( message: string, providerOverride?: string, modelOverride?: string, temperature?: number ): Promise> { if (!isTauri()) { throw new Error('Not running in Tauri'); } let processedMessage = message; try { processedMessage = injectOpenClawContext(message); } catch (error) { console.warn('[OpenClaw] Injection failed in agentChat:', error); } return await invoke('openhuman_agent_chat', { message: processedMessage, providerOverride, modelOverride, temperature, }); } export async function openhumanEncryptSecret(plaintext: string): Promise> { if (!isTauri()) { throw new Error('Not running in Tauri'); } return await invoke('openhuman_encrypt_secret', { plaintext }); } export async function openhumanDecryptSecret(ciphertext: string): Promise> { if (!isTauri()) { throw new Error('Not running in Tauri'); } return await invoke('openhuman_decrypt_secret', { ciphertext }); } export async function openhumanDoctorReport(): Promise> { if (!isTauri()) { throw new Error('Not running in Tauri'); } return await invoke('openhuman_doctor_report'); } export async function openhumanDoctorModels( providerOverride?: string, useCache = true ): Promise> { if (!isTauri()) { throw new Error('Not running in Tauri'); } return await invoke('openhuman_doctor_models', { providerOverride, useCache }); } export async function openhumanListIntegrations(): Promise> { if (!isTauri()) { throw new Error('Not running in Tauri'); } return await invoke('openhuman_list_integrations'); } export async function openhumanGetIntegrationInfo( name: string ): Promise> { if (!isTauri()) { throw new Error('Not running in Tauri'); } return await invoke('openhuman_get_integration_info', { name }); } export async function openhumanModelsRefresh( providerOverride?: string, force = false ): Promise> { if (!isTauri()) { throw new Error('Not running in Tauri'); } return await invoke('openhuman_models_refresh', { providerOverride, force }); } export async function openhumanMigrateOpenclaw( sourceWorkspace?: string, dryRun = true ): Promise> { if (!isTauri()) { throw new Error('Not running in Tauri'); } return await invoke('openhuman_migrate_openclaw', { sourceWorkspace, dryRun }); } export async function openhumanHardwareDiscover(): Promise> { if (!isTauri()) { throw new Error('Not running in Tauri'); } return await invoke('openhuman_hardware_discover'); } export async function openhumanHardwareIntrospect( path: string ): Promise> { if (!isTauri()) { throw new Error('Not running in Tauri'); } return await invoke('openhuman_hardware_introspect', { path }); } export async function openhumanServiceInstall(): Promise> { if (!isTauri()) { throw new Error('Not running in Tauri'); } return await invoke('openhuman_service_install'); } export async function openhumanServiceStart(): Promise> { if (!isTauri()) { throw new Error('Not running in Tauri'); } return await invoke('openhuman_service_start'); } export async function openhumanServiceStop(): Promise> { if (!isTauri()) { throw new Error('Not running in Tauri'); } return await invoke('openhuman_service_stop'); } export async function openhumanServiceStatus(): Promise> { if (!isTauri()) { throw new Error('Not running in Tauri'); } return await invoke('openhuman_service_status'); } export async function openhumanServiceUninstall(): Promise> { if (!isTauri()) { throw new Error('Not running in Tauri'); } return await invoke('openhuman_service_uninstall'); } export async function openhumanAgentServerStatus(): Promise> { if (!isTauri()) { throw new Error('Not running in Tauri'); } return await invoke('openhuman_agent_server_status'); } export async function runtimeListSkills(): Promise { if (!isTauri()) { throw new Error('Not running in Tauri'); } return await invoke('runtime_list_skills'); } export async function runtimeIsSkillEnabled(skillId: string): Promise { if (!isTauri()) { throw new Error('Not running in Tauri'); } return await invoke('runtime_is_skill_enabled', { skill_id: skillId }); } export async function runtimeEnableSkill(skillId: string): Promise { if (!isTauri()) { throw new Error('Not running in Tauri'); } await invoke('runtime_enable_skill', { skill_id: skillId }); } export async function runtimeDisableSkill(skillId: string): Promise { if (!isTauri()) { throw new Error('Not running in Tauri'); } await invoke('runtime_disable_skill', { skill_id: skillId }); }