| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| import { useEffect, useState } from 'react' |
|
|
| import { useAccount } from './HomePilotAccountProvider' |
| import { useComputer } from './ComputerContext' |
| import { mirrorClient } from './mirrorClient' |
| import type { MirrorStatus } from './types' |
|
|
| function cloudBase(status: MirrorStatus | null): string { |
| try { |
| const ls = localStorage.getItem('homepilot_cloud_url') |
| if (ls) return ls.replace(/\/+$/, '') |
| } catch { } |
| return (status?.cloud || '').replace(/\/+$/, '') |
| } |
|
|
| function currentModelChat(): string { |
| try { return localStorage.getItem('homepilot_model_chat') || '' } catch { return '' } |
| } |
|
|
| interface ModelsListResult { chat_models?: Array<{ id?: string } | string> } |
|
|
| function pickChatModel(list: ModelsListResult | null, preferred: string): string { |
| const ids: string[] = [] |
| for (const m of list?.chat_models || []) { |
| const id = typeof m === 'string' ? m : m?.id |
| if (id) ids.push(id) |
| } |
| if (preferred && ids.includes(preferred)) return preferred |
| return ids[0] || '' |
| } |
|
|
| export interface RemoteChatTarget { |
| baseUrl: string |
| model: string |
| nodeId: string |
| nodeName: string |
| } |
|
|
| export function useRemoteChatTarget(): RemoteChatTarget | null { |
| const { enabled, status } = useAccount() |
| const { selectedComputer, selectionMode, presenceOf } = useComputer() |
| const [model, setModel] = useState('') |
|
|
| const nodeId = selectedComputer?.node_id || '' |
| const online = nodeId ? presenceOf(nodeId) === 'online' : false |
| |
| const active = enabled && selectionMode === 'fixed' && !!nodeId && online |
|
|
| useEffect(() => { |
| if (!active || !nodeId) { setModel(''); return } |
| let cancelled = false |
| ;(async () => { |
| try { |
| const list = await mirrorClient.rpc<ModelsListResult>(nodeId, 'models.list', {}) |
| if (!cancelled) setModel(pickChatModel(list, currentModelChat())) |
| } catch { |
| |
| if (!cancelled) setModel(currentModelChat()) |
| } |
| })() |
| return () => { cancelled = true } |
| }, [active, nodeId]) |
|
|
| if (!active || !selectedComputer) return null |
| const cloud = cloudBase(status) |
| const resolved = model || currentModelChat() |
| if (!cloud || !resolved) return null |
| return { |
| baseUrl: `${cloud}/ollama/v1`, |
| model: resolved, |
| nodeId, |
| nodeName: selectedComputer.node_name || nodeId, |
| } |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| export function useSelectedOfflineNode(): { nodeId: string; nodeName: string } | null { |
| const { enabled } = useAccount() |
| const { selectedComputer, selectionMode, presenceOf } = useComputer() |
| if (!enabled || selectionMode !== 'fixed' || !selectedComputer) return null |
| if (presenceOf(selectedComputer.node_id) === 'online') return null |
| return { |
| nodeId: selectedComputer.node_id, |
| nodeName: selectedComputer.node_name || selectedComputer.node_id, |
| } |
| } |
|
|