From 97cdb1e1cda613c87c452d676b5ad4674e2c0156 Mon Sep 17 00:00:00 2001 From: Simon <10131203+gaomeng1900@users.noreply.github.com> Date: Fri, 30 Jan 2026 14:58:33 +0800 Subject: [PATCH] docs: Add `Custom UI` doc --- .../sidepanel/components/ConfigPanel.tsx | 2 +- .../website/src/i18n/locales/en-US/common.ts | 1 + .../website/src/i18n/locales/zh-CN/common.ts | 1 + packages/website/src/pages/docs/Layout.tsx | 1 + .../pages/docs/advanced/custom-ui/page.tsx | 276 ++++++++++++++++++ packages/website/src/pages/docs/index.tsx | 6 + 6 files changed, 286 insertions(+), 1 deletion(-) create mode 100644 packages/website/src/pages/docs/advanced/custom-ui/page.tsx 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) {
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 */}