From 7a97de2a378c2c121999f05f06356095407cd7c8 Mon Sep 17 00:00:00 2001 From: Simon <10131203+gaomeng1900@users.noreply.github.com> Date: Thu, 5 Mar 2026 20:34:55 +0800 Subject: [PATCH] feat(ext): expose more config --- packages/core/src/PageAgentCore.ts | 2 +- packages/extension/src/agent/useAgent.ts | 48 ++++++-- .../sidepanel/components/ConfigPanel.tsx | 115 ++++++++++++++---- 3 files changed, 130 insertions(+), 35 deletions(-) diff --git a/packages/core/src/PageAgentCore.ts b/packages/core/src/PageAgentCore.ts index e8919ef..c7ab84b 100644 --- a/packages/core/src/PageAgentCore.ts +++ b/packages/core/src/PageAgentCore.ts @@ -96,7 +96,7 @@ export class PageAgentCore extends EventTarget { constructor(config: PageAgentCoreConfig) { super() - this.config = { ...config, maxSteps: config.maxSteps || 40 } + this.config = { ...config, maxSteps: config.maxSteps ?? 40 } this.#llm = new LLM(this.config) this.tools = new Map(tools) diff --git a/packages/extension/src/agent/useAgent.ts b/packages/extension/src/agent/useAgent.ts index db53294..a4be760 100644 --- a/packages/extension/src/agent/useAgent.ts +++ b/packages/extension/src/agent/useAgent.ts @@ -16,7 +16,13 @@ import { DEMO_CONFIG, migrateLegacyEndpoint } from './constants' /** Language preference: undefined means follow system */ export type LanguagePreference = SupportedLanguage | undefined -export interface ExtConfig extends LLMConfig { +export interface AdvancedConfig { + maxSteps?: number + systemInstruction?: string + experimentalLlmsTxt?: boolean +} + +export interface ExtConfig extends LLMConfig, AdvancedConfig { language?: LanguagePreference } @@ -40,9 +46,10 @@ export function useAgent(): UseAgentResult { const [config, setConfig] = useState(null) useEffect(() => { - chrome.storage.local.get(['llmConfig', 'language']).then((result) => { + chrome.storage.local.get(['llmConfig', 'language', 'advancedConfig']).then((result) => { let llmConfig = (result.llmConfig as LLMConfig) ?? DEMO_CONFIG const language = (result.language as SupportedLanguage) || undefined + const advancedConfig = (result.advancedConfig as AdvancedConfig) ?? {} // Auto-migrate legacy testing endpoints const migrated = migrateLegacyEndpoint(llmConfig) @@ -53,14 +60,18 @@ export function useAgent(): UseAgentResult { chrome.storage.local.set({ llmConfig: DEMO_CONFIG }) } - setConfig({ ...llmConfig, language }) + setConfig({ ...llmConfig, ...advancedConfig, language }) }) }, []) useEffect(() => { if (!config) return - const agent = new MultiPageAgent(config) + const { systemInstruction, ...agentConfig } = config + const agent = new MultiPageAgent({ + ...agentConfig, + instructions: systemInstruction ? { system: systemInstruction } : undefined, + }) agentRef.current = agent const handleStatusChange = (e: Event) => { @@ -106,15 +117,26 @@ export function useAgent(): UseAgentResult { 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 }) - }, []) + const configure = useCallback( + async ({ + language, + maxSteps, + systemInstruction, + experimentalLlmsTxt, + ...llmConfig + }: ExtConfig) => { + await chrome.storage.local.set({ llmConfig }) + if (language) { + await chrome.storage.local.set({ language }) + } else { + await chrome.storage.local.remove('language') + } + const advancedConfig: AdvancedConfig = { maxSteps, systemInstruction, experimentalLlmsTxt } + await chrome.storage.local.set({ advancedConfig }) + setConfig({ ...llmConfig, ...advancedConfig, language }) + }, + [] + ) return { status, diff --git a/packages/extension/src/entrypoints/sidepanel/components/ConfigPanel.tsx b/packages/extension/src/entrypoints/sidepanel/components/ConfigPanel.tsx index efcaf88..6ae7ef3 100644 --- a/packages/extension/src/entrypoints/sidepanel/components/ConfigPanel.tsx +++ b/packages/extension/src/entrypoints/sidepanel/components/ConfigPanel.tsx @@ -1,4 +1,14 @@ -import { Copy, CornerUpLeft, Eye, EyeOff, HatGlasses, Home, Loader2, Scale } from 'lucide-react' +import { + ChevronDown, + Copy, + CornerUpLeft, + Eye, + EyeOff, + HatGlasses, + Home, + Loader2, + Scale, +} from 'lucide-react' import { useEffect, useState } from 'react' import { siGithub } from 'simple-icons' @@ -6,6 +16,7 @@ import { DEMO_API_KEY, DEMO_BASE_URL, DEMO_MODEL, isTestingEndpoint } from '@/ag import type { ExtConfig, LanguagePreference } from '@/agent/useAgent' import { Button } from '@/components/ui/button' import { Input } from '@/components/ui/input' +import { Switch } from '@/components/ui/switch' interface ConfigPanelProps { config: ExtConfig | null @@ -18,18 +29,26 @@ export function ConfigPanel({ config, onSave, onClose }: ConfigPanelProps) { const [baseURL, setBaseURL] = useState(config?.baseURL || DEMO_BASE_URL) const [model, setModel] = useState(config?.model || DEMO_MODEL) const [language, setLanguage] = useState(config?.language) + const [maxSteps, setMaxSteps] = useState(config?.maxSteps) + const [systemInstruction, setSystemInstruction] = useState(config?.systemInstruction ?? '') + const [experimentalLlmsTxt, setExperimentalLlmsTxt] = useState( + config?.experimentalLlmsTxt ?? false + ) + const [advancedOpen, setAdvancedOpen] = useState(false) const [saving, setSaving] = useState(false) const [userAuthToken, setUserAuthToken] = useState('') const [copied, setCopied] = useState(false) const [showToken, setShowToken] = useState(false) const [showApiKey, setShowApiKey] = useState(false) - // Update local state when config prop changes useEffect(() => { setApiKey(config?.apiKey || DEMO_API_KEY) setBaseURL(config?.baseURL || DEMO_BASE_URL) setModel(config?.model || DEMO_MODEL) setLanguage(config?.language) + setMaxSteps(config?.maxSteps) + setSystemInstruction(config?.systemInstruction ?? '') + setExperimentalLlmsTxt(config?.experimentalLlmsTxt ?? false) }, [config]) // Poll for user auth token every second until found @@ -67,7 +86,15 @@ export function ConfigPanel({ config, onSave, onClose }: ConfigPanelProps) { const handleSave = async () => { setSaving(true) try { - await onSave({ apiKey, baseURL, model, language }) + await onSave({ + apiKey, + baseURL, + model, + language, + maxSteps: maxSteps || undefined, + systemInstruction: systemInstruction || undefined, + experimentalLlmsTxt, + }) } finally { setSaving(false) } @@ -87,28 +114,11 @@ export function ConfigPanel({ config, onSave, onClose }: ConfigPanelProps) { - {/* Testing API notice */} - {isTestingEndpoint(baseURL) && ( -
- - You are using the free testing API. By using this service you agree to the{' '} - - Terms of Use & Privacy Policy - - . No sensitive data. No guaranteed availability. -
- )} - {/* User Auth Token Section */}

- Add this token to a website's localStorage to give it authorization to call this extension + Give a website the ability to call this extension.

+ {/* Testing API notice */} + {isTestingEndpoint(baseURL) && ( +
+ + You are using the free testing API. By using this service you agree to the{' '} + + Terms of Use & Privacy Policy + + . No sensitive data. No guaranteed availability. +
+ )} +
+ {/* Advanced Config */} + + + {advancedOpen && ( + <> +
+ + setMaxSteps(e.target.value ? Number(e.target.value) : undefined)} + className="text-xs h-8 [&::-webkit-inner-spin-button]:appearance-none [&::-webkit-outer-spin-button]:appearance-none [-moz-appearance:textfield]" + /> +
+ +
+ +