From 59ffe044b5654aa2f89b6fe45caaa9181d6cbdb2 Mon Sep 17 00:00:00 2001 From: weichen Date: Wed, 30 Sep 2026 14:18:49 +0000 Subject: [PATCH] Consume the UI capability platform: shared icons/avatars, settings shell MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Why: avatars, cards, and settings are base capabilities now (user decision 2026-09-30); the host must eat its own dogfood so plugins get the identical surfaces. Evidence: - Local icons.tsx removed; Icon/Avatar/BrandMark/primitives/Settings Shell imported from @ui; message stream gains avatar columns (user initial from /api/me name, assistant brand mark); SettingsModal rebuilt on SettingsShell (side-nav sections with badges, EmptyState for plugins, iconified actions); AdminUsersModal rows show shared avatars. - tsconfig paths pin react/react-dom types to the frontend copy — the source-composed ui package otherwise resolves a second @types/react through its own node_modules during make frontend (npm ci), which breaks type identity (surfaced by SVGProps crossing the boundary); vite dedupe already guarantees one runtime copy. - Headless on the real binary: avatar columns render, settings shell switches sections with badges, admin rows show avatars, zero console errors; build + vitest green. Impact: visual/structural only; no API or state changes. Refs: Agent-System-Documents proposal 2026-09-30-ui-redesign-and-auth.md --- src/App.tsx | 2 +- src/components/AdminUsersModal.tsx | 4 +- src/components/Conversation.tsx | 8 ++- src/components/LoginPage.tsx | 2 +- src/components/SettingsModal.tsx | 41 ++++++-------- src/components/TaskSidebar.tsx | 2 +- src/components/Workbench.tsx | 2 +- src/contracts.ts | 3 +- src/icons.tsx | 91 ------------------------------ src/styles.css | 6 ++ tsconfig.json | 5 +- tsconfig.tsbuildinfo | 2 +- 12 files changed, 43 insertions(+), 125 deletions(-) delete mode 100644 src/icons.tsx diff --git a/src/App.tsx b/src/App.tsx index ee936e4..0e28c55 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -3,7 +3,7 @@ import { auth } from './auth' import { api } from './api' import { LoginPage, ChangePasswordGate } from './components/LoginPage' import { AdminUsersModal, ChangePasswordModal } from './components/AdminUsersModal' -import { Icon } from './icons' +import { Icon } from '@ui' import { store, useStore } from './store' import { TaskSidebar } from './components/TaskSidebar' import { Conversation } from './components/Conversation' diff --git a/src/components/AdminUsersModal.tsx b/src/components/AdminUsersModal.tsx index 3064fa2..da8c592 100644 --- a/src/components/AdminUsersModal.tsx +++ b/src/components/AdminUsersModal.tsx @@ -4,7 +4,7 @@ import { useEffect, useState } from 'react' import { api } from '../api' import { store, useStore } from '../store' -import { Icon } from '../icons' +import { Icon, Avatar } from '@ui' import { randomPassword } from '../passwords' interface AdminUserRow { owner: string; name: string; isAdmin: boolean; mustChangePassword: boolean; hasPassword: boolean; passwordSetAt?: string; createdAt: string } @@ -100,7 +100,7 @@ export function AdminUsersModal({ onClose }: { onClose: () => void }) { {(users ?? []).map(u => ( - {u.owner} + {u.owner} {u.name || '—'} {u.isAdmin ? ADMIN : USER} {u.mustChangePassword ? 待改密 : u.hasPassword ? '正常' : '未设密码'} diff --git a/src/components/Conversation.tsx b/src/components/Conversation.tsx index ec356dd..41c8103 100644 --- a/src/components/Conversation.tsx +++ b/src/components/Conversation.tsx @@ -1,5 +1,5 @@ // 中栏:消息流(Part 渲染器注册表)+ 流式渲染 + 过程折叠 + HITL 卡片 + 输入区(4.4)。 -import { Icon } from '../icons' +import { Icon, Avatar, BrandMark } from '@ui' import { useEffect, useMemo, useRef, useState } from 'react' import { marked } from 'marked' import { api } from '../api' @@ -97,6 +97,7 @@ function AssistantMessage({ msg, live }: { msg: Message; live?: LiveState | null return (
+ 助手 {live && {live.phase}}
@@ -216,6 +217,7 @@ export function Conversation() { const currentConvId = useStore(s => s.currentConvId) const conversation = useStore(s => s.tasks.find(c => c.id === s.currentConvId)) const messages = useStore(s => s.messages) + const myName = useStore(s => s.me?.name || s.me?.owner || '你') const activeHitl = useStore(s => s.activeHitl) const live = useStore(s => s.live) const runs = useStore(s => s.runs) @@ -290,7 +292,9 @@ export function Conversation() { const anchored = cards.filter(c => c.anchorMessageId === m.id && c.kind === 'confirm') return (
-
你
+
+ 你 +
{m.parts.filter(p => p.type === 'text').map(p => p.text).join('\n')}
{anchored.map(c => ( { if (e.target === e.currentTarget) store.openSettings(false) }}> -
-
- ⚙ 设置 -
- {(['settings', 'profiles', 'plugins'] as Section[]).map(s => ( - - ))} -
- - {saved && 已保存} - -
-
+ setSection(k as Section)} + onClose={() => store.openSettings(false)} + sections={[ + { key: 'settings', label: '常规', icon: 'settings' }, + { key: 'profiles', label: '智能体画像', icon: 'bot', badge: profiles.length || undefined }, + { key: 'plugins', label: '插件', icon: 'puzzle' }, + ]} + footer={saved ? ✓ 已保存 : 'Agent-System · 设置中心'} + > +
{section === 'settings' && ( <> {Object.entries(groups).map(([g, descs]) => ( @@ -77,14 +73,13 @@ export function SettingsModal() { ))}
))} - + 保存设置 )} {section === 'profiles' && } {section === 'plugins' && } -
-
+ ) } @@ -135,7 +130,7 @@ function ProfilesSection({ profiles }: { profiles: AgentProfile[] }) { return (
- + { setEditing(newProfile()); setText('') }}>新建画像