Compare commits

...

10 Commits

Author SHA1 Message Date
Simon 27e9e78636 chore(version): bump version to 1.5.2 2026-03-07 03:08:33 +08:00
Simon a0c979602e feat: do not throw for webgl2 fail 2026-03-07 03:07:21 +08:00
Simon 3dc9edb8b5 fix(ext): ts types 2026-03-06 17:39:09 +08:00
Simon 32b68ab7c8 fix(docs): broken demo video 2026-03-06 16:07:22 +08:00
Simon 75a61c05c1 docs(terms): wording
Clarify the note regarding data processing location for the demo.
2026-03-06 04:33:03 +08:00
Simon bdfa98358b fix: requestIdleCallback on safari 2026-03-06 02:35:01 +08:00
Simon dc8b38ccb9 chore(ext): bump extension version to 0.1.11 2026-03-05 20:48:00 +08:00
Simon e1c288aaeb docs(changelog): 1.5.1 2026-03-05 20:44:26 +08:00
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
21 changed files with 246 additions and 111 deletions
+3 -3
View File
@@ -13,7 +13,7 @@ The GUI Agent Living in Your Webpage. Control web interfaces with natural langua
👉 <a href="https://alibaba.github.io/page-agent/" target="_blank"><b>🚀 Demo</b></a> | <a href="https://alibaba.github.io/page-agent/docs/introduction/overview" target="_blank"><b>📖 Documentation</b></a> 👉 <a href="https://alibaba.github.io/page-agent/" target="_blank"><b>🚀 Demo</b></a> | <a href="https://alibaba.github.io/page-agent/docs/introduction/overview" target="_blank"><b>📖 Documentation</b></a>
<video id="demo-video" src="https://github.com/user-attachments/assets/11aed429-b69c-49d5-8982-fa99b4a0e9a8" controls crossorigin muted></video> <video id="demo-video" src="https://github.com/user-attachments/assets/a1f2eae2-13fb-4aae-98cf-a3fc1620a6c2" controls crossorigin muted></video>
--- ---
@@ -49,8 +49,8 @@ Fastest way to try PageAgent with our free Demo LLM:
| Mirrors | URL | | Mirrors | URL |
| ------- | ---------------------------------------------------------------------------------- | | ------- | ---------------------------------------------------------------------------------- |
| Global | https://cdn.jsdelivr.net/npm/page-agent@1.4.4/dist/iife/page-agent.demo.js | | Global | https://cdn.jsdelivr.net/npm/page-agent@1.5.2/dist/iife/page-agent.demo.js |
| China | https://registry.npmmirror.com/page-agent/1.4.4/files/dist/iife/page-agent.demo.js | | China | https://registry.npmmirror.com/page-agent/1.5.2/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). > **⚠️ 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).
+31
View File
@@ -5,6 +5,37 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [1.5.1] - 2026-03-05
### Breaking Changes
- **`data-browser-use-ignore``data-page-agent-ignore`** - DOM ignore attribute renamed to match the project identity
- **Config types restructured** - `PageAgentConfig` split into `AgentConfig` + `PageAgentCoreConfig`; config definitions moved from `config/index.ts` to `types.ts`
- **Zod v3/v4 dual support** - Libraries now accept both `zod@^3.25` and `zod@^4.0` as peer dependencies
### Features
- **Experimental `llms.txt` support** - Agent can fetch and include a site's `llms.txt` in context. Enable via `experimentalLlmsTxt: true`
### Improvements
- Default `maxSteps` changed from 20 to 40 for better for complex tasks out of the box
- Added 400ms wait between agent steps for page reactions
- Increased click wait time (100ms → 200ms) for more reliable interactions
- Removed debug `console.log` statements from scroll actions
- Reset observations on new task start
- Improved logging across packages
### Extension v0.1.9
> PageAgent 1.5.1
- **Advanced config panel** - New collapsible section exposing Max Steps, System Instruction, and experimental `llms.txt` toggle
- Streamlined User Auth Token description
- Moved testing API notice below auth token section
---
## [1.4.0] - 2026-02-27 ## [1.4.0] - 2026-02-27
### Features ### Features
+3 -3
View File
@@ -13,7 +13,7 @@
👉 <a href="https://alibaba.github.io/page-agent/" target="_blank"><b>🚀 Demo</b></a> | <a href="https://alibaba.github.io/page-agent/docs/introduction/overview" target="_blank"><b>📖 Documentation</b></a> 👉 <a href="https://alibaba.github.io/page-agent/" target="_blank"><b>🚀 Demo</b></a> | <a href="https://alibaba.github.io/page-agent/docs/introduction/overview" target="_blank"><b>📖 Documentation</b></a>
<video id="demo-video" src="https://github.com/user-attachments/assets/11aed429-b69c-49d5-8982-fa99b4a0e9a8" controls crossorigin muted></video> <video id="demo-video" src="https://github.com/user-attachments/assets/a1f2eae2-13fb-4aae-98cf-a3fc1620a6c2" controls crossorigin muted></video>
--- ---
@@ -49,8 +49,8 @@
| Mirrors | URL | | Mirrors | URL |
| ------- | ---------------------------------------------------------------------------------- | | ------- | ---------------------------------------------------------------------------------- |
| Global | https://cdn.jsdelivr.net/npm/page-agent@1.4.4/dist/iife/page-agent.demo.js | | Global | https://cdn.jsdelivr.net/npm/page-agent@1.5.2/dist/iife/page-agent.demo.js |
| China | https://registry.npmmirror.com/page-agent/1.4.4/files/dist/iife/page-agent.demo.js | | China | https://registry.npmmirror.com/page-agent/1.5.2/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)。 > **⚠️ 仅用于技术评估。** 该 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)。
+1 -1
View File
@@ -36,7 +36,7 @@ This free testing API is provided **strictly for technical evaluation and R&D pu
**Recommendation for Real Usage**: For secure and continuous usage, we strongly advise using the default BYOK mode with your own legally compliant commercial LLM API keys, or connecting to local, offline models (e.g., Ollama). **Recommendation for Real Usage**: For secure and continuous usage, we strongly advise using the default BYOK mode with your own legally compliant commercial LLM API keys, or connecting to local, offline models (e.g., Ollama).
**Note**: This service processes data via servers located in Mainland China. If you are located in a region with strict data localization laws (such as the EU/EEA), please do not use this demo. **Note**: This testing LLM api processes data via servers located in Mainland China. If you are located in a region with strict data localization laws (such as the EU/EEA), please do not use this demo.
--- ---
+19 -19
View File
@@ -1,12 +1,12 @@
{ {
"name": "root", "name": "root",
"version": "1.4.4", "version": "1.5.2",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "root", "name": "root",
"version": "1.4.4", "version": "1.5.2",
"license": "MIT", "license": "MIT",
"workspaces": [ "workspaces": [
"packages/page-controller", "packages/page-controller",
@@ -11113,11 +11113,11 @@
}, },
"packages/core": { "packages/core": {
"name": "@page-agent/core", "name": "@page-agent/core",
"version": "1.4.4", "version": "1.5.2",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@page-agent/llms": "1.4.4", "@page-agent/llms": "1.5.2",
"@page-agent/page-controller": "1.4.4", "@page-agent/page-controller": "1.5.2",
"chalk": "^5.6.2" "chalk": "^5.6.2"
}, },
"devDependencies": { "devDependencies": {
@@ -11129,13 +11129,13 @@
}, },
"packages/extension": { "packages/extension": {
"name": "@page-agent/ext", "name": "@page-agent/ext",
"version": "0.1.8", "version": "0.1.11",
"hasInstallScript": true, "hasInstallScript": true,
"dependencies": { "dependencies": {
"@page-agent/core": "1.4.4", "@page-agent/core": "1.5.2",
"@page-agent/llms": "1.4.4", "@page-agent/llms": "1.5.2",
"@page-agent/page-controller": "1.4.4", "@page-agent/page-controller": "1.5.2",
"@page-agent/ui": "1.4.4", "@page-agent/ui": "1.5.2",
"ai-motion": "^0.4.8", "ai-motion": "^0.4.8",
"chalk": "^5.6.2" "chalk": "^5.6.2"
}, },
@@ -11173,7 +11173,7 @@
}, },
"packages/llms": { "packages/llms": {
"name": "@page-agent/llms", "name": "@page-agent/llms",
"version": "1.4.4", "version": "1.5.2",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"chalk": "^5.6.2" "chalk": "^5.6.2"
@@ -11186,13 +11186,13 @@
} }
}, },
"packages/page-agent": { "packages/page-agent": {
"version": "1.4.4", "version": "1.5.2",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@page-agent/core": "1.4.4", "@page-agent/core": "1.5.2",
"@page-agent/llms": "1.4.4", "@page-agent/llms": "1.5.2",
"@page-agent/page-controller": "1.4.4", "@page-agent/page-controller": "1.5.2",
"@page-agent/ui": "1.4.4", "@page-agent/ui": "1.5.2",
"chalk": "^5.6.2" "chalk": "^5.6.2"
}, },
"devDependencies": { "devDependencies": {
@@ -11204,7 +11204,7 @@
}, },
"packages/page-controller": { "packages/page-controller": {
"name": "@page-agent/page-controller", "name": "@page-agent/page-controller",
"version": "1.4.4", "version": "1.5.2",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"ai-motion": "^0.4.8" "ai-motion": "^0.4.8"
@@ -11212,12 +11212,12 @@
}, },
"packages/ui": { "packages/ui": {
"name": "@page-agent/ui", "name": "@page-agent/ui",
"version": "1.4.4", "version": "1.5.2",
"license": "MIT" "license": "MIT"
}, },
"packages/website": { "packages/website": {
"name": "@page-agent/website", "name": "@page-agent/website",
"version": "1.4.4", "version": "1.5.2",
"devDependencies": { "devDependencies": {
"@radix-ui/react-icons": "^1.3.2", "@radix-ui/react-icons": "^1.3.2",
"@radix-ui/react-separator": "^1.1.8", "@radix-ui/react-separator": "^1.1.8",
+1 -1
View File
@@ -1,7 +1,7 @@
{ {
"name": "root", "name": "root",
"private": true, "private": true,
"version": "1.4.4", "version": "1.5.2",
"type": "module", "type": "module",
"workspaces": [ "workspaces": [
"packages/page-controller", "packages/page-controller",
+3 -3
View File
@@ -1,7 +1,7 @@
{ {
"name": "@page-agent/core", "name": "@page-agent/core",
"private": false, "private": false,
"version": "1.4.4", "version": "1.5.2",
"type": "module", "type": "module",
"main": "./dist/esm/page-agent-core.js", "main": "./dist/esm/page-agent-core.js",
"module": "./dist/esm/page-agent-core.js", "module": "./dist/esm/page-agent-core.js",
@@ -44,8 +44,8 @@
}, },
"dependencies": { "dependencies": {
"chalk": "^5.6.2", "chalk": "^5.6.2",
"@page-agent/llms": "1.4.4", "@page-agent/llms": "1.5.2",
"@page-agent/page-controller": "1.4.4" "@page-agent/page-controller": "1.5.2"
}, },
"peerDependencies": { "peerDependencies": {
"zod": "^3.25.0 || ^4.0.0" "zod": "^3.25.0 || ^4.0.0"
+1 -1
View File
@@ -96,7 +96,7 @@ export class PageAgentCore extends EventTarget {
constructor(config: PageAgentCoreConfig) { constructor(config: PageAgentCoreConfig) {
super() super()
this.config = { ...config, maxSteps: config.maxSteps || 40 } this.config = { ...config, maxSteps: config.maxSteps ?? 40 }
this.#llm = new LLM(this.config) this.#llm = new LLM(this.config)
this.tools = new Map(tools) this.tools = new Map(tools)
+5 -5
View File
@@ -1,7 +1,7 @@
{ {
"name": "@page-agent/ext", "name": "@page-agent/ext",
"private": true, "private": true,
"version": "0.1.8", "version": "0.1.11",
"type": "module", "type": "module",
"scripts": { "scripts": {
"dev": "wxt", "dev": "wxt",
@@ -38,10 +38,10 @@
"wxt": "^0.20.18" "wxt": "^0.20.18"
}, },
"dependencies": { "dependencies": {
"@page-agent/core": "1.4.4", "@page-agent/core": "1.5.2",
"@page-agent/llms": "1.4.4", "@page-agent/llms": "1.5.2",
"@page-agent/page-controller": "1.4.4", "@page-agent/page-controller": "1.5.2",
"@page-agent/ui": "1.4.4", "@page-agent/ui": "1.5.2",
"ai-motion": "^0.4.8", "ai-motion": "^0.4.8",
"chalk": "^5.6.2" "chalk": "^5.6.2"
}, },
@@ -1,4 +1,4 @@
import { type PageAgentConfig, PageAgentCore } from '@page-agent/core' import { type AgentConfig, PageAgentCore } from '@page-agent/core'
import { RemotePageController } from './RemotePageController' import { RemotePageController } from './RemotePageController'
import { TabsController } from './TabsController' import { TabsController } from './TabsController'
@@ -17,7 +17,7 @@ function detectLanguage(): 'en-US' | 'zh-CN' {
* - can be used from a side panel or a content script * - can be used from a side panel or a content script
*/ */
export class MultiPageAgent extends PageAgentCore { export class MultiPageAgent extends PageAgentCore {
constructor(config: Omit<PageAgentConfig, 'pageController'> & { includeInitialTab?: boolean }) { constructor(config: AgentConfig & { includeInitialTab?: boolean }) {
// multi page controller // multi page controller
const tabsController = new TabsController() const tabsController = new TabsController()
const pageController = new RemotePageController(tabsController) const pageController = new RemotePageController(tabsController)
+35 -13
View File
@@ -16,7 +16,13 @@ import { DEMO_CONFIG, migrateLegacyEndpoint } from './constants'
/** Language preference: undefined means follow system */ /** Language preference: undefined means follow system */
export type LanguagePreference = SupportedLanguage | undefined 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 language?: LanguagePreference
} }
@@ -40,9 +46,10 @@ export function useAgent(): UseAgentResult {
const [config, setConfig] = useState<ExtConfig | null>(null) const [config, setConfig] = useState<ExtConfig | null>(null)
useEffect(() => { 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 let llmConfig = (result.llmConfig as LLMConfig) ?? DEMO_CONFIG
const language = (result.language as SupportedLanguage) || undefined const language = (result.language as SupportedLanguage) || undefined
const advancedConfig = (result.advancedConfig as AdvancedConfig) ?? {}
// Auto-migrate legacy testing endpoints // Auto-migrate legacy testing endpoints
const migrated = migrateLegacyEndpoint(llmConfig) const migrated = migrateLegacyEndpoint(llmConfig)
@@ -53,14 +60,18 @@ export function useAgent(): UseAgentResult {
chrome.storage.local.set({ llmConfig: DEMO_CONFIG }) chrome.storage.local.set({ llmConfig: DEMO_CONFIG })
} }
setConfig({ ...llmConfig, language }) setConfig({ ...llmConfig, ...advancedConfig, language })
}) })
}, []) }, [])
useEffect(() => { useEffect(() => {
if (!config) return 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 agentRef.current = agent
const handleStatusChange = (e: Event) => { const handleStatusChange = (e: Event) => {
@@ -106,15 +117,26 @@ export function useAgent(): UseAgentResult {
agentRef.current?.stop() agentRef.current?.stop()
}, []) }, [])
const configure = useCallback(async ({ language, ...llmConfig }: ExtConfig) => { const configure = useCallback(
await chrome.storage.local.set({ llmConfig }) async ({
if (language) { language,
await chrome.storage.local.set({ language }) maxSteps,
} else { systemInstruction,
await chrome.storage.local.remove('language') experimentalLlmsTxt,
} ...llmConfig
setConfig({ ...llmConfig, language }) }: 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 { return {
status, 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 { useEffect, useState } from 'react'
import { siGithub } from 'simple-icons' 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 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'
import { Switch } from '@/components/ui/switch'
interface ConfigPanelProps { interface ConfigPanelProps {
config: ExtConfig | null config: ExtConfig | null
@@ -18,18 +29,26 @@ export function ConfigPanel({ config, onSave, onClose }: ConfigPanelProps) {
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 [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 [saving, setSaving] = useState(false)
const [userAuthToken, setUserAuthToken] = useState<string>('') const [userAuthToken, setUserAuthToken] = useState<string>('')
const [copied, setCopied] = useState(false) const [copied, setCopied] = useState(false)
const [showToken, setShowToken] = useState(false) const [showToken, setShowToken] = useState(false)
const [showApiKey, setShowApiKey] = useState(false) const [showApiKey, setShowApiKey] = useState(false)
// Update local state when config prop changes
useEffect(() => { useEffect(() => {
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) setLanguage(config?.language)
setMaxSteps(config?.maxSteps)
setSystemInstruction(config?.systemInstruction ?? '')
setExperimentalLlmsTxt(config?.experimentalLlmsTxt ?? false)
}, [config]) }, [config])
// Poll for user auth token every second until found // Poll for user auth token every second until found
@@ -67,7 +86,15 @@ export function ConfigPanel({ config, onSave, onClose }: ConfigPanelProps) {
const handleSave = async () => { const handleSave = async () => {
setSaving(true) setSaving(true)
try { try {
await onSave({ apiKey, baseURL, model, language }) await onSave({
apiKey,
baseURL,
model,
language,
maxSteps: maxSteps || undefined,
systemInstruction: systemInstruction || undefined,
experimentalLlmsTxt,
})
} finally { } finally {
setSaving(false) setSaving(false)
} }
@@ -87,28 +114,11 @@ export function ConfigPanel({ config, onSave, onClose }: ConfigPanelProps) {
</Button> </Button>
</div> </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 */} {/* User Auth Token Section */}
<div className="flex flex-col gap-1.5 p-3 bg-muted/50 rounded-md border"> <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> <label className="text-xs font-medium text-muted-foreground">User Auth Token</label>
<p className="text-[10px] text-muted-foreground mb-1"> <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> </p>
<div className="flex gap-2 items-center"> <div className="flex gap-2 items-center">
<Input <Input
@@ -153,6 +163,23 @@ export function ConfigPanel({ config, onSave, onClose }: ConfigPanelProps) {
/> />
</div> </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"> <div className="flex flex-col gap-1.5">
<label className="text-xs text-muted-foreground">Model</label> <label className="text-xs text-muted-foreground">Model</label>
<Input <Input
@@ -197,6 +224,52 @@ export function ConfigPanel({ config, onSave, onClose }: ConfigPanelProps) {
</select> </select>
</div> </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"> <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
@@ -43,20 +43,24 @@ export function MotionOverlay({ active }: { active: boolean }) {
const motionRef = useRef<Motion | null>(null) const motionRef = useRef<Motion | null>(null)
useEffect(() => { useEffect(() => {
const mode = document.documentElement.classList.contains('dark') ? 'dark' : 'light' try {
const motion = new Motion({ const mode = document.documentElement.classList.contains('dark') ? 'dark' : 'light'
mode, const motion = new Motion({
borderWidth: 4, mode,
borderRadius: 14, borderWidth: 4,
glowWidth: mode === 'dark' ? 120 : 60, borderRadius: 14,
styles: { position: 'absolute', inset: '0' }, glowWidth: mode === 'dark' ? 120 : 60,
}) styles: { position: 'absolute', inset: '0' },
motionRef.current = motion })
containerRef.current!.appendChild(motion.element) motionRef.current = motion
motion.autoResize(containerRef.current!) containerRef.current!.appendChild(motion.element)
motion.autoResize(containerRef.current!)
} catch (e) {
console.warn('[MotionOverlay] Motion unavailable:', e)
}
return () => { return () => {
motion.dispose() motionRef.current?.dispose()
motionRef.current = null motionRef.current = null
} }
}, []) }, [])
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "@page-agent/llms", "name": "@page-agent/llms",
"version": "1.4.4", "version": "1.5.2",
"type": "module", "type": "module",
"main": "./dist/lib/page-agent-llms.js", "main": "./dist/lib/page-agent-llms.js",
"module": "./dist/lib/page-agent-llms.js", "module": "./dist/lib/page-agent-llms.js",
+5 -5
View File
@@ -1,7 +1,7 @@
{ {
"name": "page-agent", "name": "page-agent",
"private": false, "private": false,
"version": "1.4.4", "version": "1.5.2",
"type": "module", "type": "module",
"main": "./dist/esm/page-agent.js", "main": "./dist/esm/page-agent.js",
"module": "./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{}})\"" "postpublish": "node -e \"['README.md','LICENSE'].forEach(f=>{try{require('fs').unlinkSync(f)}catch{}})\""
}, },
"dependencies": { "dependencies": {
"@page-agent/core": "1.4.4", "@page-agent/core": "1.5.2",
"@page-agent/llms": "1.4.4", "@page-agent/llms": "1.5.2",
"@page-agent/page-controller": "1.4.4", "@page-agent/page-controller": "1.5.2",
"@page-agent/ui": "1.4.4", "@page-agent/ui": "1.5.2",
"chalk": "^5.6.2" "chalk": "^5.6.2"
}, },
"peerDependencies": { "peerDependencies": {
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "@page-agent/page-controller", "name": "@page-agent/page-controller",
"version": "1.4.4", "version": "1.5.2",
"type": "module", "type": "module",
"main": "./dist/lib/page-controller.js", "main": "./dist/lib/page-controller.js",
"module": "./dist/lib/page-controller.js", "module": "./dist/lib/page-controller.js",
@@ -8,13 +8,7 @@ import cursorStyles from './cursor.module.css'
export class SimulatorMask { export class SimulatorMask {
shown: boolean = false shown: boolean = false
wrapper = document.createElement('div') wrapper = document.createElement('div')
motion = new Motion({ motion: Motion | null = null
mode: isPageDark() ? 'dark' : 'light',
styles: {
position: 'absolute',
inset: '0',
},
})
#cursor = document.createElement('div') #cursor = document.createElement('div')
@@ -30,8 +24,17 @@ export class SimulatorMask {
this.wrapper.setAttribute('data-browser-use-ignore', 'true') this.wrapper.setAttribute('data-browser-use-ignore', 'true')
this.wrapper.setAttribute('data-page-agent-ignore', 'true') this.wrapper.setAttribute('data-page-agent-ignore', 'true')
this.wrapper.appendChild(this.motion.element) try {
this.motion.autoResize(this.wrapper) const motion = new Motion({
mode: isPageDark() ? 'dark' : 'light',
styles: { position: 'absolute', inset: '0' },
})
this.motion = motion
this.wrapper.appendChild(motion.element)
motion.autoResize(this.wrapper)
} catch (e) {
console.warn('[SimulatorMask] Motion overlay unavailable:', e)
}
// Capture all mouse, keyboard, and wheel events // Capture all mouse, keyboard, and wheel events
this.wrapper.addEventListener('click', (e) => { this.wrapper.addEventListener('click', (e) => {
@@ -145,8 +148,8 @@ export class SimulatorMask {
if (this.shown) return if (this.shown) return
this.shown = true this.shown = true
this.motion.start() this.motion?.start()
this.motion.fadeIn() this.motion?.fadeIn()
this.wrapper.style.display = 'block' this.wrapper.style.display = 'block'
@@ -163,8 +166,8 @@ export class SimulatorMask {
if (!this.shown) return if (!this.shown) return
this.shown = false this.shown = false
this.motion.fadeOut() this.motion?.fadeOut()
this.motion.pause() this.motion?.pause()
this.#cursor.classList.remove(cursorStyles.clicking) this.#cursor.classList.remove(cursorStyles.clicking)
@@ -174,7 +177,7 @@ export class SimulatorMask {
} }
dispose() { dispose() {
this.motion.dispose() this.motion?.dispose()
this.wrapper.remove() this.wrapper.remove()
} }
} }
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "@page-agent/ui", "name": "@page-agent/ui",
"version": "1.4.4", "version": "1.5.2",
"type": "module", "type": "module",
"main": "./dist/lib/page-agent-ui.js", "main": "./dist/lib/page-agent-ui.js",
"module": "./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", "name": "@page-agent/website",
"private": true, "private": true,
"version": "1.4.4", "version": "1.5.2",
"type": "module", "type": "module",
"scripts": { "scripts": {
"dev": "vite --host 0.0.0.0", "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) // Demo build (auto-init with demo LLM, for quick testing)
export const CDN_DEMO_URL = 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.2/dist/iife/page-agent.demo.js'
export const CDN_DEMO_CN_URL = 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.2/files/dist/iife/page-agent.demo.js'
// Demo LLM for website testing (homepage quick trial uses flash) // Demo LLM for website testing (homepage quick trial uses flash)
export const DEMO_MODEL = 'qwen3.5-flash' export const DEMO_MODEL = 'qwen3.5-flash'
+4 -2
View File
@@ -18,8 +18,10 @@ function ScrollToTop() {
export default function Router() { export default function Router() {
useEffect(() => { useEffect(() => {
const id = requestIdleCallback(() => docsImport()) const schedule = globalThis.requestIdleCallback ?? ((cb: () => void) => setTimeout(cb, 1))
return () => cancelIdleCallback(id) const cancel = globalThis.cancelIdleCallback ?? clearTimeout
const id = schedule(() => docsImport())
return () => cancel(id)
}, []) }, [])
return ( return (