/** * React hook for using AgentController */ import type { AgentActivity, AgentStatus, HistoricalEvent, SupportedLanguage, } from '@page-agent/core' import type { LLMConfig } from '@page-agent/llms' import { useCallback, useEffect, useRef, useState } from 'react' import { MultiPageAgent } from './MultiPageAgent' import { DEMO_CONFIG } from './constants' /** Language preference: undefined means follow system */ export type LanguagePreference = SupportedLanguage | undefined export interface ExtConfig extends LLMConfig { language?: LanguagePreference } export interface UseAgentResult { status: AgentStatus history: HistoricalEvent[] activity: AgentActivity | null currentTask: string config: ExtConfig | null execute: (task: string) => Promise stop: () => void configure: (config: ExtConfig) => Promise } export function useAgent(): UseAgentResult { const agentRef = useRef(null) const [status, setStatus] = useState('idle') const [history, setHistory] = useState([]) const [activity, setActivity] = useState(null) const [currentTask, setCurrentTask] = useState('') const [config, setConfig] = useState(null) useEffect(() => { chrome.storage.local.get(['llmConfig', 'language']).then((result) => { const llmConfig = (result.llmConfig as LLMConfig) ?? DEMO_CONFIG const language = (result.language as SupportedLanguage) || undefined const full = { ...llmConfig, language } if (!result.llmConfig) { chrome.storage.local.set({ llmConfig: DEMO_CONFIG }) } setConfig(full) }) }, []) useEffect(() => { if (!config) return const agent = new MultiPageAgent(config) agentRef.current = agent const handleStatusChange = (e: Event) => { const newStatus = agent.status as AgentStatus setStatus(newStatus) if (newStatus === 'idle' || newStatus === 'completed' || newStatus === 'error') { setActivity(null) } } const handleHistoryChange = (e: Event) => { setHistory([...agent.history]) } const handleActivity = (e: Event) => { const newActivity = (e as CustomEvent).detail as AgentActivity setActivity(newActivity) } agent.addEventListener('statuschange', handleStatusChange) agent.addEventListener('historychange', handleHistoryChange) agent.addEventListener('activity', handleActivity) return () => { agent.removeEventListener('statuschange', handleStatusChange) agent.removeEventListener('historychange', handleHistoryChange) agent.removeEventListener('activity', handleActivity) agent.dispose() } }, [config]) const execute = useCallback(async (task: string) => { const agent = agentRef.current console.log('🚀 [useAgent] start executing task:', task) if (!agent) throw new Error('Agent not initialized') setCurrentTask(task) setHistory([]) await agent.execute(task) }, []) const stop = useCallback(() => { agentRef.current?.stop() }, []) const configure = useCallback(async ({ language, ...llmConfig }: ExtConfig) => { await chrome.storage.local.set({ llmConfig }) if (language) { await chrome.storage.local.set({ language }) } else { await chrome.storage.local.remove('language') } setConfig({ ...llmConfig, language }) }, []) return { status, history, activity, currentTask, config, execute, stop, configure, } }