Compare commits

...

2 Commits

Author SHA1 Message Date
Simon 7a97de2a37 feat(ext): expose more config 2026-03-05 20:34:55 +08:00
Simon 19b03b83ea chore(version): bump version to 1.5.1 2026-03-05 19:28:19 +08:00
15 changed files with 171 additions and 76 deletions
+2 -2
View File
@@ -49,8 +49,8 @@ Fastest way to try PageAgent with our free Demo LLM:
| Mirrors | URL |
| ------- | ---------------------------------------------------------------------------------- |
| Global | https://cdn.jsdelivr.net/npm/page-agent@1.4.4/dist/iife/page-agent.demo.js |
| China | https://registry.npmmirror.com/page-agent/1.4.4/files/dist/iife/page-agent.demo.js |
| Global | https://cdn.jsdelivr.net/npm/page-agent@1.5.1/dist/iife/page-agent.demo.js |
| China | https://registry.npmmirror.com/page-agent/1.5.1/files/dist/iife/page-agent.demo.js |
> **⚠️ For technical evaluation only.** This demo CDN uses our free [testing LLM API](https://alibaba.github.io/page-agent/docs/features/models#free-testing-api). By using it, you agree to its [terms](https://github.com/alibaba/page-agent/blob/main/docs/terms-and-privacy.md).
+2 -2
View File
@@ -49,8 +49,8 @@
| Mirrors | URL |
| ------- | ---------------------------------------------------------------------------------- |
| Global | https://cdn.jsdelivr.net/npm/page-agent@1.4.4/dist/iife/page-agent.demo.js |
| China | https://registry.npmmirror.com/page-agent/1.4.4/files/dist/iife/page-agent.demo.js |
| Global | https://cdn.jsdelivr.net/npm/page-agent@1.5.1/dist/iife/page-agent.demo.js |
| China | https://registry.npmmirror.com/page-agent/1.5.1/files/dist/iife/page-agent.demo.js |
> **⚠️ 仅用于技术评估。** 该 Demo CDN 使用了免费的[测试 LLM API](https://alibaba.github.io/page-agent/docs/features/models#free-testing-api),使用即表示您同意其[条款](https://github.com/alibaba/page-agent/blob/main/docs/terms-and-privacy.md)。
+18 -18
View File
@@ -1,12 +1,12 @@
{
"name": "root",
"version": "1.4.4",
"version": "1.5.1",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "root",
"version": "1.4.4",
"version": "1.5.1",
"license": "MIT",
"workspaces": [
"packages/page-controller",
@@ -11113,11 +11113,11 @@
},
"packages/core": {
"name": "@page-agent/core",
"version": "1.4.4",
"version": "1.5.1",
"license": "MIT",
"dependencies": {
"@page-agent/llms": "1.4.4",
"@page-agent/page-controller": "1.4.4",
"@page-agent/llms": "1.5.1",
"@page-agent/page-controller": "1.5.1",
"chalk": "^5.6.2"
},
"devDependencies": {
@@ -11132,10 +11132,10 @@
"version": "0.1.8",
"hasInstallScript": true,
"dependencies": {
"@page-agent/core": "1.4.4",
"@page-agent/llms": "1.4.4",
"@page-agent/page-controller": "1.4.4",
"@page-agent/ui": "1.4.4",
"@page-agent/core": "1.5.1",
"@page-agent/llms": "1.5.1",
"@page-agent/page-controller": "1.5.1",
"@page-agent/ui": "1.5.1",
"ai-motion": "^0.4.8",
"chalk": "^5.6.2"
},
@@ -11173,7 +11173,7 @@
},
"packages/llms": {
"name": "@page-agent/llms",
"version": "1.4.4",
"version": "1.5.1",
"license": "MIT",
"dependencies": {
"chalk": "^5.6.2"
@@ -11186,13 +11186,13 @@
}
},
"packages/page-agent": {
"version": "1.4.4",
"version": "1.5.1",
"license": "MIT",
"dependencies": {
"@page-agent/core": "1.4.4",
"@page-agent/llms": "1.4.4",
"@page-agent/page-controller": "1.4.4",
"@page-agent/ui": "1.4.4",
"@page-agent/core": "1.5.1",
"@page-agent/llms": "1.5.1",
"@page-agent/page-controller": "1.5.1",
"@page-agent/ui": "1.5.1",
"chalk": "^5.6.2"
},
"devDependencies": {
@@ -11204,7 +11204,7 @@
},
"packages/page-controller": {
"name": "@page-agent/page-controller",
"version": "1.4.4",
"version": "1.5.1",
"license": "MIT",
"dependencies": {
"ai-motion": "^0.4.8"
@@ -11212,12 +11212,12 @@
},
"packages/ui": {
"name": "@page-agent/ui",
"version": "1.4.4",
"version": "1.5.1",
"license": "MIT"
},
"packages/website": {
"name": "@page-agent/website",
"version": "1.4.4",
"version": "1.5.1",
"devDependencies": {
"@radix-ui/react-icons": "^1.3.2",
"@radix-ui/react-separator": "^1.1.8",
+1 -1
View File
@@ -1,7 +1,7 @@
{
"name": "root",
"private": true,
"version": "1.4.4",
"version": "1.5.1",
"type": "module",
"workspaces": [
"packages/page-controller",
+3 -3
View File
@@ -1,7 +1,7 @@
{
"name": "@page-agent/core",
"private": false,
"version": "1.4.4",
"version": "1.5.1",
"type": "module",
"main": "./dist/esm/page-agent-core.js",
"module": "./dist/esm/page-agent-core.js",
@@ -44,8 +44,8 @@
},
"dependencies": {
"chalk": "^5.6.2",
"@page-agent/llms": "1.4.4",
"@page-agent/page-controller": "1.4.4"
"@page-agent/llms": "1.5.1",
"@page-agent/page-controller": "1.5.1"
},
"peerDependencies": {
"zod": "^3.25.0 || ^4.0.0"
+1 -1
View File
@@ -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)
+4 -4
View File
@@ -38,10 +38,10 @@
"wxt": "^0.20.18"
},
"dependencies": {
"@page-agent/core": "1.4.4",
"@page-agent/llms": "1.4.4",
"@page-agent/page-controller": "1.4.4",
"@page-agent/ui": "1.4.4",
"@page-agent/core": "1.5.1",
"@page-agent/llms": "1.5.1",
"@page-agent/page-controller": "1.5.1",
"@page-agent/ui": "1.5.1",
"ai-motion": "^0.4.8",
"chalk": "^5.6.2"
},
+35 -13
View File
@@ -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<ExtConfig | null>(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,
@@ -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<LanguagePreference>(config?.language)
const [maxSteps, setMaxSteps] = useState<number | undefined>(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<string>('')
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) {
</Button>
</div>
{/* Testing API notice */}
{isTestingEndpoint(baseURL) && (
<div className="p-2.5 rounded-md border border-amber-500/30 bg-amber-500/5 text-[10px] text-muted-foreground leading-relaxed">
<Scale className="size-3 inline-block mr-1 -mt-0.5 text-amber-600" />
You are using the free testing API. By using this service you agree to the{' '}
<a
href="https://github.com/alibaba/page-agent/blob/main/docs/terms-and-privacy.md"
target="_blank"
rel="noopener noreferrer"
className="underline hover:text-foreground"
>
Terms of Use & Privacy Policy
</a>
. No sensitive data. No guaranteed availability.
</div>
)}
{/* User Auth Token Section */}
<div className="flex flex-col gap-1.5 p-3 bg-muted/50 rounded-md border">
<label className="text-xs font-medium text-muted-foreground">User Auth Token</label>
<p className="text-[10px] text-muted-foreground mb-1">
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.
</p>
<div className="flex gap-2 items-center">
<Input
@@ -153,6 +163,23 @@ export function ConfigPanel({ config, onSave, onClose }: ConfigPanelProps) {
/>
</div>
{/* Testing API notice */}
{isTestingEndpoint(baseURL) && (
<div className="p-2.5 rounded-md border border-amber-500/30 bg-amber-500/5 text-[11px] text-muted-foreground leading-relaxed">
<Scale className="size-3 inline-block mr-1 -mt-0.5 text-amber-600" />
You are using the free testing API. By using this service you agree to the{' '}
<a
href="https://github.com/alibaba/page-agent/blob/main/docs/terms-and-privacy.md"
target="_blank"
rel="noopener noreferrer"
className="underline hover:text-foreground"
>
Terms of Use & Privacy Policy
</a>
. No sensitive data. No guaranteed availability.
</div>
)}
<div className="flex flex-col gap-1.5">
<label className="text-xs text-muted-foreground">Model</label>
<Input
@@ -197,6 +224,52 @@ export function ConfigPanel({ config, onSave, onClose }: ConfigPanelProps) {
</select>
</div>
{/* Advanced Config */}
<button
type="button"
onClick={() => setAdvancedOpen(!advancedOpen)}
className="flex items-center gap-1 text-xs text-muted-foreground hover:text-foreground cursor-pointer mt-1 font-bold"
>
Advanced
<ChevronDown
className="size-3 transition-transform"
style={{ transform: advancedOpen ? 'rotate(0deg)' : 'rotate(90deg)' }}
/>
</button>
{advancedOpen && (
<>
<div className="flex flex-col gap-1.5">
<label className="text-xs text-muted-foreground">Max Steps</label>
<Input
type="number"
placeholder="40"
min={1}
max={200}
value={maxSteps ?? ''}
onChange={(e) => 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]"
/>
</div>
<div className="flex flex-col gap-1.5">
<label className="text-xs text-muted-foreground">System Instruction</label>
<textarea
placeholder="Additional instructions for the agent..."
value={systemInstruction}
onChange={(e) => setSystemInstruction(e.target.value)}
rows={3}
className="text-xs rounded-md border border-input bg-background px-3 py-2 resize-y min-h-[60px]"
/>
</div>
<label className="flex items-center justify-between cursor-pointer">
<span className="text-xs text-muted-foreground">Experimental llms.txt support</span>
<Switch checked={experimentalLlmsTxt} onCheckedChange={setExperimentalLlmsTxt} />
</label>
</>
)}
<div className="flex gap-2 mt-2">
<Button variant="outline" onClick={onClose} className="flex-1 h-8 text-xs cursor-pointer">
Cancel
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@page-agent/llms",
"version": "1.4.4",
"version": "1.5.1",
"type": "module",
"main": "./dist/lib/page-agent-llms.js",
"module": "./dist/lib/page-agent-llms.js",
+5 -5
View File
@@ -1,7 +1,7 @@
{
"name": "page-agent",
"private": false,
"version": "1.4.4",
"version": "1.5.1",
"type": "module",
"main": "./dist/esm/page-agent.js",
"module": "./dist/esm/page-agent.js",
@@ -44,10 +44,10 @@
"postpublish": "node -e \"['README.md','LICENSE'].forEach(f=>{try{require('fs').unlinkSync(f)}catch{}})\""
},
"dependencies": {
"@page-agent/core": "1.4.4",
"@page-agent/llms": "1.4.4",
"@page-agent/page-controller": "1.4.4",
"@page-agent/ui": "1.4.4",
"@page-agent/core": "1.5.1",
"@page-agent/llms": "1.5.1",
"@page-agent/page-controller": "1.5.1",
"@page-agent/ui": "1.5.1",
"chalk": "^5.6.2"
},
"peerDependencies": {
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@page-agent/page-controller",
"version": "1.4.4",
"version": "1.5.1",
"type": "module",
"main": "./dist/lib/page-controller.js",
"module": "./dist/lib/page-controller.js",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@page-agent/ui",
"version": "1.4.4",
"version": "1.5.1",
"type": "module",
"main": "./dist/lib/page-agent-ui.js",
"module": "./dist/lib/page-agent-ui.js",
+1 -1
View File
@@ -1,7 +1,7 @@
{
"name": "@page-agent/website",
"private": true,
"version": "1.4.4",
"version": "1.5.1",
"type": "module",
"scripts": {
"dev": "vite --host 0.0.0.0",
+2 -2
View File
@@ -1,8 +1,8 @@
// Demo build (auto-init with demo LLM, for quick testing)
export const CDN_DEMO_URL =
'https://cdn.jsdelivr.net/npm/page-agent@1.4.4/dist/iife/page-agent.demo.js'
'https://cdn.jsdelivr.net/npm/page-agent@1.5.1/dist/iife/page-agent.demo.js'
export const CDN_DEMO_CN_URL =
'https://registry.npmmirror.com/page-agent/1.4.4/files/dist/iife/page-agent.demo.js'
'https://registry.npmmirror.com/page-agent/1.5.1/files/dist/iife/page-agent.demo.js'
// Demo LLM for website testing (homepage quick trial uses flash)
export const DEMO_MODEL = 'qwen3.5-flash'