docs: update advanced docs; rm best-practice

This commit is contained in:
Simon
2026-03-04 21:13:10 +08:00
parent e5437b445a
commit 53c2c19d69
13 changed files with 480 additions and 329 deletions

View File

@@ -5,10 +5,9 @@
*/ */
import * as React from 'react' import * as React from 'react'
import { Badge } from '@/components/ui/badge'
import { cn } from '@/lib/utils' import { cn } from '@/lib/utils'
import { Badge } from './badge'
// ============================================================================ // ============================================================================
// Types // Types
// ============================================================================ // ============================================================================
@@ -35,6 +34,8 @@ export interface APIReferenceProps {
description?: React.ReactNode description?: React.ReactNode
/** Property definitions */ /** Property definitions */
properties: PropDefinition[] properties: PropDefinition[]
/** Display variant: 'properties' for fields, 'methods' for methods */
variant?: 'properties' | 'methods'
/** Additional CSS classes */ /** Additional CSS classes */
className?: string className?: string
} }
@@ -43,7 +44,14 @@ export interface APIReferenceProps {
// Component // Component
// ============================================================================ // ============================================================================
export function APIReference({ title, description, properties, className }: APIReferenceProps) { export function APIReference({
title,
description,
properties,
variant = 'properties',
className,
}: APIReferenceProps) {
const isMethodsVariant = variant === 'methods'
return ( return (
<div className={cn('my-6', className)}> <div className={cn('my-6', className)}>
{title && ( {title && (
@@ -58,10 +66,10 @@ export function APIReference({ title, description, properties, className }: APIR
<thead> <thead>
<tr className="bg-gray-50 dark:bg-gray-800/50"> <tr className="bg-gray-50 dark:bg-gray-800/50">
<th className="px-4 py-3 text-left font-medium text-gray-600 dark:text-gray-300"> <th className="px-4 py-3 text-left font-medium text-gray-600 dark:text-gray-300">
Property {isMethodsVariant ? 'Method' : 'Property'}
</th> </th>
<th className="px-4 py-3 text-left font-medium text-gray-600 dark:text-gray-300"> <th className="px-4 py-3 text-left font-medium text-gray-600 dark:text-gray-300">
Type {isMethodsVariant ? 'Return Type' : 'Type'}
</th> </th>
<th className="px-4 py-3 text-left font-medium text-gray-600 dark:text-gray-300 hidden md:table-cell"> <th className="px-4 py-3 text-left font-medium text-gray-600 dark:text-gray-300 hidden md:table-cell">
Default Default
@@ -120,7 +128,7 @@ function PropRow({ name, type, required, defaultValue, description, status }: Pr
{/* Type */} {/* Type */}
<td className="px-4 py-3 align-top"> <td className="px-4 py-3 align-top">
<code className="font-mono text-xs text-gray-700 dark:text-gray-300 bg-gray-100 dark:bg-gray-800 px-1.5 py-0.5 rounded whitespace-nowrap"> <code className="font-mono text-xs text-gray-700 dark:text-gray-300 bg-gray-100 dark:bg-gray-800 px-1.5 py-0.5 rounded wrap-break-word">
{type} {type}
</code> </code>
</td> </td>

View File

@@ -42,7 +42,7 @@ const CodeEditor: React.FC<CodeEditorProps> = ({
return ( return (
<div <div
className={`group relative ${containerClasses} rounded-xl border shadow-2xl overflow-hidden ${className}`} className={`group relative ${containerClasses} rounded-xl border shadow-2xl my-4 overflow-hidden ${className}`}
> >
{/* 编辑器顶部栏 */} {/* 编辑器顶部栏 */}
{showHeader && ( {showHeader && (

View File

@@ -34,10 +34,6 @@ export default function DocsLayout({ children }: DocsLayoutProps) {
title: isZh ? '故障排查' : 'Troubleshooting', title: isZh ? '故障排查' : 'Troubleshooting',
path: '/introduction/troubleshooting', path: '/introduction/troubleshooting',
}, },
{
title: '🚧 ' + (isZh ? '最佳实践' : 'Best Practices'),
path: '/integration/best-practices',
},
], ],
}, },
{ {
@@ -50,7 +46,7 @@ export default function DocsLayout({ children }: DocsLayoutProps) {
{ title: isZh ? 'Chrome 扩展' : 'Chrome Extension', path: '/features/chrome-extension' }, { title: isZh ? 'Chrome 扩展' : 'Chrome Extension', path: '/features/chrome-extension' },
{ {
title: isZh ? '接入第三方 Agent' : 'Third-party Agent', title: isZh ? '接入第三方 Agent' : 'Third-party Agent',
path: '/integration/third-party-agent', path: '/features/third-party-agent',
}, },
], ],
}, },
@@ -59,10 +55,11 @@ export default function DocsLayout({ children }: DocsLayoutProps) {
items: [ items: [
{ title: 'PageAgent', path: '/advanced/page-agent' }, { title: 'PageAgent', path: '/advanced/page-agent' },
{ title: 'PageAgentCore', path: '/advanced/page-agent-core' }, { title: 'PageAgentCore', path: '/advanced/page-agent-core' },
{ title: 'PageController', path: '/advanced/page-controller' },
{ title: isZh ? '自定义 UI' : 'Custom UI', path: '/advanced/custom-ui' }, { title: isZh ? '自定义 UI' : 'Custom UI', path: '/advanced/custom-ui' },
{ {
title: '🚧 ' + (isZh ? '安全与权限' : 'Security & Permissions'), title: '🚧 ' + (isZh ? '安全与权限' : 'Security & Permissions'),
path: '/integration/security-permissions', path: '/advanced/security-permissions',
}, },
], ],
}, },

View File

@@ -1,6 +1,6 @@
import { APIDivider, APIReference } from '@/components/APIReference'
import CodeEditor from '@/components/CodeEditor' import CodeEditor from '@/components/CodeEditor'
import { Heading } from '@/components/Heading' import { Heading } from '@/components/Heading'
import { APIDivider, APIReference } from '@/components/ui/api-reference'
import { useLanguage } from '@/i18n/context' import { useLanguage } from '@/i18n/context'
export default function CustomUIDocs() { export default function CustomUIDocs() {

View File

@@ -1,6 +1,8 @@
import { Link } from 'wouter'
import { APIDivider, APIReference, TypeRef } from '@/components/APIReference'
import CodeEditor from '@/components/CodeEditor' import CodeEditor from '@/components/CodeEditor'
import { Heading } from '@/components/Heading' import { Heading } from '@/components/Heading'
import { APIDivider, APIReference, TypeRef } from '@/components/ui/api-reference'
import { useLanguage } from '@/i18n/context' import { useLanguage } from '@/i18n/context'
export default function PageAgentCoreDocs() { export default function PageAgentCoreDocs() {
@@ -50,19 +52,13 @@ const agent = new PageAgentCore({
baseURL: 'https://api.openai.com/v1', baseURL: 'https://api.openai.com/v1',
apiKey: 'your-api-key', apiKey: 'your-api-key',
model: 'gpt-5.2', model: 'gpt-5.2',
language: 'en-US',
}) })
// Listen to events for UI display // Listen to events for UI display
agent.addEventListener('statuschange', () => { agent.addEventListener('statuschange', () => {
console.log('Status:', agent.status) console.log('Status:', agent.status)
}) })
agent.addEventListener('historychange', () => {
console.log('History:', agent.history)
})
agent.addEventListener('activity', (e) => { agent.addEventListener('activity', (e) => {
const activity = (e as CustomEvent).detail const activity = (e as CustomEvent).detail
console.log('Activity:', activity.type) console.log('Activity:', activity.type)
@@ -75,14 +71,54 @@ const result = await agent.execute('Fill in the form with test data')`}
<APIDivider title={isZh ? '配置' : 'Configuration'} /> <APIDivider title={isZh ? '配置' : 'Configuration'} />
{/* LLM Configuration */} {/* Configuration */}
<section className="mb-10"> <section className="mb-10">
<Heading id="llmconfig">LLMConfig</Heading> <Heading id="configuration">PageAgentCoreConfig</Heading>
<p className="text-gray-600 dark:text-gray-400 mb-4"> <p className="text-gray-600 dark:text-gray-400 mb-4">
{isZh {isZh
? '配置与大语言模型的连接参数。支持 OpenAI 兼容的 API。' ? 'PageAgentCoreConfig = AgentConfig & { pageController: PageController }。AgentConfig 包含以下配置项:'
: 'Configure connection parameters for the language model. Supports OpenAI-compatible APIs.'} : 'PageAgentCoreConfig = AgentConfig & { pageController: PageController }. AgentConfig contains the following options:'}
</p> </p>
{/* PageController */}
<h3 className="text-lg font-semibold mt-6 mb-3 text-gray-800 dark:text-gray-200">
PageController
</h3>
<APIReference
properties={[
{
name: 'pageController',
type: 'PageController',
required: true,
description: isZh ? (
<>
<Link
href="/advanced/page-controller"
className="text-blue-600 dark:text-blue-400 hover:underline"
>
PageController
</Link>{' '}
DOM
</>
) : (
<>
<Link
href="/advanced/page-controller"
className="text-blue-600 dark:text-blue-400 hover:underline"
>
PageController
</Link>{' '}
instance for DOM operations and element interaction.
</>
),
},
]}
/>
{/* LLM Config */}
<h3 className="text-lg font-semibold mt-6 mb-3 text-gray-800 dark:text-gray-200">
{isZh ? 'LLM 配置' : 'LLM Config'}
</h3>
<APIReference <APIReference
properties={[ properties={[
{ {
@@ -110,7 +146,6 @@ const result = await agent.execute('Fill in the form with test data')`}
{ {
name: 'temperature', name: 'temperature',
type: 'number', type: 'number',
defaultValue: '0',
description: isZh description: isZh
? '模型温度参数,控制输出随机性' ? '模型温度参数,控制输出随机性'
: 'Model temperature, controls output randomness', : 'Model temperature, controls output randomness',
@@ -130,16 +165,11 @@ const result = await agent.execute('Fill in the form with test data')`}
}, },
]} ]}
/> />
</section>
{/* Agent Configuration */} {/* Agent Config */}
<section className="mb-10"> <h3 className="text-lg font-semibold mt-6 mb-3 text-gray-800 dark:text-gray-200">
<Heading id="agentconfig">AgentConfig</Heading> {isZh ? 'Agent 配置' : 'Agent Config'}
<p className="text-gray-600 dark:text-gray-400 mb-4"> </h3>
{isZh
? '配置 Agent 的行为、生命周期钩子和扩展能力。'
: 'Configure agent behavior, lifecycle hooks, and extension capabilities.'}
</p>
<APIReference <APIReference
properties={[ properties={[
{ {
@@ -166,8 +196,8 @@ const result = await agent.execute('Fill in the form with test data')`}
name: 'instructions', name: 'instructions',
type: 'InstructionsConfig', type: 'InstructionsConfig',
description: isZh description: isZh
? '指导 Agent 行为的指令配置' ? '指导 Agent 行为的指令配置,见下方类型定义'
: 'Instructions to guide agent behavior', : 'Instructions to guide agent behavior, see type definition below',
}, },
{ {
name: 'transformPageContent', name: 'transformPageContent',
@@ -177,7 +207,15 @@ const result = await agent.execute('Fill in the form with test data')`}
: 'Transform page content before sending to LLM, useful for data masking', : 'Transform page content before sending to LLM, useful for data masking',
}, },
{ {
name: 'experimentalScriptExecutionTool', name: 'customSystemPrompt',
type: 'string',
status: 'experimental',
description: isZh
? '完全覆盖默认系统提示词。谨慎使用。'
: 'Completely override the default system prompt. Use with caution.',
},
{
name: 'experimentalScript\nExecutionTool',
type: 'boolean', type: 'boolean',
defaultValue: 'false', defaultValue: 'false',
status: 'experimental', status: 'experimental',
@@ -191,137 +229,52 @@ const result = await agent.execute('Fill in the form with test data')`}
defaultValue: 'false', defaultValue: 'false',
status: 'experimental', status: 'experimental',
description: isZh description: isZh
? '从当前站点根目录获取 /llms.txt 并作为上下文提供给 LLM,每个 origin 仅请求一次' ? '从当前站点根目录获取 /llms.txt 并作为上下文提供给 LLM'
: 'Fetch /llms.txt from site origin and include as LLM context, fetched once per origin', : 'Fetch /llms.txt from site origin and include as LLM context',
}, },
]} ]}
/> />
<h3 className="text-lg font-semibold mt-6 mb-3">InstructionsConfig</h3> {/* Lifecycle Hooks */}
<APIReference <h3 className="text-lg font-semibold mt-6 mb-3 text-gray-800 dark:text-gray-200">
properties={[ {isZh ? '生命周期钩子' : 'Lifecycle Hooks'}
{ <span className="ml-2 text-xs font-normal text-amber-600 dark:text-amber-400">
name: 'system', experimental
type: 'string', </span>
description: isZh </h3>
? '全局系统级指令,应用于所有任务'
: 'Global system-level instructions, applied to all tasks',
},
{
name: 'getPageInstructions',
type: '(url: string) => string | undefined | null',
description: isZh
? '动态页面级指令回调,在每个步骤前调用'
: 'Dynamic page-level instructions callback, called before each step',
},
]}
/>
</section>
{/* Lifecycle Hooks */}
<section className="mb-10">
<Heading id="lifecycle-hooks">{isZh ? '生命周期钩子' : 'Lifecycle Hooks'}</Heading>
<div className="bg-amber-50 dark:bg-amber-900/20 border border-amber-200 dark:border-amber-800 rounded-lg p-4 mb-4"> <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"> <p className="text-amber-800 dark:text-amber-200 text-sm">
<strong> {isZh ? '警告' : 'Warning'}:</strong>{' '}
{isZh {isZh
? '这些接口高度实验性,可能在未来版本中发生变化。建议优先使用事件系统Events来监听 Agent 状态。' ? '这些接口高度实验性,可能在未来版本中发生变化。'
: 'These APIs are highly experimental and may change in future versions. Prefer using the Events system for monitoring agent state.'} : 'These APIs are highly experimental and may change in future versions. '}
</p> </p>
</div> </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 <APIReference
properties={[ properties={[
{ {
name: 'onBeforeStep', name: 'onBeforeStep',
type: '(agent: PageAgentCore, stepCount: number) => void | Promise<void>', type: '(agent, stepCount) => void | Promise<void>',
description: isZh ? '每个步骤执行前调用' : 'Called before each step execution', description: isZh ? '每个步骤执行前调用' : 'Called before each step execution',
status: 'experimental',
}, },
{ {
name: 'onAfterStep', name: 'onAfterStep',
type: '(agent: PageAgentCore, history: HistoricalEvent[]) => void | Promise<void>', type: '(agent, history) => void | Promise<void>',
description: isZh ? '每个步骤执行后调用' : 'Called after each step execution', description: isZh ? '每个步骤执行后调用' : 'Called after each step execution',
status: 'experimental',
}, },
{ {
name: 'onBeforeTask', name: 'onBeforeTask',
type: '(agent: PageAgentCore) => void | Promise<void>', type: '(agent) => void | Promise<void>',
description: isZh ? '任务开始前调用' : 'Called before task starts', description: isZh ? '任务开始前调用' : 'Called before task starts',
status: 'experimental',
}, },
{ {
name: 'onAfterTask', name: 'onAfterTask',
type: '(agent: PageAgentCore, result: ExecutionResult) => void | Promise<void>', type: '(agent, result) => void | Promise<void>',
description: isZh ? '任务结束后调用' : 'Called after task ends', description: isZh ? '任务结束后调用' : 'Called after task ends',
status: 'experimental',
}, },
{ {
name: 'onDispose', name: 'onDispose',
type: '(agent: PageAgentCore, reason?: string) => void', type: '(agent, reason?) => void',
description: isZh ? 'Agent 销毁时调用' : 'Called when agent is disposed', description: isZh ? 'Agent 销毁时调用' : 'Called when agent is disposed',
status: 'experimental',
},
]}
/>
</section>
{/* PageController Configuration */}
<section className="mb-10">
<Heading id="pagecontrollerconfig">PageControllerConfig</Heading>
<p className="text-gray-600 dark:text-gray-400 mb-4">
{isZh
? '配置 DOM 提取、元素交互和视觉反馈。'
: 'Configure DOM extraction, element interaction, and visual feedback.'}
</p>
<APIReference
properties={[
{
name: 'pageController',
type: 'PageController',
status: 'experimental',
description: isZh
? '自定义 PageController 实例。如不提供,将创建默认实例。'
: 'Custom PageController instance. If not provided, a default one will be created.',
},
{
name: 'enableMask',
type: 'boolean',
defaultValue: 'true',
description: isZh
? '启用视觉遮罩覆盖层,阻止用户在自动化期间操作'
: 'Enable visual mask overlay that blocks user interaction during automation',
},
{
name: 'viewportExpansion',
type: 'number',
defaultValue: '0',
description: isZh
? '视口扩展像素数,-1 表示提取整个页面'
: 'Viewport expansion in pixels, -1 means extract entire page',
},
{
name: 'interactiveBlacklist',
type: '(Element | (() => Element))[]',
description: isZh ? '要排除的交互元素列表' : 'Elements to exclude from interaction',
},
{
name: 'interactiveWhitelist',
type: '(Element | (() => Element))[]',
description: isZh
? '要强制包含的交互元素列表'
: 'Elements to force include for interaction',
},
{
name: 'includeAttributes',
type: 'string[]',
description: isZh
? '在 DOM 提取中包含的额外属性'
: 'Additional attributes to include in DOM extraction',
}, },
]} ]}
/> />
@@ -378,16 +331,24 @@ const result = await agent.execute('Fill in the form with test data')`}
<section className="mb-10"> <section className="mb-10">
<Heading id="methods">{isZh ? '方法' : 'Methods'}</Heading> <Heading id="methods">{isZh ? '方法' : 'Methods'}</Heading>
<APIReference <APIReference
variant="methods"
properties={[ properties={[
{ {
name: 'execute(task: string)', name: 'execute(task)',
type: 'Promise<ExecutionResult>', type: 'Promise<ExecutionResult>',
description: isZh description: isZh
? '执行任务并返回结果。包含 success、data 和 history 字段。' ? '执行任务并返回结果。包含 success、data 和 history 字段。'
: 'Execute a task and return result. Contains success, data, and history fields.', : 'Execute a task and return result. Contains success, data, and history fields.',
}, },
{ {
name: 'dispose(reason?: string)', name: 'stop()',
type: 'void',
description: isZh
? '停止当前任务。Agent 仍可复用。'
: 'Stop the current task. Agent remains reusable.',
},
{
name: 'dispose()',
type: 'void', type: 'void',
description: isZh description: isZh
? '销毁 Agent 并清理资源' ? '销毁 Agent 并清理资源'
@@ -452,11 +413,8 @@ const result = await agent.execute('Fill in the form with test data')`}
<CodeEditor <CodeEditor
language="typescript" language="typescript"
code={`interface ExecutionResult { code={`interface ExecutionResult {
/** Whether the task completed successfully */
success: boolean success: boolean
/** Result description from the agent */
data: string data: string
/** Full execution history */
history: HistoricalEvent[] history: HistoricalEvent[]
}`} }`}
/> />
@@ -476,50 +434,21 @@ const result = await agent.execute('Fill in the form with test data')`}
/> />
</section> </section>
<APIDivider title={isZh ? '无头模式' : 'Headless Mode'} /> {/* InstructionsConfig */}
{/* Headless Usage */}
<section className="mb-10"> <section className="mb-10">
<Heading id="headless-mode">{isZh ? '无头模式' : 'Headless Mode'}</Heading> <Heading id="instructionsconfig">InstructionsConfig</Heading>
<p className="text-gray-600 dark:text-gray-400 mb-4">
{isZh
? '在非 DOM 环境中,你必须实现自定义的 PageController例如远程操作页面或 Puppeteer。'
: 'In non-DOM environments, you must implement a custom PageController (e.g., remote page control or Puppeteer).'}
</p>
<CodeEditor <CodeEditor
language="typescript" language="typescript"
code={`import { PageAgentCore } from '@page-agent/core' code={`interface InstructionsConfig {
import type { PageController } from '@page-agent/page-controller' /** Global system-level instructions, applied to all tasks */
system?: string
class MyRemotePageController implements PageController { /**
// Implement required methods for DOM extraction and interaction * Dynamic page-level instructions callback.
} * Called before each step to get instructions for the current page.
*/
const agent = new PageAgentCore({ getPageInstructions?: (url: string) => string | undefined
pageController: new MyRemotePageController(), }`}
baseURL: 'https://api.openai.com/v1',
apiKey: 'your-api-key',
model: 'gpt-5.2',
language: 'en-US',
})
// Listen to events for UI display
agent.addEventListener('statuschange', () => {
console.log('Status:', agent.status)
})
agent.addEventListener('historychange', () => {
console.log('History:', agent.history)
})
agent.addEventListener('activity', (e) => {
const activity = (e as CustomEvent).detail
console.log('Activity:', activity.type)
})
// Execute task
const result = await agent.execute('Fill in the form with test data')`}
/> />
</section> </section>
</div> </div>

View File

@@ -2,7 +2,6 @@ import { Link } from 'wouter'
import CodeEditor from '@/components/CodeEditor' import CodeEditor from '@/components/CodeEditor'
import { Heading } from '@/components/Heading' import { Heading } from '@/components/Heading'
import { APIReference, TypeRef } from '@/components/ui/api-reference'
import { useLanguage } from '@/i18n/context' import { useLanguage } from '@/i18n/context'
export default function PageAgentDocs() { export default function PageAgentDocs() {
@@ -14,8 +13,8 @@ export default function PageAgentDocs() {
<p className="text-xl text-gray-600 dark:text-gray-300 mb-8 leading-relaxed"> <p className="text-xl text-gray-600 dark:text-gray-300 mb-8 leading-relaxed">
{isZh {isZh
? 'PageAgent 是带有内置 UI 面板的完整 Agent 类。它继承自 PageAgentCore并自动创建交互面板。' ? 'PageAgent 是带有内置 UI 面板的完整 Agent 类。它继承自 PageAgentCore并自动创建交互面板和 PageController。'
: 'PageAgent is the complete Agent class with built-in UI panel. It extends PageAgentCore and automatically creates an interactive panel.'} : 'PageAgent is the complete Agent class with built-in UI panel. It extends PageAgentCore and automatically creates an interactive panel and PageController.'}
</p> </p>
{/* When to use */} {/* When to use */}
@@ -29,6 +28,11 @@ export default function PageAgentDocs() {
: 'In most cases, you should use PageAgent. It provides a complete out-of-the-box experience:'} : 'In most cases, you should use PageAgent. It provides a complete out-of-the-box experience:'}
</p> </p>
<ul className="list-disc list-inside text-gray-600 dark:text-gray-400 space-y-2 mb-6"> <ul className="list-disc list-inside text-gray-600 dark:text-gray-400 space-y-2 mb-6">
<li>
{isZh
? '自动创建 PageController处理 DOM 提取和元素操作'
: 'Automatically creates PageController for DOM extraction and element actions'}
</li>
<li> <li>
{isZh {isZh
? '内置 UI 面板显示任务进度、Agent 思考过程和操作结果' ? '内置 UI 面板显示任务进度、Agent 思考过程和操作结果'
@@ -74,9 +78,8 @@ console.log(result.history) // Full execution history`}
<CodeEditor <CodeEditor
language="typescript" language="typescript"
code={`class PageAgent extends PageAgentCore { code={`class PageAgent extends PageAgentCore {
/** The UI panel instance */
panel: Panel panel: Panel
pageController: PageController
constructor(config: PageAgentConfig) constructor(config: PageAgentConfig)
}`} }`}
/> />
@@ -90,7 +93,21 @@ console.log(result.history) // Full execution history`}
> >
PageAgentCore PageAgentCore
</Link> </Link>
API PageAgentCore {' '}
<Link
href="/advanced/page-agent-core#configuration"
className="text-blue-600 dark:text-blue-400 hover:underline"
>
AgentConfig
</Link>{' '}
{' '}
<Link
href="/advanced/page-controller#configuration"
className="text-blue-600 dark:text-blue-400 hover:underline"
>
PageControllerConfig
</Link>
</> </>
) : ( ) : (
<> <>
@@ -101,71 +118,34 @@ console.log(result.history) // Full execution history`}
> >
PageAgentCore PageAgentCore
</Link> </Link>
. All core methods and events are available. See PageAgentCore docs for detailed API . All core methods and events are available. Config merges{' '}
reference.
</>
)}
</p>
</section>
{/* Configuration */}
<section className="mb-10">
<Heading id="configuration">{isZh ? '配置' : 'Configuration'}</Heading>
<p className="text-gray-600 dark:text-gray-400 mb-4">
{isZh
? 'PageAgent 使用与 PageAgentCore 相同的配置接口。'
: 'PageAgent uses the same configuration interface as PageAgentCore.'}
</p>
<p className="text-gray-600 dark:text-gray-400 mb-4">
{isZh ? (
<>
{' '}
<Link <Link
href="/advanced/page-agent-core" href="/advanced/page-agent-core#configuration"
className="text-blue-600 dark:text-blue-400 hover:underline" className="text-blue-600 dark:text-blue-400 hover:underline"
> >
PageAgentCore AgentConfig
</Link>
</>
) : (
<>
See{' '}
<Link
href="/advanced/page-agent-core"
className="text-blue-600 dark:text-blue-400 hover:underline"
>
PageAgentCore configuration docs
</Link>{' '} </Link>{' '}
for complete reference. and{' '}
<Link
href="/advanced/page-controller#configuration"
className="text-blue-600 dark:text-blue-400 hover:underline"
>
PageControllerConfig
</Link>
.
</> </>
)} )}
</p> </p>
</section> </section>
{/* Panel Property */} {/* Panel */}
<section className="mb-10"> <section className="mb-10">
<Heading id="panel-property">{isZh ? 'Panel 属性' : 'Panel Property'}</Heading> <Heading id="panel">{isZh ? 'UI 面板' : 'UI Panel'}</Heading>
<p className="text-gray-600 dark:text-gray-400 mb-4"> <p className="text-gray-600 dark:text-gray-400 mb-4">
{isZh {isZh
? 'PageAgent 自动创建一个 Panel 实例。你可以通过 panel 属性访问它来控制 UI' ? 'PageAgent 自动创建一个 Panel 实例。你可以通过 panel 属性控制 UI'
: 'PageAgent automatically creates a Panel instance. You can access it via the panel property to control the UI:'} : 'PageAgent automatically creates a Panel instance. You can control the UI via the panel property:'}
</p> </p>
<APIReference
properties={[
{
name: 'panel',
type: 'Panel',
required: true,
description: isZh
? '内置的 UI 面板实例,用于显示任务进度和接收用户输入。'
: 'The built-in UI panel instance for displaying task progress and receiving user input.',
},
]}
/>
<h3 className="text-lg font-semibold mt-6 mb-3">{isZh ? 'Panel 方法' : 'Panel Methods'}</h3>
<CodeEditor <CodeEditor
language="typescript" language="typescript"
code={`// Show/hide the panel code={`// Show/hide the panel
@@ -212,16 +192,16 @@ agent.panel.dispose()`}
</tr> </tr>
<tr className="bg-white dark:bg-gray-900"> <tr className="bg-white dark:bg-gray-900">
<td className="px-4 py-3 text-gray-600 dark:text-gray-400"> <td className="px-4 py-3 text-gray-600 dark:text-gray-400">
{isZh ? 'Headless 模式' : 'Headless Mode'} {isZh ? '自动创建 PageController' : 'Auto-creates PageController'}
</td> </td>
<td className="px-4 py-3 text-center text-gray-400 dark:text-gray-600">-</td>
<td className="px-4 py-3 text-center text-green-600 dark:text-green-400"></td> <td className="px-4 py-3 text-center text-green-600 dark:text-green-400"></td>
<td className="px-4 py-3 text-center text-gray-400 dark:text-gray-600">-</td>
</tr> </tr>
<tr className="bg-white dark:bg-gray-900"> <tr className="bg-white dark:bg-gray-900">
<td className="px-4 py-3 text-gray-600 dark:text-gray-400"> <td className="px-4 py-3 text-gray-600 dark:text-gray-400">
{isZh ? '自定义 PageController' : 'Custom PageController'} {isZh ? 'Headless 模式' : 'Headless Mode'}
</td> </td>
<td className="px-4 py-3 text-center text-green-600 dark:text-green-400"></td> <td className="px-4 py-3 text-center text-gray-400 dark:text-gray-600">-</td>
<td className="px-4 py-3 text-center text-green-600 dark:text-green-400"></td> <td className="px-4 py-3 text-center text-green-600 dark:text-green-400"></td>
</tr> </tr>
<tr className="bg-white dark:bg-gray-900"> <tr className="bg-white dark:bg-gray-900">

View File

@@ -0,0 +1,286 @@
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
? '在 DOM 提取中包含的额外 HTML 属性(如 data-testid。默认已包含常见属性如 role, aria-label 等。'
: 'Additional HTML attributes to include in DOM extraction (e.g. data-testid). Common attributes like role, aria-label are included by default.',
},
]}
/>
</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>
)
}

View File

@@ -105,27 +105,6 @@ const pageAgentTool = {
</p> </p>
</div> </div>
</div> </div>
<div className="bg-yellow-50 dark:bg-yellow-900/20 border border-yellow-200 dark:border-yellow-800 rounded-lg p-4 mb-6">
<h3 className="text-lg font-semibold text-yellow-900 dark:text-yellow-100 mb-2">
{isZh ? '⚠️ 注意事项' : '⚠️ Notes'}
</h3>
<ul className="text-yellow-800 dark:text-yellow-200 space-y-1 text-sm">
<li>
{' '}
{isZh
? '确保目标网站允许自动化操作'
: 'Ensure target website allows automated operations'}
</li>
<li> {isZh ? '实现适当的频率限制' : 'Implement appropriate rate limiting'}</li>
<li>
{' '}
{isZh
? '敏感操作建议要求人工确认'
: 'Recommend human confirmation for sensitive operations'}
</li>
</ul>
</div>
</div> </div>
) )
} }

View File

@@ -6,15 +6,15 @@ import CustomUIDocs from './advanced/custom-ui/page'
import PageAgentCoreDocs from './advanced/page-agent-core/page' import PageAgentCoreDocs from './advanced/page-agent-core/page'
// Advanced // Advanced
import PageAgentDocs from './advanced/page-agent/page' import PageAgentDocs from './advanced/page-agent/page'
import PageControllerDocs from './advanced/page-controller/page'
import SecurityPermissions from './advanced/security-permissions/page'
// Features // Features
import ChromeExtension from './features/chrome-extension/page' import ChromeExtension from './features/chrome-extension/page'
import Instructions from './features/custom-instructions/page' import Instructions from './features/custom-instructions/page'
import CustomTools from './features/custom-tools/page' import CustomTools from './features/custom-tools/page'
import DataMasking from './features/data-masking/page' import DataMasking from './features/data-masking/page'
import Models from './features/models/page' import Models from './features/models/page'
import BestPractices from './integration/best-practices/page' import ThirdPartyAgent from './features/third-party-agent/page'
import SecurityPermissions from './integration/security-permissions/page'
import ThirdPartyAgent from './integration/third-party-agent/page'
import Limitations from './introduction/limitations/page' import Limitations from './introduction/limitations/page'
// Introduction // Introduction
import Overview from './introduction/overview/page' import Overview from './introduction/overview/page'
@@ -80,6 +80,11 @@ export default function DocsRouter() {
<ChromeExtension /> <ChromeExtension />
</DocsPage> </DocsPage>
</Route> </Route>
<Route path="/features/third-party-agent">
<DocsPage>
<ThirdPartyAgent />
</DocsPage>
</Route>
{/* Advanced */} {/* Advanced */}
<Route path="/advanced/page-agent"> <Route path="/advanced/page-agent">
@@ -92,26 +97,21 @@ export default function DocsRouter() {
<PageAgentCoreDocs /> <PageAgentCoreDocs />
</DocsPage> </DocsPage>
</Route> </Route>
<Route path="/advanced/page-controller">
<DocsPage>
<PageControllerDocs />
</DocsPage>
</Route>
<Route path="/advanced/custom-ui"> <Route path="/advanced/custom-ui">
<DocsPage> <DocsPage>
<CustomUIDocs /> <CustomUIDocs />
</DocsPage> </DocsPage>
</Route> </Route>
<Route path="/integration/security-permissions"> <Route path="/advanced/security-permissions">
<DocsPage> <DocsPage>
<SecurityPermissions /> <SecurityPermissions />
</DocsPage> </DocsPage>
</Route> </Route>
<Route path="/integration/best-practices">
<DocsPage>
<BestPractices />
</DocsPage>
</Route>
<Route path="/integration/third-party-agent">
<DocsPage>
<ThirdPartyAgent />
</DocsPage>
</Route>
{/* Default redirect or 404 */} {/* Default redirect or 404 */}
<Route path="/docs"> <Route path="/docs">

View File

@@ -1,20 +0,0 @@
import BetaNotice from '@/components/BetaNotice'
import CodeEditor from '@/components/CodeEditor'
import { useLanguage } from '@/i18n/context'
export default function BestPractices() {
const { isZh } = useLanguage()
return (
<div>
<h1 className="text-4xl font-bold mb-6">{isZh ? '最佳实践' : 'Best Practices'}</h1>
<BetaNotice />
<p className="text-xl text-gray-600 dark:text-gray-300 mb-6 leading-relaxed">
{isZh
? '使用 page-agent 的最佳实践和常见问题解决方案。'
: 'Best practices and common solutions for using page-agent.'}
</p>
<CodeEditor code={`// TODO`} />
</div>
)
}

View File

@@ -83,7 +83,7 @@ export default function LimitationsPage() {
</div> </div>
{/* Interaction Limitations */} {/* Interaction Limitations */}
<Heading id="interaction-capabilities" className="text-2xl font-bold mb-3"> <Heading id="interaction-capabilities" className="text-2xl font-bold mb-3 mt-6">
{isZh ? '交互能力' : 'Interaction Capabilities'} {isZh ? '交互能力' : 'Interaction Capabilities'}
</Heading> </Heading>
<div className="bg-gray-50 dark:bg-gray-800 rounded-lg p-6 mb-6"> <div className="bg-gray-50 dark:bg-gray-800 rounded-lg p-6 mb-6">
@@ -128,33 +128,25 @@ export default function LimitationsPage() {
</div> </div>
{/* Understanding Limitations */} {/* Understanding Limitations */}
<Heading id="understanding" className="text-2xl font-bold mb-3"> <Heading id="understanding" className="text-2xl font-bold mb-3 mt-6">
{isZh ? '理解能力' : 'Understanding'} {isZh ? '理解能力' : 'Understanding'}
</Heading> </Heading>
<div className="bg-amber-50 dark:bg-amber-900/20 border-l-4 border-amber-400 p-4 mb-6">
<p className="text-amber-800 dark:text-amber-200 mb-2 font-medium">
{isZh
? 'Page Agent 不使用多模态模型,不截图,没有视觉能力。仅通过 DOM 结构理解页面。'
: 'Page Agent does not use multimodal models, does not take screenshots, and has no visual capability. It reads pages through DOM structure only.'}
</p>
<p className="text-amber-700 dark:text-amber-300 text-sm">
{isZh
? '图片、Canvas、WebGL、SVG 等视觉内容无法被识别。页面的语义化程度和可访问性直接影响 AI 的理解准确性。'
: 'Images, Canvas, WebGL, SVG and other visual content cannot be recognized. Page semantic quality and accessibility directly affect AI accuracy.'}
</p>
</div>
{/* Website Quality */} <p className="mb-2 font-medium">
<Heading id="page-quality-matters" className="text-2xl font-bold mb-3"> {isZh
{isZh ? '网页质量影响' : 'Page Quality Matters'} ? 'Page Agent 不使用多模态模型,不截图,没有视觉能力。仅通过 DOM 结构理解页面。'
</Heading> : 'Page Agent does not use multimodal models, does not take screenshots, and has no visual capability. It reads pages through DOM structure only.'}
<div className="bg-gray-50 dark:bg-gray-800 rounded-lg p-6"> </p>
<p className="text-gray-600 dark:text-gray-300 text-sm"> <p className="mb-2 font-medium">
{isZh {isZh
? '反常识的交互逻辑、纯视觉的操作提示、快速出现消失的元素等都会降低自动化成功率。语义化的 HTML 和良好的可访问性会显著提升效果。' ? '图片、Canvas、WebGL、SVG 等视觉内容无法被识别。页面的语义化程度和可访问性直接影响 AI 的理解准确性。'
: 'Counter-intuitive interactions, visual-only cues, and rapidly appearing/disappearing elements reduce automation success. Semantic HTML and good accessibility significantly improve results.'} : 'Images, Canvas, WebGL, SVG and other visual content cannot be recognized. Page semantic quality and accessibility directly affect AI accuracy.'}
</p> </p>
</div> <p className="mb-2 font-medium">
{isZh
? '反常识的交互逻辑、纯视觉的操作提示、快速出现消失的元素等都会降低自动化成功率。语义化的 HTML 和良好的可访问性会显著提升效果。'
: 'Counter-intuitive interactions, visual-only cues, and rapidly appearing/disappearing elements reduce automation success. Semantic HTML and good accessibility significantly improve results.'}
</p>
</div> </div>
</div> </div>
) )

View File

@@ -27,12 +27,12 @@ const SPA_ROUTES = [
'docs/features/custom-instructions', 'docs/features/custom-instructions',
'docs/features/models', 'docs/features/models',
'docs/features/chrome-extension', 'docs/features/chrome-extension',
'docs/features/third-party-agent',
'docs/advanced/page-agent', 'docs/advanced/page-agent',
'docs/advanced/page-agent-core', 'docs/advanced/page-agent-core',
'docs/advanced/page-controller',
'docs/advanced/custom-ui', 'docs/advanced/custom-ui',
'docs/integration/security-permissions', 'docs/advanced/security-permissions',
'docs/integration/best-practices',
'docs/integration/third-party-agent',
] ]
function spaRoutes() { function spaRoutes() {