@cubos/代理服务器-sdk- react-dom
为 Cubos 代理聊天准备的 React 组件 。 这里的一切都让DOM
就跟那个不一样 @cubos/agent-sdk-react,哪个
保持平台中立,所以它的钩子也运行在React Industrial.
bun add @cubos/agent-sdk-react-dom # or npm / pnpm / yarn
它的依赖性是下行链和 lucide-react 为少数
图标。 反应是一个对等方.
代理标记
import { AgentMarkdown } from "@cubos/agent-sdk-react-dom";
<AgentMarkdown>{message.content}</AgentMarkdown>;
这就是整个设置。 GFM 表格,带有语法加亮的有栅栏的代码, TeX, 和已经起作用的表情—— 无样式表可导入。 。 。 .
社保局自己照顾自己
组件导入自己的样式表 。 您的捆绑者决定的方式
它解决了任何其他导入——Vite, Next, Rspack, Webpack, Bun——并且有
没有什么让你记得, 没有命令来正确,没有 styles.css 猎取
在读取.
两个属性使得这个安全 在别人的应用程序:
- 无所逃避. 每个选择者都被设定为此软件包设置的类
它自己的包装符 :
.cubos-agent-sdk-react-dom这里每个组件的 份额,.cubos-agent-sdk-react-dom--markdown这个是规矩 工作表 不能碰任何它没有画的东西. - 没有什么能赢得争论. 整个床单坐落于
cubos-agent-sdk-react-dom级联层,每个选择器被包裹:where(),帮助 无特异性。 一层失去无层 CSS 直接,一个赤裸的p {}击败了零特性规则——这是默认,而你的是 决定.
如果您的应用程序将自己的CSS分层 (Tailwind v4 does), 命名我们的一次这样 命令是明确的,而不是偶然的:
/* Above your `@import`, since that is where a layer's position gets fixed. */
@layer theme, base, cubos-agent-sdk-react-dom, components, utilities;
@import "tailwindcss";
重设后,自课前. 重新设置可以清除边界和
边距 *在它下面,这些缺省 将连同
浏览器的。 在你的部件和公用设施之上, 你的应用必须战斗
此软件包可以重塑任何东西.
他们 --cubos-agent-sdk-react-dom-*在一个街区
此处各部分如下:
.cubos-agent-sdk-react-dom {
--cubos-agent-sdk-react-dom-border: var(--my-border);
--cubos-agent-sdk-react-dom-surface: var(--my-code-bg);
--cubos-agent-sdk-react-dom-keyword: var(--my-pink);
}
大多数你从不碰它:边框,哑音文字和代码表面是混合的
currentColor,所以同一个工作表读的正确 在白页,黑暗的,或者
在一个有色的气泡里 只有六个语法颜色是绝对的,它们
打开 prefers-color-scheme ——如果你的应用程序自己切换出暗模式,则覆盖
那些在你们所选取的事物下的人.
同样的同物是道具, 对于一个在 JavaScript 中的主题或想要一个的应用程序 实例不同于其他实例:
<VoiceMessage colors={{ surface: "#0b57d0", border: "#8ab4f8" }} … />
他们作为内衣定制物产登陆
排在每张样式表的后列,这个软件包包含,没有 !important
随便哪里.
成为你的
// Your design system, element by element. Anything you style here outranks the
// packaged default for that element; anything you leave alone keeps it.
<AgentMarkdown components={{ p: (props) => <p className="my-2" {...props} /> }}>
{text}
</AgentMarkdown>;
components 实值 react-markdown地图,合并在默认值上——如此压倒一切
a 将表格滚动器留在原地. gfm, (中文(简体) ), math 财务报告和审定财务报表 highlight 每个回合
他们的插件关闭。 这就是整个API:没有 unstyled 旗帜,因为
以零特异性标出地层 没有什么可选择的.
有两件事值得了解
Raw HTML 永远不会被渲染,也没有允许它的选择. 消息
内容是模型输出,这是不可信的输入,无论代理如何友好.
rehype-raw 刻意缺失 : 减值, 元素退出 .
KaTeX是你的:它与你的 katex它的样式表是您的
导入. katex 是一个对等依赖,所以写标记的复制是
复制它的 CSS 样式 —— KaTeX 的样式表是为自己发行的
标记,和两本漂移 错误的样式公式,没有失败.
样式表也没有捆绑:它传送字体,并重新导出复制件
从这里来的人会把它们翻一番 在您的应用程序中加入一次:
bun add katex
import "katex/dist/katex.min.css";
没有样式表公式 仍然渲染,只是没有样式. math={false} 若为
经纪人从来不写任何.
语音信息
import { VoiceMessage } from "@cubos/agent-sdk-react-dom";
<VoiceMessage
loadBytes={(signal) => client.fetchAttachment(conversationId, message.id, attachment.id, signal)}
bytes={attachment.bytes}
transcript={message.content}
/>;
这个 填充它所有东西的宽度 语音信息有多广 泡泡的决定 而不是玩家的决定 它只坚持一个地板,所以 没有自有宽度的容器不会在波形周围倒塌 绝对位置.
播放/暂停,一个搜索栏, 时间已过, 复制折叠
在披露下——默认崩溃,因为玩家是消息和
当你想要的时候 字就在那里. defaultTranscriptOpen 打开它.
它做的三件事很容易错过:
- 波形是弹夹自己的. 它从解码样本中读出 峰值 每个桶的振幅,正常化——所以在录制中暂停是一个空白 屏幕。 在字节出现之前 没有东西可以读 赛道是 简单的进步栏而不是一种被发明的模式。 浏览器无法解码器 解码保留了条;它从不中断播放.
- 直到你按下播放键前, 什么都拿不到. 笔录经常回答 {\fn黑体\fs22\bord1\shad0\3ahbe\4ah00\fscx67\fscy66\2chffffff\3ch808080}而充满声音的谈话 {\fn黑体\fs22\bord1\shad0\3ahbe\4ah00\fscx67\fscy66\2chffffff\3ch808080}不应该拉出每一段 下到一个屏幕.
- 搜索控制是真实的
<input type="range">, (中文(简体) ), 键盘和 由我们画的,因为土生土长的拇指需要卖家 伪元素并藏起来opacity输给了尾风的飞行前, 设置opacity: 1每页input从这个包的上一层. - 它衡量a
MediaRecorder图标. 其期限为: 标题, 浏览器报告Infinity(a) 直至通过文件查找; 用于测量和倒行的组件,这就是为什么搜索栏 完全有一个范围.
loadBytes 返回 a Blob 因为字节通常坐落在持枪人身后
符号,该符号 <audio src> 无法携带。 每个字符串在 labels数字 :
<VoiceMessage
loadBytes={…}
labels={{ play: "Tocar", pause: "Pausar", transcript: "Transcrição" }}
/>
记录语音信息
useRecorder 是另一个半 VoiceMessage: 捕获,作为 Blob 准备
页:1 sendAudio。 。 。 .
const rec = useRecorder();
{
rec.state !== "unsupported" && (
<button onClick={() => (rec.state === "recording" ? finish() : rec.start())}>
{rec.state === "recording" ? `Gravando ${rec.seconds}s` : "Gravar"}
</button>
);
}
async function finish() {
const clip = await rec.stop(); // null when nothing was captured
if (clip) await sendAudio(clip);
}
它拥有两样东西 都沉默在错误中
- 容器被探测,没有选择. Chrome和Firefox唱片WebM; (中文); Safari只生产过MP4/AAC和 沉默失败 当请求WebM时—— 一个从未组装过的片段.
- 流出在每个退出路径 - 停,取消,卸载,a
权限失败 。 现场直播
MediaStream保留浏览器的记录 指示器在UI移动很久后点亮,屏幕上没有显示 解释一下.
state 实值 unsupported 不存在的地方 MediaRecorder 或无安全上下文
(单位:千美元)getUserMedia 它只存在于一个中),它会在挂起后而不是在挂起后定居
因此在服务器上可以安全渲染. cancel() 放下带子
而不加以集合; error 带着一个否认的麦克风,这就是失败
值得当着别人的面.
保留记录
useTranscriptAnchor 是底盘记录的卷轴行为
没有任何外表,它使无元素,无阶级, 并交出你们两个
裁判员.
const { scrollRef, contentRef, onScroll, isAtBottom, scrollToEnd } = useTranscriptAnchor({
tailKey: messages.at(-1)?.id,
hasOlder,
loadOlder,
});
<div ref={scrollRef} onScroll={onScroll} className="overflow-auto">
<div ref={contentRef}>{items}</div>
</div>;
{
!isAtBottom && <button onClick={scrollToEnd}>Ver o mais recente</button>;
}
tailKey 尾巴生长时会改变的事物——最后的事件 seq, (中文(简体) ),
信息计数,是否显示输入指标。 这只是一个触发器
数值从不读取. loadOlder 解决 它准备了多少项, (中文(简体) ),
它让一页空空释放锚而不是
将风景点冻结.
4个行为,每个行为都是这个寄存器库中的一个错误,之前它是一个 规则:
- 只有已经跟在后面时才跟着. 读取器记录意图 卷轴,在更新后从未计量过——到那时内容已经增长,所以 坐在最后的某个人 突然"远远"离它很近 随你便.
- 当内容增长时跟随,而不是当React重播时. 笔录
增长的原因没有改变状态:图像解码、字体交换、a
披露打开,一张卡片放出一个框架 晚。 就是这样
contentRef手表,跳过它 留下最后几百像素—— 那些是 答案写在——折叠下方. - 向后呼唤时,请保持读者位置在涂料之前,反对 在犯罪前测量高度 纠正就意味着 发生 时 书页在飞来飞去,书页在他们头一被消耗 是什么把读者丢在他们从未要求跳过的一页的顶端.
- 在内容短于取景口时继续拉,或简称 第一页留下一个无法滚动的框,任何滚动事件都不会向 问余相.
此软件包中属于什么
酒吧是故意高的,因为一个组件包 答案每一个 请求成为聊天 UI 没有人可以重写:
- 它解决了一个问题 协议 ——将模型写出标记,字节 需要玩家的剪辑 机械师 当对与错在任何地方都一样时,这是无形的像一个 记录必须遵循 答案被写入其中。 从来没有 产品品味的问题.
- 有一种明显正确的行为, 或者一种安全不常态 值得保持 在一个地方.
- 造型是委托给别人的,不是烘焙进来的.
- 它已经写了两次.
泡泡,作曲和对话列表失败(1):它们就是出品的地方
最不一样的,还有仪表板 packages/web/components/chats/ 输入
仓库是复制的示例。 记录一个语音符是
下一个候选人——仪表盘上有它,问题只是是否
录音机属于玩家旁边.