feat(ext): add lang setting
This commit is contained in:
2
package-lock.json
generated
2
package-lock.json
generated
@@ -11074,7 +11074,7 @@
|
|||||||
},
|
},
|
||||||
"packages/extension": {
|
"packages/extension": {
|
||||||
"name": "@page-agent/ext",
|
"name": "@page-agent/ext",
|
||||||
"version": "0.1.6",
|
"version": "0.1.7",
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@page-agent/core": "1.3.0",
|
"@page-agent/core": "1.3.0",
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import type { BrowserState, PageController } from '@page-agent/page-controller'
|
|||||||
import chalk from 'chalk'
|
import chalk from 'chalk'
|
||||||
import * as zod from 'zod'
|
import * as zod from 'zod'
|
||||||
|
|
||||||
import { type PageAgentConfig } from './config'
|
import { type PageAgentConfig, type SupportedLanguage } from './config'
|
||||||
import { DEFAULT_MAX_STEPS } from './config/constants'
|
import { DEFAULT_MAX_STEPS } from './config/constants'
|
||||||
import SYSTEM_PROMPT from './prompts/system_prompt.md?raw'
|
import SYSTEM_PROMPT from './prompts/system_prompt.md?raw'
|
||||||
import { tools } from './tools'
|
import { tools } from './tools'
|
||||||
@@ -24,6 +24,7 @@ import type {
|
|||||||
import { assert, normalizeResponse, uid, waitFor } from './utils'
|
import { assert, normalizeResponse, uid, waitFor } from './utils'
|
||||||
|
|
||||||
export { type PageAgentConfig }
|
export { type PageAgentConfig }
|
||||||
|
export type { SupportedLanguage }
|
||||||
export { tool, type PageAgentTool } from './tools'
|
export { tool, type PageAgentTool } from './tools'
|
||||||
export type * from './types'
|
export type * from './types'
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "@page-agent/ext",
|
"name": "@page-agent/ext",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "0.1.6",
|
"version": "0.1.7",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "wxt",
|
"dev": "wxt",
|
||||||
|
|||||||
@@ -1,22 +1,34 @@
|
|||||||
/**
|
/**
|
||||||
* React hook for using AgentController
|
* React hook for using AgentController
|
||||||
*/
|
*/
|
||||||
import type { AgentActivity, AgentStatus, HistoricalEvent } from '@page-agent/core'
|
import type {
|
||||||
|
AgentActivity,
|
||||||
|
AgentStatus,
|
||||||
|
HistoricalEvent,
|
||||||
|
SupportedLanguage,
|
||||||
|
} from '@page-agent/core'
|
||||||
import type { LLMConfig } from '@page-agent/llms'
|
import type { LLMConfig } from '@page-agent/llms'
|
||||||
import { useCallback, useEffect, useRef, useState } from 'react'
|
import { useCallback, useEffect, useRef, useState } from 'react'
|
||||||
|
|
||||||
import { MultiPageAgent } from './MultiPageAgent'
|
import { MultiPageAgent } from './MultiPageAgent'
|
||||||
import { DEMO_CONFIG } from './constants'
|
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 {
|
export interface UseAgentResult {
|
||||||
status: AgentStatus
|
status: AgentStatus
|
||||||
history: HistoricalEvent[]
|
history: HistoricalEvent[]
|
||||||
activity: AgentActivity | null
|
activity: AgentActivity | null
|
||||||
currentTask: string
|
currentTask: string
|
||||||
config: LLMConfig | null
|
config: ExtConfig | null
|
||||||
execute: (task: string) => Promise<void>
|
execute: (task: string) => Promise<void>
|
||||||
stop: () => void
|
stop: () => void
|
||||||
configure: (config: LLMConfig) => Promise<void>
|
configure: (config: ExtConfig) => Promise<void>
|
||||||
}
|
}
|
||||||
|
|
||||||
export function useAgent(): UseAgentResult {
|
export function useAgent(): UseAgentResult {
|
||||||
@@ -25,16 +37,17 @@ export function useAgent(): UseAgentResult {
|
|||||||
const [history, setHistory] = useState<HistoricalEvent[]>([])
|
const [history, setHistory] = useState<HistoricalEvent[]>([])
|
||||||
const [activity, setActivity] = useState<AgentActivity | null>(null)
|
const [activity, setActivity] = useState<AgentActivity | null>(null)
|
||||||
const [currentTask, setCurrentTask] = useState('')
|
const [currentTask, setCurrentTask] = useState('')
|
||||||
const [config, setConfig] = useState<LLMConfig | null>(null)
|
const [config, setConfig] = useState<ExtConfig | null>(null)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
chrome.storage.local.get('llmConfig').then((result) => {
|
chrome.storage.local.get(['llmConfig', 'language']).then((result) => {
|
||||||
if (result.llmConfig) {
|
const llmConfig = (result.llmConfig as LLMConfig) ?? DEMO_CONFIG
|
||||||
setConfig(result.llmConfig as LLMConfig)
|
const language = (result.language as SupportedLanguage) || undefined
|
||||||
} else {
|
const full = { ...llmConfig, language }
|
||||||
|
if (!result.llmConfig) {
|
||||||
chrome.storage.local.set({ llmConfig: DEMO_CONFIG })
|
chrome.storage.local.set({ llmConfig: DEMO_CONFIG })
|
||||||
setConfig(DEMO_CONFIG)
|
|
||||||
}
|
}
|
||||||
|
setConfig(full)
|
||||||
})
|
})
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
@@ -87,9 +100,14 @@ export function useAgent(): UseAgentResult {
|
|||||||
agentRef.current?.stop()
|
agentRef.current?.stop()
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
const configure = useCallback(async (newConfig: LLMConfig) => {
|
const configure = useCallback(async ({ language, ...llmConfig }: ExtConfig) => {
|
||||||
await chrome.storage.local.set({ llmConfig: newConfig })
|
await chrome.storage.local.set({ llmConfig })
|
||||||
setConfig(newConfig)
|
if (language) {
|
||||||
|
await chrome.storage.local.set({ language })
|
||||||
|
} else {
|
||||||
|
await chrome.storage.local.remove('language')
|
||||||
|
}
|
||||||
|
setConfig({ ...llmConfig, language })
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -1,15 +1,15 @@
|
|||||||
import type { LLMConfig } from '@page-agent/llms'
|
|
||||||
import { Copy, CornerUpLeft, Eye, EyeOff, HatGlasses, Home, Loader2, Scale } from 'lucide-react'
|
import { Copy, CornerUpLeft, Eye, EyeOff, HatGlasses, Home, Loader2, Scale } from 'lucide-react'
|
||||||
import { useEffect, useState } from 'react'
|
import { useEffect, useState } from 'react'
|
||||||
import { siGithub } from 'simple-icons'
|
import { siGithub } from 'simple-icons'
|
||||||
|
|
||||||
import { DEMO_API_KEY, DEMO_BASE_URL, DEMO_MODEL } from '@/agent/constants'
|
import { DEMO_API_KEY, DEMO_BASE_URL, DEMO_MODEL } from '@/agent/constants'
|
||||||
|
import type { ExtConfig, LanguagePreference } from '@/agent/useAgent'
|
||||||
import { Button } from '@/components/ui/button'
|
import { Button } from '@/components/ui/button'
|
||||||
import { Input } from '@/components/ui/input'
|
import { Input } from '@/components/ui/input'
|
||||||
|
|
||||||
interface ConfigPanelProps {
|
interface ConfigPanelProps {
|
||||||
config: LLMConfig | null
|
config: ExtConfig | null
|
||||||
onSave: (config: LLMConfig) => Promise<void>
|
onSave: (config: ExtConfig) => Promise<void>
|
||||||
onClose: () => void
|
onClose: () => void
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -17,6 +17,7 @@ export function ConfigPanel({ config, onSave, onClose }: ConfigPanelProps) {
|
|||||||
const [apiKey, setApiKey] = useState(config?.apiKey || DEMO_API_KEY)
|
const [apiKey, setApiKey] = useState(config?.apiKey || DEMO_API_KEY)
|
||||||
const [baseURL, setBaseURL] = useState(config?.baseURL || DEMO_BASE_URL)
|
const [baseURL, setBaseURL] = useState(config?.baseURL || DEMO_BASE_URL)
|
||||||
const [model, setModel] = useState(config?.model || DEMO_MODEL)
|
const [model, setModel] = useState(config?.model || DEMO_MODEL)
|
||||||
|
const [language, setLanguage] = useState<LanguagePreference>(config?.language)
|
||||||
const [saving, setSaving] = useState(false)
|
const [saving, setSaving] = useState(false)
|
||||||
const [userAuthToken, setUserAuthToken] = useState<string>('')
|
const [userAuthToken, setUserAuthToken] = useState<string>('')
|
||||||
const [copied, setCopied] = useState(false)
|
const [copied, setCopied] = useState(false)
|
||||||
@@ -28,6 +29,7 @@ export function ConfigPanel({ config, onSave, onClose }: ConfigPanelProps) {
|
|||||||
setApiKey(config?.apiKey || DEMO_API_KEY)
|
setApiKey(config?.apiKey || DEMO_API_KEY)
|
||||||
setBaseURL(config?.baseURL || DEMO_BASE_URL)
|
setBaseURL(config?.baseURL || DEMO_BASE_URL)
|
||||||
setModel(config?.model || DEMO_MODEL)
|
setModel(config?.model || DEMO_MODEL)
|
||||||
|
setLanguage(config?.language)
|
||||||
}, [config])
|
}, [config])
|
||||||
|
|
||||||
// Poll for user auth token every second until found
|
// Poll for user auth token every second until found
|
||||||
@@ -65,7 +67,7 @@ export function ConfigPanel({ config, onSave, onClose }: ConfigPanelProps) {
|
|||||||
const handleSave = async () => {
|
const handleSave = async () => {
|
||||||
setSaving(true)
|
setSaving(true)
|
||||||
try {
|
try {
|
||||||
await onSave({ apiKey, baseURL, model })
|
await onSave({ apiKey, baseURL, model, language })
|
||||||
} finally {
|
} finally {
|
||||||
setSaving(false)
|
setSaving(false)
|
||||||
}
|
}
|
||||||
@@ -165,6 +167,19 @@ export function ConfigPanel({ config, onSave, onClose }: ConfigPanelProps) {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div className="flex flex-col gap-1.5">
|
||||||
|
<label className="text-xs text-muted-foreground">Language</label>
|
||||||
|
<select
|
||||||
|
value={language ?? ''}
|
||||||
|
onChange={(e) => setLanguage((e.target.value || undefined) as LanguagePreference)}
|
||||||
|
className="h-8 text-xs rounded-md border border-input bg-background px-2 cursor-pointer"
|
||||||
|
>
|
||||||
|
<option value="">System</option>
|
||||||
|
<option value="en-US">English</option>
|
||||||
|
<option value="zh-CN">中文</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div className="flex gap-2 mt-2">
|
<div className="flex gap-2 mt-2">
|
||||||
<Button variant="outline" onClick={onClose} className="flex-1 h-8 text-xs cursor-pointer">
|
<Button variant="outline" onClick={onClose} className="flex-1 h-8 text-xs cursor-pointer">
|
||||||
Cancel
|
Cancel
|
||||||
|
|||||||
Reference in New Issue
Block a user