Compare commits

...

5 Commits

Author SHA1 Message Date
Simon f83a4174cc chore(version): bump version to 1.0.0-beta.0 2026-01-19 20:39:57 +08:00
Simon 334512210d feat: improve lifecycle hooks API; wait a little after url change 2026-01-19 20:39:03 +08:00
Simon 3df71788ff docs: update package descriptions 2026-01-19 20:14:40 +08:00
Simon 60450ea7be chore: export tool from PageAgent package 2026-01-19 20:12:46 +08:00
Simon 80c93bd668 feat: expose maxSteps config 2026-01-19 20:11:53 +08:00
18 changed files with 244 additions and 106 deletions
+18 -18
View File
@@ -31,8 +31,8 @@ Simple monorepo solution: TypeScript references + Vite aliases. Update tsconfig
```
packages/
├── page-agent/ # npm: "page-agent" ⭐ MAIN (with Panel UI + IIFE builds)
├── core/ # npm: "@page-agent/core" (headless, no UI)
├── core/ # npm: "@page-agent/core" ⭐ Core agent logic (headless)
├── page-agent/ # npm: "page-agent" entry class (with UI + controller + demo builds)
├── website/ # @page-agent/website (private)
├── llms/ # @page-agent/llms
├── page-controller/ # @page-agent/page-controller
@@ -89,28 +89,28 @@ Build with `npm run build:iife --workspace=page-agent`.
### Page Agent (`packages/page-agent/`)
| File | Description |
| ----------------------- | -------------------------------------------- |
| `src/PageAgent.ts` | ⭐ Main class with UI, extends PageAgentCore |
| `src/entry-iife.ts` | IIFE entry (exposes PageAgent class) |
| `src/entry-iife-demo.ts`| IIFE demo entry (auto-init with demo API) |
| File | Description |
| ------------------------ | -------------------------------------------- |
| `src/PageAgent.ts` | ⭐ Main class with UI, extends PageAgentCore |
| `src/entry-iife.ts` | IIFE entry (exposes PageAgent class) |
| `src/entry-iife-demo.ts` | IIFE demo entry (auto-init with demo API) |
### Core (`packages/core/`)
| File | Description |
| ----------------------- | ------------------------------------------- |
| `src/PageAgentCore.ts` | ⭐ Core agent class without UI |
| `src/tools/` | Tool definitions calling PageController |
| `src/config/` | Configuration types and constants |
| `src/prompts/` | System prompt templates |
| File | Description |
| ---------------------- | --------------------------------------- |
| `src/PageAgentCore.ts` | ⭐ Core agent class without UI |
| `src/tools/` | Tool definitions calling PageController |
| `src/config/` | Configuration types and constants |
| `src/prompts/` | System prompt templates |
### LLMs (`packages/llms/`)
| File | Description |
| ---------------------------- | ------------------------------------- |
| `src/index.ts` | ⭐ LLM class with retry logic |
| `src/types.ts` | MacroToolInput, AgentBrain, LLMConfig |
| `src/OpenAILenientClient.ts` | OpenAI-compatible client |
| File | Description |
| --------------------- | ------------------------------------- |
| `src/index.ts` | ⭐ LLM class with retry logic |
| `src/types.ts` | MacroToolInput, AgentBrain, LLMConfig |
| `src/OpenAIClient.ts` | OpenAI-compatible client |
### Page Controller (`packages/page-controller/`)
+94
View File
@@ -0,0 +1,94 @@
# Changelog
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/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [1.0.0] - 2026-01-19
### 🎉 First Stable Release
PageAgent is now ready for production use. The API is stable and breaking changes will follow semantic versioning.
### Features
#### Core
- **PageAgent** - Main entry class with built-in UI Panel
- **PageAgentCore** - Headless agent class for custom UI or programmatic use
- **DOM Analysis** - Text-based DOM extraction with high-intensity dehydration
- **LLM Support** - Works with OpenAI, Claude, DeepSeek, Qwen, and other OpenAI-compatible APIs
- **Tool System** - Built-in tools for click, input, scroll, select, and more
- **Custom Tools** - Extend agent capabilities with your own tools (experimental)
- **Lifecycle Hooks** - Hook into agent execution (experimental)
- **Instructions System** - System-level and page-level instructions to guide agent behavior
- **Data Masking** - Transform page content before sending to LLM
#### Page Controller
- **Element Interactions** - Click, input text, select options, scroll
- **Visual Mask** - Blocks user interaction during automation
- **DOM Tree Extraction** - Efficient page structure extraction for LLM consumption
#### UI
- **Interactive Panel** - Real-time task progress and agent thinking display
- **Ask User Tool** - Agent can ask users for clarification
- **i18n Support** - English and Chinese localization
### Configuration
```typescript
interface PageAgentConfig {
// LLM Configuration (required)
baseURL: string
apiKey: string
model: string
temperature?: number
maxRetries?: number
customFetch?: typeof fetch
// Agent Configuration
language?: 'en-US' | 'zh-CN'
maxSteps?: number // default: 20
customTools?: Record<string, PageAgentTool> // experimental
instructions?: InstructionsConfig
transformPageContent?: (content: string) => string | Promise<string>
experimentalScriptExecutionTool?: boolean // default: false
// Lifecycle Hooks (experimental)
onBeforeTask?: (agent, result) => void
onAfterTask?: (agent, result) => void
onBeforeStep?: (agent, stepCount) => void
onAfterStep?: (agent, history) => void
onDispose?: (agent, reason?) => void
// Page Controller Configuration
enableMask?: boolean // default: true
viewportExpansion?: number
interactiveBlacklist?: Element[]
interactiveWhitelist?: Element[]
}
```
### Packages
| Package | Description |
| ----------------------------- | ---------------------------------- |
| `page-agent` | Main entry with UI Panel |
| `@page-agent/core` | Core agent logic without UI |
| `@page-agent/llms` | LLM client with retry logic |
| `@page-agent/page-controller` | DOM operations and visual feedback |
| `@page-agent/ui` | Panel and i18n |
### Known Limitations
- Single-page application only (cannot navigate across pages)
- No visual recognition (relies on DOM structure)
- Limited interaction support (no hover, drag-drop, canvas operations)
- See [Limitations](https://alibaba.github.io/page-agent/#/docs/introduction/limitations) for details
### Acknowledgments
This project builds upon the excellent work of [browser-use](https://github.com/browser-use/browser-use). DOM processing components and prompts are adapted from browser-use (MIT License).
+2 -2
View File
@@ -76,8 +76,8 @@ PageAgent adopts a simplified monorepo structure:
```
packages/
├── page-agent/ # AI agent and demo(npm: page-agent)
├── core/ # Agent core logic without UI(npm: @page-agent/core)
├── core/ # ** Core agent logic without UI(npm: @page-agent/core) **
├── page-agent/ # Exported agent and demo(npm: page-agent)
├── llms/ # LLM 客户端 (npm: @page-agent/llms)
├── page-controller/ # DOM 操作 & 蒙层 & 模拟鼠标 (npm: @page-agent/page-controller)
├── ui/ # 面板 & i18n (npm: @page-agent/ui)
+2 -2
View File
@@ -74,8 +74,8 @@ PageAgent adopts a simplified monorepo structure:
```
packages/
├── page-agent/ # AI agent and demo(npm: page-agent)
├── core/ # Agent core logic without UI(npm: @page-agent/core)
├── core/ # ** Core agent logic without UI(npm: @page-agent/core) **
├── page-agent/ # Exported agent and demo(npm: page-agent)
├── llms/ # LLM client (npm: @page-agent/llms)
├── page-controller/ # DOM operations & Visual Mask (npm: @page-agent/page-controller)
├── ui/ # Panel & i18n (npm: @page-agent/ui)
+14 -14
View File
@@ -1,12 +1,12 @@
{
"name": "root",
"version": "0.3.0",
"version": "1.0.0-beta.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "root",
"version": "0.3.0",
"version": "1.0.0-beta.0",
"license": "MIT",
"workspaces": [
"packages/page-controller",
@@ -8142,18 +8142,18 @@
},
"packages/core": {
"name": "@page-agent/core",
"version": "0.3.0",
"version": "1.0.0-beta.0",
"license": "MIT",
"dependencies": {
"@page-agent/llms": "0.3.0",
"@page-agent/page-controller": "0.3.0",
"@page-agent/llms": "1.0.0-beta.0",
"@page-agent/page-controller": "1.0.0-beta.0",
"chalk": "^5.6.2",
"zod": "^4.3.5"
}
},
"packages/llms": {
"name": "@page-agent/llms",
"version": "0.3.0",
"version": "1.0.0-beta.0",
"license": "MIT",
"dependencies": {
"chalk": "^5.6.2",
@@ -8161,20 +8161,20 @@
}
},
"packages/page-agent": {
"version": "0.3.0",
"version": "1.0.0-beta.0",
"license": "MIT",
"dependencies": {
"@page-agent/core": "0.3.0",
"@page-agent/llms": "0.3.0",
"@page-agent/page-controller": "0.3.0",
"@page-agent/ui": "0.3.0",
"@page-agent/core": "1.0.0-beta.0",
"@page-agent/llms": "1.0.0-beta.0",
"@page-agent/page-controller": "1.0.0-beta.0",
"@page-agent/ui": "1.0.0-beta.0",
"chalk": "^5.6.2",
"zod": "^4.3.5"
}
},
"packages/page-controller": {
"name": "@page-agent/page-controller",
"version": "0.3.0",
"version": "1.0.0-beta.0",
"license": "MIT",
"dependencies": {
"ai-motion": "^0.4.8"
@@ -8182,12 +8182,12 @@
},
"packages/ui": {
"name": "@page-agent/ui",
"version": "0.3.0",
"version": "1.0.0-beta.0",
"license": "MIT"
},
"packages/website": {
"name": "@page-agent/website",
"version": "0.3.0",
"version": "1.0.0-beta.0",
"dependencies": {
"@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": "0.3.0",
"version": "1.0.0-beta.0",
"type": "module",
"workspaces": [
"packages/page-controller",
+3 -3
View File
@@ -1,7 +1,7 @@
{
"name": "@page-agent/core",
"private": false,
"version": "0.3.0",
"version": "1.0.0-beta.0",
"type": "module",
"main": "./dist/esm/page-agent-core.js",
"module": "./dist/esm/page-agent-core.js",
@@ -45,7 +45,7 @@
"dependencies": {
"chalk": "^5.6.2",
"zod": "^4.3.5",
"@page-agent/llms": "0.3.0",
"@page-agent/page-controller": "0.3.0"
"@page-agent/llms": "1.0.0-beta.0",
"@page-agent/page-controller": "1.0.0-beta.0"
}
}
+20 -18
View File
@@ -8,7 +8,7 @@ import chalk from 'chalk'
import zod from 'zod'
import { type PageAgentConfig } from './config'
import { MAX_STEPS } from './config/constants'
import { DEFAULT_MAX_STEPS } from './config/constants'
import SYSTEM_PROMPT from './prompts/system_prompt.md?raw'
import { tools } from './tools'
import {
@@ -21,7 +21,7 @@ import {
MacroToolInput,
MacroToolResult,
} from './types'
import { normalizeResponse, trimLines, uid } from './utils'
import { normalizeResponse, trimLines, uid, waitFor } from './utils'
import { assert } from './utils/assert'
export { type PageAgentConfig }
@@ -49,7 +49,7 @@ export { tool, type PageAgentTool } from './tools'
* - Types: thinking, executing, executed, retrying, error
*/
export class PageAgentCore extends EventTarget {
config: PageAgentConfig
config: PageAgentConfig & { maxSteps: number }
id = uid()
tools: typeof tools
disposed = false
@@ -86,7 +86,8 @@ export class PageAgentCore extends EventTarget {
constructor(config: PageAgentConfig & { pageController: PageController }) {
super()
this.config = config
this.config = { ...config, maxSteps: config.maxSteps || DEFAULT_MAX_STEPS }
this.#llm = new LLM(this.config)
this.tools = new Map(tools)
this.pageController = config.pageController
@@ -183,12 +184,12 @@ export class PageAgentCore extends EventTarget {
this.tools.delete('ask_user')
}
const onBeforeStep = this.config.onBeforeStep || (() => void 0)
const onAfterStep = this.config.onAfterStep || (() => void 0)
const onBeforeTask = this.config.onBeforeTask || (() => void 0)
const onAfterTask = this.config.onAfterTask || (() => void 0)
const onBeforeStep = this.config.onBeforeStep
const onAfterStep = this.config.onAfterStep
const onBeforeTask = this.config.onBeforeTask
const onAfterTask = this.config.onAfterTask
await onBeforeTask.call(this)
await onBeforeTask?.(this)
// Show mask
await this.pageController.showMask()
@@ -214,7 +215,7 @@ export class PageAgentCore extends EventTarget {
while (true) {
await this.#generateObservations(step)
await onBeforeStep.call(this, step)
await onBeforeStep?.(this, step)
console.group(`step: ${step}`)
@@ -270,17 +271,17 @@ export class PageAgentCore extends EventTarget {
console.log(chalk.green('Step finished:'), actionName)
console.groupEnd()
await onAfterStep.call(this, this.history)
await onAfterStep?.(this, this.history)
step++
if (step > MAX_STEPS) {
if (step > this.config.maxSteps) {
this.#onDone('Step count exceeded maximum limit', false)
const result: ExecutionResult = {
success: false,
data: 'Step count exceeded maximum limit',
history: this.history,
}
await onAfterTask.call(this, result)
await onAfterTask?.(this, result)
return result
}
if (actionName === 'done') {
@@ -293,7 +294,7 @@ export class PageAgentCore extends EventTarget {
data: text,
history: this.history,
}
await onAfterTask.call(this, result)
await onAfterTask?.(this, result)
return result
}
}
@@ -307,7 +308,7 @@ export class PageAgentCore extends EventTarget {
data: errorMessage,
history: this.history,
}
await onAfterTask.call(this, result)
await onAfterTask?.(this, result)
return result
}
}
@@ -472,10 +473,11 @@ export class PageAgentCore extends EventTarget {
if (currentURL !== this.states.lastURL) {
this.pushObservation(`Page navigated to → ${currentURL}`)
this.states.lastURL = currentURL
await waitFor(500) // wait for page to stabilize
}
// Warn about remaining steps
const remaining = MAX_STEPS - stepCount
const remaining = this.config.maxSteps - stepCount
if (remaining === 5) {
this.pushObservation(
`⚠️ Only ${remaining} steps remaining. Consider wrapping up or calling done with partial results.`
@@ -505,7 +507,7 @@ export class PageAgentCore extends EventTarget {
${this.task}
</user_request>
<step_info>
Step ${stepCount + 1} of ${MAX_STEPS} max possible steps
Step ${stepCount + 1} of ${this.config.maxSteps} max possible steps
Current date and time: ${new Date().toISOString()}
</step_info>
</agent_state>
@@ -583,6 +585,6 @@ export class PageAgentCore extends EventTarget {
// Emit dispose event for UI cleanup
this.dispatchEvent(new Event('dispose'))
this.config.onDispose?.call(this, reason)
this.config.onDispose?.(this, reason)
}
}
+1 -2
View File
@@ -1,2 +1 @@
// Agent-specific constants (LLM constants moved to @page-agent/llms)
export const MAX_STEPS = 20
export const DEFAULT_MAX_STEPS = 20
+50 -27
View File
@@ -1,5 +1,5 @@
import type { LLMConfig } from '@page-agent/llms'
import type { PageController, PageControllerConfig } from '@page-agent/page-controller'
import type { PageControllerConfig } from '@page-agent/page-controller'
import type { PageAgentCore } from '../PageAgentCore'
import type { PageAgentTool } from '../tools'
@@ -14,6 +14,12 @@ export interface AgentConfig {
// theme?: 'light' | 'dark'
language?: SupportedLanguage
/**
* Maximum number of steps the agent can take per task.
* @default 20
*/
maxSteps?: number
/**
* Custom tools to extend PageAgent capabilities
* @experimental
@@ -63,20 +69,52 @@ export interface AgentConfig {
getPageInstructions?: (url: string) => string | undefined | null
}
// lifecycle hooks
// @todo: use event instead of hooks
// @todo: remove `this` binding, pass agent as explicit parameter instead
onBeforeStep?: (this: PageAgentCore, stepCnt: number) => Promise<void> | void
onAfterStep?: (this: PageAgentCore, history: HistoricalEvent[]) => Promise<void> | void
onBeforeTask?: (this: PageAgentCore) => Promise<void> | void
onAfterTask?: (this: PageAgentCore, result: ExecutionResult) => Promise<void> | void
/**
* Lifecycle hooks for task execution.
* @experimental API may change in future versions.
*
* All hooks receive the agent instance as first parameter.
*/
/**
* @note this hook can block the disposal process
* @todo remove `this` binding, pass agent as explicit parameter instead
* Called before each step execution.
* @experimental
* @param agent - The PageAgentCore instance
* @param stepCount - Current step number (0-indexed)
*/
onDispose?: (this: PageAgentCore, reason?: string) => void
onBeforeStep?: (agent: PageAgentCore, stepCount: number) => Promise<void> | void
/**
* Called after each step execution.
* @experimental
* @param agent - The PageAgentCore instance
* @param history - Current history of events
*/
onAfterStep?: (agent: PageAgentCore, history: HistoricalEvent[]) => Promise<void> | void
/**
* Called before task execution starts.
* @experimental
* @param agent - The PageAgentCore instance
*/
onBeforeTask?: (agent: PageAgentCore) => Promise<void> | void
/**
* Called after task execution completes (success or failure).
* @experimental
* @param agent - The PageAgentCore instance
* @param result - The execution result
*/
onAfterTask?: (agent: PageAgentCore, result: ExecutionResult) => Promise<void> | void
/**
* Called when the agent is disposed.
* @experimental
* @note This hook can block the disposal process if it's async.
* @param agent - The PageAgentCore instance
* @param reason - Optional reason for disposal
*/
onDispose?: (agent: PageAgentCore, reason?: string) => void
// page behavior hooks
@@ -103,21 +141,6 @@ export interface AgentConfig {
* }
*/
transformPageContent?: (content: string) => Promise<string> | string
/**
* TODO: @unimplemented
* hook when action causes a new page to be opened
* @note PageAgent will try to detect new pages and decide if it's caused by an action. But not very reliable.
* @todo remove `this` binding, pass agent as explicit parameter instead
*/
// onNewPageOpen?: (this: PageAgent, url: string) => Promise<void> | void
/**
* TODO: @unimplemented
* try to navigate to a new page instead of opening a new tab/window.
* @note will unload the current page when a action tries to open a new page. so that things keep in the same tab/window.
*/
// experimentalPreventNewPage?: boolean
}
export type PageAgentConfig = LLMConfig & AgentConfig & PageControllerConfig
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@page-agent/llms",
"version": "0.3.0",
"version": "1.0.0-beta.0",
"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": "0.3.0",
"version": "1.0.0-beta.0",
"type": "module",
"main": "./dist/esm/page-agent.js",
"module": "./dist/esm/page-agent.js",
@@ -46,9 +46,9 @@
"dependencies": {
"chalk": "^5.6.2",
"zod": "^4.3.5",
"@page-agent/llms": "0.3.0",
"@page-agent/page-controller": "0.3.0",
"@page-agent/core": "0.3.0",
"@page-agent/ui": "0.3.0"
"@page-agent/llms": "1.0.0-beta.0",
"@page-agent/page-controller": "1.0.0-beta.0",
"@page-agent/core": "1.0.0-beta.0",
"@page-agent/ui": "1.0.0-beta.0"
}
}
+3 -2
View File
@@ -2,11 +2,12 @@
* Copyright (C) 2025 Alibaba Group Holding Limited
* All rights reserved.
*/
import { type PageAgentConfig, PageAgentCore } from '@page-agent/core'
import { type PageAgentConfig, PageAgentCore, type PageAgentTool, tool } from '@page-agent/core'
import { PageController } from '@page-agent/page-controller'
import { Panel } from '@page-agent/ui'
export type { PageAgentConfig }
export type { PageAgentConfig, PageAgentTool }
export { tool }
export class PageAgent extends PageAgentCore {
panel: Panel
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@page-agent/page-controller",
"version": "0.3.0",
"version": "1.0.0-beta.0",
"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": "0.3.0",
"version": "1.0.0-beta.0",
"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": "0.3.0",
"version": "1.0.0-beta.0",
"type": "module",
"scripts": {
"dev": "vite --host 0.0.0.0",
@@ -105,8 +105,8 @@ const result = await agent.execute('Fill in the form with test data')`}
type: 'string',
required: true,
description: isZh
? '模型名称(如 gpt-4o, claude-3.5-sonnet'
: 'Model name (e.g., gpt-4o, claude-3.5-sonnet)',
? '模型名称(如 gpt-5.2, anthropic/claude-4.5-haiku'
: 'Model name (e.g., gpt-5.2, anthropic/claude-4.5-haiku)',
},
{
name: 'temperature',
@@ -149,6 +149,12 @@ const result = await agent.execute('Fill in the form with test data')`}
defaultValue: "'en-US'",
description: isZh ? 'Agent 输出语言' : 'Agent output language',
},
{
name: 'maxSteps',
type: 'number',
defaultValue: '20',
description: isZh ? '每个任务的最大步骤数' : 'Maximum number of steps per task',
},
{
name: 'customTools',
type: 'Record<string, PageAgentTool | null>',
@@ -207,35 +213,48 @@ const result = await agent.execute('Fill in the form with test data')`}
{/* Lifecycle Hooks */}
<section className="mb-10">
<h2 className="text-2xl font-semibold mb-4">{isZh ? '生命周期钩子' : 'Lifecycle Hooks'}</h2>
<div className="bg-amber-50 dark:bg-amber-900/20 border border-amber-200 dark:border-amber-800 rounded-lg p-4 mb-4">
<p className="text-amber-800 dark:text-amber-200 text-sm">
<strong> {isZh ? '警告' : 'Warning'}:</strong>{' '}
{isZh
? '这些接口高度实验性,可能在未来版本中发生变化。建议优先使用事件系统(Events)来监听 Agent 状态。'
: 'These APIs are highly experimental and may change in future versions. Prefer using the Events system for monitoring agent state.'}
</p>
</div>
<p className="text-gray-600 dark:text-gray-400 mb-4">
{isZh
? '所有生命周期钩子都接收 agent 实例作为第一个参数,便于在回调中访问 Agent 状态和方法。'
: 'All lifecycle hooks receive the agent instance as first parameter, making it easy to access agent state and methods in callbacks.'}
</p>
<APIReference
properties={[
{
name: 'onBeforeStep',
type: '(stepCnt: number) => void | Promise<void>',
type: '(agent: PageAgentCore, stepCount: number) => void | Promise<void>',
description: isZh ? '每个步骤执行前调用' : 'Called before each step execution',
status: 'experimental',
},
{
name: 'onAfterStep',
type: '(history: HistoricalEvent[]) => void | Promise<void>',
type: '(agent: PageAgentCore, history: HistoricalEvent[]) => void | Promise<void>',
description: isZh ? '每个步骤执行后调用' : 'Called after each step execution',
status: 'experimental',
},
{
name: 'onBeforeTask',
type: '() => void | Promise<void>',
type: '(agent: PageAgentCore) => void | Promise<void>',
description: isZh ? '任务开始前调用' : 'Called before task starts',
status: 'experimental',
},
{
name: 'onAfterTask',
type: '(result: ExecutionResult) => void | Promise<void>',
type: '(agent: PageAgentCore, result: ExecutionResult) => void | Promise<void>',
description: isZh ? '任务结束后调用' : 'Called after task ends',
status: 'experimental',
},
{
name: 'onDispose',
type: '(reason?: string) => void',
type: '(agent: PageAgentCore, reason?: string) => void',
description: isZh ? 'Agent 销毁时调用' : 'Called when agent is disposed',
status: 'experimental',
},
@@ -53,7 +53,7 @@ const agent = new PageAgent({
// LLM Configuration (required)
baseURL: 'https://api.openai.com/v1',
apiKey: 'your-api-key',
model: 'gpt-4o',
model: 'gpt-5.2',
// Optional settings
language: 'en-US',