diff --git a/packages/extension/src/entrypoints/sidepanel/components/ConfigPanel.tsx b/packages/extension/src/entrypoints/sidepanel/components/ConfigPanel.tsx
index 0dc5d0e..2721c39 100644
--- a/packages/extension/src/entrypoints/sidepanel/components/ConfigPanel.tsx
+++ b/packages/extension/src/entrypoints/sidepanel/components/ConfigPanel.tsx
@@ -109,7 +109,7 @@ export function ConfigPanel({ config, onSave, onClose }: ConfigPanelProps) {
Model
setModel(e.target.value)}
className="text-xs h-8"
diff --git a/packages/website/src/i18n/locales/en-US/common.ts b/packages/website/src/i18n/locales/en-US/common.ts
index cdb8fc2..b24ad77 100644
--- a/packages/website/src/i18n/locales/en-US/common.ts
+++ b/packages/website/src/i18n/locales/en-US/common.ts
@@ -39,5 +39,6 @@ export default {
security_permissions: 'Security & Permissions',
page_agent: 'PageAgent',
page_agent_core: 'PageAgentCore',
+ custom_ui: 'Custom UI',
},
}
diff --git a/packages/website/src/i18n/locales/zh-CN/common.ts b/packages/website/src/i18n/locales/zh-CN/common.ts
index d796078..acb4037 100644
--- a/packages/website/src/i18n/locales/zh-CN/common.ts
+++ b/packages/website/src/i18n/locales/zh-CN/common.ts
@@ -38,5 +38,6 @@ export default {
security_permissions: '安全与权限',
page_agent: 'PageAgent',
page_agent_core: 'PageAgentCore',
+ custom_ui: '自定义 UI',
},
}
diff --git a/packages/website/src/pages/docs/Layout.tsx b/packages/website/src/pages/docs/Layout.tsx
index b8bc3da..34952d8 100644
--- a/packages/website/src/pages/docs/Layout.tsx
+++ b/packages/website/src/pages/docs/Layout.tsx
@@ -56,6 +56,7 @@ export default function DocsLayout({ children }: DocsLayoutProps) {
items: [
{ title: t('nav.page_agent'), path: '/advanced/page-agent' },
{ title: t('nav.page_agent_core'), path: '/advanced/page-agent-core' },
+ { title: t('nav.custom_ui'), path: '/advanced/custom-ui' },
],
},
]
diff --git a/packages/website/src/pages/docs/advanced/custom-ui/page.tsx b/packages/website/src/pages/docs/advanced/custom-ui/page.tsx
new file mode 100644
index 0000000..2b12eb3
--- /dev/null
+++ b/packages/website/src/pages/docs/advanced/custom-ui/page.tsx
@@ -0,0 +1,276 @@
+import { useTranslation } from 'react-i18next'
+
+import CodeEditor from '@/components/CodeEditor'
+import { APIDivider, APIReference } from '@/components/ui/api-reference'
+
+export default function CustomUIDocs() {
+ const { i18n } = useTranslation()
+ const isZh = i18n.language === 'zh-CN'
+
+ return (
+
+
{isZh ? '自定义 UI' : 'Custom UI'}
+
+
+ {isZh
+ ? 'PageAgent 的核心逻辑(PageAgentCore)和 UI 完全解耦,通过事件通讯。你可以用自己的 UI 替换内置 Panel。'
+ : 'PageAgent core logic (PageAgentCore) is fully decoupled from UI through events. You can replace the built-in Panel with your own UI.'}
+
+
+ {/* Architecture */}
+
+ {isZh ? '架构' : 'Architecture'}
+
+ {isZh
+ ? 'PageAgent 由三个独立模块组成,可自由组合:'
+ : 'PageAgent consists of three independent modules that can be freely combined:'}
+
+
+
+ PageAgentCore -{' '}
+ {isZh ? '核心 Agent 逻辑,不包含 UI' : 'Core agent logic, no UI'}
+
+
+ PageController -{' '}
+ {isZh ? 'DOM 操作和视觉反馈' : 'DOM operations and visual feedback'}
+
+
+ UI (Panel) -{' '}
+ {isZh
+ ? '用户界面,可替换为自定义实现'
+ : 'User interface, replaceable with custom implementation'}
+
+
+
+
+
+
+ {/* Two Event Streams */}
+
+ {isZh ? '两个事件流' : 'Two Event Streams'}
+
+ {isZh
+ ? 'PageAgentCore 提供两种不同性质的事件流,服务于不同的 UI 需求:'
+ : 'PageAgentCore provides two distinct event streams for different UI needs:'}
+
+
+ {/* Comparison Table */}
+
+
+
+
+
+ {isZh ? '特性' : 'Feature'}
+
+
+ Historical Events
+
+
+ Activity Events
+
+
+
+
+
+
+ {isZh ? '事件名' : 'Event Name'}
+
+
+ historychange
+
+
+ activity
+
+
+
+
+ {isZh ? '持久性' : 'Persistence'}
+
+
+ {isZh ? '持久化到 agent.history' : 'Persisted in agent.history'}
+
+
+ {isZh ? '瞬态,无存储' : 'Transient, not stored'}
+
+
+
+
+ {isZh ? '传给 LLM' : 'Sent to LLM'}
+
+
+ {isZh ? '是' : 'Yes'}
+
+
+ {isZh ? '否' : 'No'}
+
+
+
+
+ {isZh ? '用途' : 'Purpose'}
+
+
+ {isZh ? '构成 Agent 记忆,显示历史步骤' : 'Forms agent memory, displays history'}
+
+
+ {isZh
+ ? '实时 UI 反馈(如 loading 状态)'
+ : 'Real-time UI feedback (e.g., loading state)'}
+
+
+
+
+
+
+
+ {/* All Events */}
+
+ {isZh ? '所有事件' : 'All Events'}
+ ',
+ description: isZh
+ ? '实时活动反馈:thinking, executing, executed, retrying, error'
+ : 'Real-time activity: thinking, executing, executed, retrying, error',
+ },
+ {
+ name: 'dispose',
+ type: 'Event',
+ description: isZh ? 'Agent 被销毁' : 'Agent is disposed',
+ },
+ ]}
+ />
+
+
+ {/* HistoricalEvent Types */}
+
+ HistoricalEvent
+
+ {isZh ? 'agent.history 数组中的事件类型:' : 'Event types in agent.history array:'}
+
+
+
+
+ {/* AgentActivity Types */}
+
+ AgentActivity
+
+ {isZh ? 'activity 事件的 detail 类型:' : 'The detail type of activity events:'}
+
+
+
+
+
+
+ {/* React Hooks Example */}
+
+
+ {isZh ? '使用 React Hooks' : 'Using React Hooks'}
+
+
+ {isZh ? '监听事件并更新 React 状态:' : 'Listen to events and update React state:'}
+
+ (null)
+
+ useEffect(() => {
+ const onStatus = () => setStatus(agent.status)
+ const onHistory = () => setHistory([...agent.history])
+ const onActivity = (e: Event) => setActivity((e as CustomEvent).detail)
+
+ agent.addEventListener('statuschange', onStatus)
+ agent.addEventListener('historychange', onHistory)
+ agent.addEventListener('activity', onActivity)
+
+ return () => {
+ agent.removeEventListener('statuschange', onStatus)
+ agent.removeEventListener('historychange', onHistory)
+ agent.removeEventListener('activity', onActivity)
+ }
+ }, [agent])
+
+ return { status, history, activity }
+}`}
+ />
+
+
+
+
+ {/* Assembly Example */}
+
+
+ {isZh ? '组装 Core + Controller + 自定义 UI' : 'Assembling Core + Controller + Custom UI'}
+
+
+ {isZh
+ ? '参考内置 PageAgent 的实现方式,用自定义 UI 替换 Panel:'
+ : 'Following the built-in PageAgent pattern, replace Panel with custom UI:'}
+
+ )
+
+// 4. Handle user input (optional)
+agent.onAskUser = async (question) => window.prompt(question) || ''
+
+// 5. Execute task
+await agent.execute('Fill the form with test data')
+
+// 6. Cleanup
+agent.dispose()`}
+ />
+
+
+ )
+}
diff --git a/packages/website/src/pages/docs/index.tsx b/packages/website/src/pages/docs/index.tsx
index 19a8296..1d84ff3 100644
--- a/packages/website/src/pages/docs/index.tsx
+++ b/packages/website/src/pages/docs/index.tsx
@@ -3,6 +3,7 @@ import { Route, Switch } from 'wouter'
import Header from '../../components/Header'
import DocsLayout from './Layout'
+import CustomUIDocs from './advanced/custom-ui/page'
import PageAgentCoreDocs from './advanced/page-agent-core/page'
// Advanced
import PageAgentDocs from './advanced/page-agent/page'
@@ -113,6 +114,11 @@ export default function DocsRouter() {
+
+
+
+
+
{/* Default redirect or 404 */}