2026-03-04 21:13:10 +08:00
import { Link } from 'wouter'
import { APIDivider , APIReference } from '@/components/APIReference'
import CodeEditor from '@/components/CodeEditor'
import { Heading } from '@/components/Heading'
import { useLanguage } from '@/i18n/context'
export default function PageControllerDocs() {
const { isZh } = useLanguage ()
return (
< div >
< h1 className = "text-4xl font-bold mb-6" > PageController </ h1 >
< p className = "text-xl text-gray-600 dark:text-gray-300 mb-8 leading-relaxed" >
{ isZh
? 'PageController 负责 DOM 提取和元素交互,独立于 LLM。它将页面状态结构化为 LLM 可消费的格式,并执行元素级操作。'
: 'PageController handles DOM extraction and element interaction, independent of LLM. It structures page state into LLM-consumable format and executes element-level actions.' }
</ p >
{ /* Basic Usage */ }
< section className = "mb-10" >
< Heading id = "basic-usage" >{ isZh ? '基本用法' : 'Basic Usage' }</ Heading >
< p className = "text-gray-600 dark:text-gray-400 mb-4" >
{ isZh
? 'PageAgent 接受 PageController 配置项:'
: 'PageAgent accepts PageController options:' }
</ p >
< CodeEditor
language = "typescript"
code = { `import { PageAgent } from 'page-agent'
const agent = new PageAgent({
baseURL: 'https://api.openai.com/v1',
apiKey: 'your-api-key',
model: 'gpt-5.2',
// PageController options
enableMask: true,
viewportExpansion: 0,
})` }
/>
< p className = "text-gray-600 dark:text-gray-400 mt-4" >
{ isZh
? 'PageAgentCore 接受 PageController 实例:'
: 'PageAgentCore accepts a PageController instance:' }
</ p >
< CodeEditor
language = "typescript"
code = { `import { PageAgentCore } from '@page-agent/core'
import { PageController } from '@page-agent/page-controller'
const pageController = new PageController({
enableMask: true,
viewportExpansion: -1, // extract full page
})
const agent = new PageAgentCore({
pageController,
baseURL: 'https://api.openai.com/v1',
apiKey: 'your-api-key',
model: 'gpt-5.2',
})` }
/>
</ section >
< APIDivider title = { isZh ? '配置' : 'Configuration' } />
{ /* Configuration */ }
< section className = "mb-10" >
< Heading id = "configuration" > PageControllerConfig </ Heading >
< APIReference
properties = {[
{
name : 'enableMask' ,
type : 'boolean' ,
defaultValue : 'false' ,
description : isZh
? '启用视觉遮罩覆盖层,在自动化期间阻止用户操作页面。通过 PageAgent 创建时默认为 true。'
: 'Enable visual mask overlay that blocks user interaction during automation. Defaults to true when created via PageAgent.' ,
},
{
name : 'viewportExpansion' ,
type : 'number' ,
defaultValue : '0' ,
description : isZh
? '向视口外扩展提取的像素数。设为 -1 表示提取整个页面。'
: 'Pixels to expand extraction beyond viewport. Set to -1 to extract the entire page.' ,
},
{
name : 'interactiveBlacklist' ,
type : '(Element | (() => Element))[]' ,
description : isZh
? '要排除的交互元素列表。支持元素引用或返回元素的函数(延迟求值)。'
: 'Elements to exclude from interaction. Supports element references or functions returning elements (lazy evaluation).' ,
},
{
name : 'interactiveWhitelist' ,
type : '(Element | (() => Element))[]' ,
description : isZh
? '要强制包含的交互元素列表。支持元素引用或返回元素的函数。'
: 'Elements to force include for interaction. Supports element references or functions returning elements.' ,
},
{
name : 'includeAttributes' ,
type : 'string[]' ,
description : isZh
2026-03-09 22:02:35 +08:00
? '在 DOM 提取中包含的额外 HTML 属性。支持通配符 *(如 data-* 匹配所有 data- 开头的属性)。默认已包含常见属性如 role, aria-label 等。'
: 'Additional HTML attributes to include in DOM extraction. Supports wildcard * (e.g. data-* matches all data- prefixed attributes). Common attributes like role, aria-label are included by default.' ,
2026-03-04 21:13:10 +08:00
},
]}
/>
</ section >
< APIDivider title = { isZh ? '方法' : 'Methods' } />
{ /* Methods */ }
< section className = "mb-10" >
< Heading id = "methods" >{ isZh ? '方法' : 'Methods' }</ Heading >
< h3 className = "text-lg font-semibold mt-6 mb-3" >{ isZh ? '状态查询' : 'State Queries' }</ h3 >
< APIReference
variant = "methods"
properties = {[
{
name : 'getBrowserState()' ,
type : 'Promise<BrowserState>' ,
description : isZh
? '获取结构化的浏览器状态(URL、标题、简化 HTML 等),自动调用 updateTree() 刷新 DOM。这是 Agent 在每步使用的主要方法。'
: 'Get structured browser state (URL, title, simplified HTML, etc.), automatically calls updateTree() to refresh DOM. This is the primary method the agent uses each step.' ,
},
{
name : 'updateTree()' ,
type : 'Promise<string>' ,
description : isZh
? '刷新 DOM 树并返回简化 HTML。通常不需要手动调用 —— getBrowserState() 会自动调用。'
: 'Refresh DOM tree and return simplified HTML. Usually not needed manually — getBrowserState() calls it automatically.' ,
},
{
name : 'getCurrentUrl()' ,
type : 'Promise<string>' ,
description : isZh ? '获取当前页面 URL。' : 'Get current page URL.' ,
},
]}
/>
< h3 className = "text-lg font-semibold mt-6 mb-3" >{ isZh ? '元素操作' : 'Element Actions' }</ h3 >
< APIReference
variant = "methods"
properties = {[
{
name : 'clickElement(index)' ,
type : 'Promise<ActionResult>' ,
description : isZh
? '按索引点击元素。索引来自简化 HTML 中的 [N] 标记。'
: 'Click element by index. Index comes from [N] markers in simplified HTML.' ,
},
{
name : 'inputText(index, text)' ,
type : 'Promise<ActionResult>' ,
description : isZh ? '向输入框元素填入文本。' : 'Input text into a form element.' ,
},
{
name : 'selectOption(index, optionText)' ,
type : 'Promise<ActionResult>' ,
description : isZh ? '在下拉框中选择选项。' : 'Select option in a dropdown element.' ,
},
{
name : 'scroll(options)' ,
type : 'Promise<ActionResult>' ,
description : isZh
? '垂直滚动页面或指定元素。'
: 'Scroll page or specific element vertically.' ,
},
{
name : 'scrollHorizontally(options)' ,
type : 'Promise<ActionResult>' ,
description : isZh
? '水平滚动页面或指定元素。'
: 'Scroll page or specific element horizontally.' ,
},
]}
/>
< h3 className = "text-lg font-semibold mt-6 mb-3" >{ isZh ? '遮罩控制' : 'Mask Control' }</ h3 >
< APIReference
variant = "methods"
properties = {[
{
name : 'showMask()' ,
type : 'Promise<void>' ,
description : isZh
? '显示视觉遮罩。需要 enableMask: true。'
: 'Show visual mask overlay. Requires enableMask: true.' ,
},
{
name : 'hideMask()' ,
type : 'Promise<void>' ,
description : isZh ? '隐藏视觉遮罩。' : 'Hide visual mask overlay.' ,
},
]}
/>
< h3 className = "text-lg font-semibold mt-6 mb-3" >{ isZh ? '生命周期' : 'Lifecycle' }</ h3 >
< APIReference
variant = "methods"
properties = {[
{
name : 'dispose()' ,
type : 'void' ,
description : isZh
? '清理所有资源(DOM 高亮、遮罩等)。Agent 销毁时自动调用。'
: 'Clean up all resources (DOM highlights, mask, etc.). Called automatically when agent disposes.' ,
},
]}
/>
</ section >
< APIDivider title = { isZh ? '类型定义' : 'Type Definitions' } />
{ /* BrowserState */ }
< section className = "mb-10" >
< Heading id = "browser-state" > BrowserState </ Heading >
< p className = "text-gray-600 dark:text-gray-400 mb-4" >
{ isZh
? 'getBrowserState() 返回的结构化浏览器状态,直接用于构建 LLM prompt。'
: 'Structured browser state returned by getBrowserState(), used directly to build LLM prompts.' }
</ p >
< CodeEditor
language = "typescript"
code = { `interface BrowserState {
url: string
title: string
header: string // page info + scroll position
content: string // simplified HTML of interactive elements
footer: string // scroll hint
}` }
/>
</ section >
{ /* ActionResult */ }
< section className = "mb-10" >
< Heading id = "action-result" > ActionResult </ Heading >
< CodeEditor
language = "typescript"
code = { `interface ActionResult {
success: boolean
message: string
}` }
/>
</ section >
{ /* Custom PageController */ }
< section className = "mb-10" >
< Heading id = "custom-implementation" >
{ isZh ? '自定义实现' : 'Custom Implementation' }
</ Heading >
< p className = "text-gray-600 dark:text-gray-400 mb-4" >
{ isZh
? '在非浏览器环境(如 Puppeteer、Playwright),你可以实现自定义 PageController。需要实现 Agent 使用的核心方法:'
: 'In non-browser environments (e.g. Puppeteer, Playwright), you can implement a custom PageController. Implement the core methods used by the agent:' }
</ p >
< CodeEditor
language = "typescript"
code = { `import { PageAgentCore } from '@page-agent/core'
import type { PageController } from '@page-agent/page-controller'
class PuppeteerPageController implements PageController {
async getBrowserState() { /* ... */ }
async clickElement(index: number) { /* ... */ }
async inputText(index: number, text: string) { /* ... */ }
async scroll(options: { down: boolean; numPages: number }) { /* ... */ }
// ... other methods
}
const agent = new PageAgentCore({
pageController: new PuppeteerPageController(),
baseURL: 'https://api.openai.com/v1',
apiKey: 'your-api-key',
model: 'gpt-5.2',
})` }
/>
</ section >
</ div >
)
}