@tier0/uns-agent-ui
v1.5.1
Published
Tier0 UNS Agent 的前端组件包:聊天面板(SSE 流式对话)、卡片画布、技能管理、定时任务。 配合 Tier0 uns-agent-service 后端使用,宿主应用自行编排布局。
Keywords
Readme
@tier0/uns-agent-ui
Tier0 UNS Agent 的前端组件包:聊天面板(SSE 流式对话)、卡片画布、技能管理、定时任务。 配合 Tier0 uns-agent-service 后端使用,宿主应用自行编排布局。
React components for the Tier0 UNS Agent (chat panel, card canvas, skills, scheduled tasks). Requires a Tier0 uns-agent-service backend.
安装
npm install @tier0/uns-agent-ui包为自包含产物(内部依赖已内联),宿主只需满足 peerDependencies:
react / react-dom(^18.2.0 || ^19.0.0)、use-intl、reactflow、recharts、
zustand、use-sync-external-store、react-markdown、remark-gfm、remark-breaks、
rehype-highlight。
前提:/agent-svc/* 同源反代
包内所有请求(chat SSE、会话、画布持久化、任务)都是 fetch('/agent-svc/...') 同源相对路径,
宿主必须把这个路径反向代理到 uns-agent-service 实例。没有这条反代,UI 挂载正常但聊天/会话/
画布保存全部静默失败。
快速接入
组件按 subpath 导出(ChatPanel 聊天面板 / UnsCanvas 画布)。除组件本身,还有七个必做
接线(漏掉任何一个都是「能编译、跑不对」的静默失败):
configureUnsAgentWorkspaceAccessor——模块级注入缝(画布 store 是非 React 模块,读不到 Provider props),加载时配置一次,否则画布的加载/持久化取不到 workspaceId 空转;useUnsChatStore.getState().initForWorkspace(...)——会话 store 初始化(挂载时一次,可放 useEffect),否则 ChatPanel 永远处于「恢复中」状态、无法发消息;UnsCanvas外面包ReactFlowProvider(组件体内调 ReactFlow hooks,宿主提供 context);- 挂
<UnsAgentToaster />(包根导出)——sonner 已内联进包,包内toast.error(...)只有 这个同实例 Toaster 收得到,宿主自己装的 sonner Toaster 收不到; - messages 两段拼齐:
{ uns: <包 i18n JSON> }之外还要 spreadi18n-ui的uiMessages*(内联的 UI 基础组件消费ui.*词条,缺了弹窗/确认按钮/空态渲染裸 key), en/zh-cn/ja/ko 四语言的 uns 与 ui 词表包里都有; configureUnsAgentI18n——React 树之外的确定性文案(agent 回复状态行、定时任务描述等) 拿不到 IntlProvider,这个缝喂 messages 取词,不配则这类文案渲染裸 key;configureUnsAgentClient——请求层错误提示注入(t+toast),不配则请求失败的默认 错误提示静默无声(有安全兜底不抛错,但用户看不到失败原因)。
另有一个强烈建议的 Provider prop:portalContainer(返回一个自带 .tier0-uns-agent
class 的零尺寸锚点元素)——包内抽屉/对话框/下拉/@ 选择器默认 portal 到 document.body,
落在作用域盒之外会丢全部 scoped 样式。
import { IntlProvider } from 'use-intl';
import { ReactFlowProvider } from 'reactflow';
import zhCn from '@tier0/uns-agent-ui/i18n/zh-cn.json';
import { UnsAgentProvider, UnsAgentToaster } from '@tier0/uns-agent-ui';
import { ChatPanel } from '@tier0/uns-agent-ui/components/chat-panel';
import { UnsCanvas } from '@tier0/uns-agent-ui/components/uns-canvas';
import { uiMessagesZhCn } from '@tier0/uns-agent-ui/i18n-ui';
import { configureUnsAgentI18n } from '@tier0/uns-agent-ui/lib/i18n-adapter';
import { configureUnsAgentClient } from '@tier0/uns-agent-ui/client/host-adapter';
import { configureUnsAgentWorkspaceAccessor } from '@tier0/uns-agent-ui/store/workspace-adapter';
import { useUnsChatStore } from '@tier0/uns-agent-ui/store/unsChat';
import '@tier0/uns-agent-ui/style.css';
const messages = { uns: zhCn, ...uiMessagesZhCn }; // 接线 5:uns + ui 词表拼齐
// 接线 1:画布 store 的 workspace 来源(模块加载时一次)
configureUnsAgentWorkspaceAccessor(() => 'default');
// 接线 6:React 树之外的确定性文案取词(agent 回复状态行等)
configureUnsAgentI18n({ getMessages: async () => messages, getMessagesSync: () => messages });
// 接线 7:请求层错误提示(t 取词 + notify 弹提示,按宿主习惯实现)
configureUnsAgentClient({
notify: (message) => {
/* 宿主的 message/toast 组件 */
},
});
// 接线 2:会话 store 初始化(示意;真实代码放挂载 useEffect 里)
useUnsChatStore.getState().initForWorkspace('default');
<IntlProvider locale="zh-cn" messages={messages}>
<UnsAgentProvider workspaceId="default" treeData={宿主的树} mqtt={宿主的桥}>
<div style={{ display: 'flex', height: '100%' }}>
<ReactFlowProvider>
{/* 接线 3 */}
<UnsCanvas />
</ReactFlowProvider>
<ChatPanel
onClose={() => {
/* 宿主自行收起聊天栏 */
}}
/>
</div>
<UnsAgentToaster />
{/* 接线 4:包内 toast 的渲染出口 */}
</UnsAgentProvider>
</IntlProvider>;样式
- 必须
import '@tier0/uns-agent-ui/style.css';全部样式作用域在.tier0-uns-agent前缀下 (UnsAgentProvider根节点自动挂载,display:contents不占布局盒子),不污染宿主页面、 不带 preflight 重置。 - 深色模式:跟随祖先元素的
.darkclass(不是prefers-color-scheme媒体查询),与宿主 的主题开关策略保持一致即可。
i18n(双宿主兼容)
包内组件统一从 use-intl 导入 useTranslations——next-intl 是 use-intl 的薄封装、共用同一个
React Context,因此:
- Next.js 宿主:套自己已有的
next-intlNextIntlClientProvider即可,不需额外配置; - 非 Next 宿主(如 Vite):套
use-intl的IntlProvider(本包 peer)。
文案随包分发(i18n/en.json / zh-cn.json / ja.json / ko.json,扁平 key),挂载时整体嵌进
{ uns: {...} } 命名空间。IntlProvider 套在应用任意上层节点即可,与宿主既有的 react-intl
互不冲突、互不感知。
类型完备性(已知限制)
根入口与常用子路径的 d.ts 零内联依赖引用;部分深层子路径(chat-panel 内部类型、store 状态
形状)的 d.ts 引用了未随包分发的内部类型源——宿主 TS 解析不到时这些类型退化为 any,
只影响 IDE 提示与类型检查精度,不影响运行时与构建。
License
MIT
