主题开发
本页供制作主题时查阅配置能力和约束。第一次制作主题,可以跟随主题开发指南。选择、应用和导入主题见主题。
主题组成与配置
主题包含基础外观、自定义 CSS 和随主题保存的资源。不写 CSS 也可以创建、导出和分享完整主题。
| 配置 | 控制内容 |
|---|---|
| 显示模式 | 消息模式或视觉小说模式,视觉小说模式还可调整气泡高度比例 |
| 消息样式 | 气泡或平面布局,以及用户和角色气泡的颜色、模糊、圆角与对齐 |
| 背景 | 颜色、图片、图片透明度,或使用角色头像作为背景 |
| 字体 | 用户和角色的正文样式,以及语气、引用文字的样式与高亮 |
| 头像 | 用户、角色及群聊中的头像显示、圆角和名称显示 |
| 输入区 | 背景、模糊、圆角、发送按钮颜色,以及文字与占位文字样式 |
| 自定义 CSS | 在高级前端渲染中补充公开聊天区域的样式 |
| 资源 | 主题内保存的文件,可供主题背景或 CSS 引用 |
显示模式与消息样式在主题编辑器的气泡设置中调整。布局会影响配置的可见效果,例如平面布局不使用常规气泡外观。思考区和状态栏样式还可通过主题 API 配置,编辑器不提供这两项的独立入口。
配置接口
主题可通过 TavoJS、MCP 和原生工具调用管理。具体方法、字段和取值以对应接口文档或当前工具 schema 为准,不要把界面名称直接当成 API 字段名。
TavoJS 的 theme.create 接受完整或部分主题对象,theme.update 接受递归 patch。气泡颜色字段是 color,不支持 backgroundColor 或边框字段,边框可通过 CSS 设置。
主题 API 的颜色字段使用 #AARRGGBB,例如 #FF202838 表示不透明颜色。CSS 使用标准 CSS 颜色语法,如 #202838 或 rgba(32, 40, 56, 0.8),不要将 API 的八位颜色直接照搬为 CSS 颜色。
官方主题只读。修改共享主题会影响所有使用它的聊天,当前聊天的样式会立即更新。创建主题不会自动绑定到聊天,需要单独应用。
底部遮罩使用 background.bottomOverlayType,取值为 none(关闭)、auto(自动,默认)或 custom(自定义)。background.bottomOverlayColor 仅在 custom 时使用,采用包含透明度的 #AARRGGBB,默认 #FF222222。例如 { background: { bottomOverlayType: "custom", bottomOverlayColor: "#CC202838" } }。
自定义 CSS
customCss 是原始 CSS 字符串,只在高级前端渲染中生效。不要包含 HTML、<style> 标签或 Markdown 代码围栏。编辑器的语法提示不阻止保存,也不代表浏览器一定支持所有属性。
作用范围与覆盖规则
- CSS 随主题保存,使用同一主题的聊天会共享这些规则。要只修改一个聊天,先创建或复制独立主题,再绑定到该聊天。
- 自定义样式在主题基础样式之后应用。
- CSS 可以修改下表列出的消息、头像和 Web 输入区。设置页、菜单和系统弹窗不在作用范围内。
- 清空自定义 CSS 并保存即可恢复主题的基础样式。仅更改基础颜色等设置时,已有 CSS 仍可能覆盖这些设置。
公开选择器
以下清单与应用内 CSS Helper 一致,是对外支持的全部选择器。使用这些选择器搭配标准 CSS 属性,不要依赖未列出的 DOM 类、内部 CSS 变量、私有属性或子节点结构。
公开选择器使用 .tavo- 前缀。先前文档列出的 .tav- 对应名称仍兼容已有主题,其他 .tav- class 属于内部实现。
| 选择器 | 作用区域 |
|---|---|
.tavo-bubble | 所有消息气泡 |
.tavo-user-bubble | 用户气泡 |
.tavo-character-bubble | 角色气泡 |
.tavo-bubble-content | 所有气泡内容容器 |
.tavo-user-bubble-content | 用户气泡内容容器 |
.tavo-character-bubble-content | 角色气泡内容容器 |
.tavo-bubble-content-body | 气泡内容主体 |
.tavo-message-divider | 平面消息分割线 |
.tavo-action-bar-button | 操作栏按钮,包含插件和更多按钮,不包含弹出菜单项 |
.tavo-action-bar-button-group | 组合按钮的背景和圆角 |
.tavo-message-content | 消息正文 |
.tavo-message-attachments | 消息附件区域 |
.tavo-message-reasoning | 整个思考过程区域 |
.tavo-message-reasoning > summary | 思考过程标题 |
.tavo-avatar | 所有头像 |
.tavo-user-avatar, .tavo-group-user-avatar | 用户头像,含群聊 |
.tavo-character-avatar, .tavo-group-character-avatar | 角色头像,含群聊 |
.tavo-speaker-name | 发言人名称 |
.tavo-composer | 输入区域 |
.tavo-composer-shell | 输入框外壳 |
.tavo-composer-input | 文字输入框 |
.tavo-composer-add-icon | 加号图标 |
.tavo-composer-send-icon | 发送图标 |
.tavo-composer-stop-icon | 停止图标 |
.tavo-composer-voice-icon | 录音图标 |
分割线用于平面模式,最后一条消息不显示。统一操作按钮的底色和圆角时,请同时设置 .tavo-action-bar-button 和 .tavo-action-bar-button-group,后者负责连体按钮的共享背景。这些选择器覆盖原生、插件及更多按钮,不包含弹出菜单项。
内容容器适合设置字体,气泡外层适合设置背景、边框和阴影。正文中有单独样式的文字可能不会继承容器颜色。思考、附件、头像和名称只有在对应内容存在且启用显示时才有可见效果,具体布局也取决于气泡或平面等显示模式。
发送、停止和录音图标随输入区状态切换,并非同时存在。停止图标用于生成停止和桌面录音停止状态。图标选择器命中的是图片,适合调整尺寸、透明度或滤镜,color 不会直接给图片改色。修改图标不等于修改按钮的点击范围。
可复制的样式
正文间距与角色气泡边框
.tavo-message-content {
line-height: 1.8;
letter-spacing: 0.02em;
}
.tavo-character-bubble {
border: 1px solid rgba(160, 180, 220, 0.4);
box-shadow: 0 4px 14px rgba(0, 0, 0, 0.12);
}输入框背景、圆角与文字
.tavo-composer-shell {
background: rgba(24, 28, 40, 0.85);
border: 1px solid rgba(180, 195, 230, 0.35);
border-radius: 16px;
backdrop-filter: blur(12px);
-webkit-backdrop-filter: blur(12px);
}
.tavo-composer-input {
color: #edf2ff;
font-size: 16px;
}停止图标
.tavo-composer-stop-icon {
width: 22px;
height: 22px;
opacity: 0.85;
}思考标题与发言人
.tavo-message-reasoning > summary {
font-weight: 600;
opacity: 0.8;
}
.tavo-speaker-name {
letter-spacing: 0.04em;
}每次先加一段规则,再预览效果。避免用全局样式重排聊天页面,也不要修改输入区的定位、交互状态或事件处理。
通过 API 或工具保存 CSS
三个接口写入同一个顶层字段 customCss,值是原始 CSS 字符串,不是对象或文件路径。
| 接口 | 写入方式 |
|---|---|
| TavoJS | tavo.theme.create({ name, customCss }) 或 tavo.theme.update(id, { customCss }) |
| MCP | tavo_theme_create 的 theme.customCss,或 tavo_theme_update 的 patch.customCss,更新使用 id |
| 原生 Tool Calling | 同名主题工具的 theme.customCss / patch.customCss,更新使用 themeId |
创建时省略 customCss 默认是空字符串。更新时省略则保留原值,传 "" 清空,传入新字符串会替换整段 CSS,不会按选择器合并。想保留旧规则时先读取主题,再自行合并字符串。null 不是有效的清空方式。API 保存字符串不等于验证 CSS 语法或视觉效果。
const id = await tavo.theme.create({
name: '柔和边框',
customCss: '.tavo-character-bubble { border: 1px solid rgba(160, 180, 220, 0.4); }',
})
await tavo.chat.update({ theme: id })需要恢复时,单独执行:
await tavo.theme.update(id, { customCss: '' })更新当前使用的主题后,样式会立即生效。创建主题本身不会自动将它应用到当前聊天。修改已有共享主题前应明确受影响的聊天。
资源引用与打包
在主题编辑器的 自定义样式 → 资源 中导入文件。资源旁的 复制地址 会复制完整的 url("...") 表达式,可以直接作为 CSS 的 background-image 等属性值。
- 地址只在所属主题中有效,不是外部下载链接。使用实际复制或 API 返回的地址,避免自行拼接文件名。
- 同名导入会自动改名,后续引用使用导入后的实际名称。
- 重命名或删除资源不会自动改写
customCss,需要同步修改 CSS 引用。用作主题背景的资源则会同步更新或清空背景引用。 .thm导出包含主题资源和自定义 CSS。CSS 中直接引用的外部图片与字体不会自动打包。
通过 TavoJS 主题资源接口导入时,返回的 url 是地址字符串,在 CSS 中需要放入 url(...),也可以赋给 background.image。资源通过 theme.assets 单独管理,theme.get() 不返回资源列表,theme.create/update 也不接受 assets 字段。
主题包格式(离线制作)
Agent 无需连接 MCP,也可以在本地生成 .thm 文件供用户导入。本节和示例描述当前主题包格式。旧版本可能使用不同的资源封装和大小限制,面向旧版本时应在目标版本中导入验证。
ZIP 结构
.thm 是使用 ZIP 格式压缩、扩展名为 .thm 的文件。包根目录必须直接包含 UTF-8 编码的 theme.json,不要再包一层主题文件夹。图片等资源放在单层 assets/ 下:
soft-night.thm
├── theme.json
└── assets/
└── paper.png没有资源时,只打包 theme.json 即可。CSS 写入 JSON 的 custom_css 字符串,不会自动加载单独的 .css 文件。
最小清单与默认值
下面是可以导入的最小 theme.json:
{
"spec": "tavo_theme_v1",
"name": "Minimal Theme"
}spec 必须为 tavo_theme_v1,name 去除首尾空白后须为 1–40 个 UTF-16 代码单元。其余字段可省略。省略时使用导入版本的主题默认值,不继承当前聊天主题:显示模式为 message,消息样式为 bubble,视觉小说气泡高度比例为 0.6,CSS 为空字符串。
外观需要稳定时,请明确填写用到的样式。省略整个样式对象与提供部分对象的默认结果不一定相同,例如省略 user_bubble 使用用户气泡默认右对齐,但提供该对象后省略 alignment 会使用气泡对象默认的 left。下载完整示例清单作为起点更合适。
清单字段
包格式不是 API 对象格式。顶层使用下表的字段名,嵌套样式使用表中列出的名称。不要将 MCP 或 TavoJS 返回的对象直接当作 theme.json。
| 包字段 | 类型、取值或嵌套字段 |
|---|---|
spec、name | 必填字符串,见上文 |
display_mode | message 或 visualNovel |
visual_novel_bubble_height_ratio | 数值,0.25–1.0 |
bubble_display_type | bubble 或 flat |
custom_css | 原始 CSS 字符串,省略为 "" |
background | charAvatar(布尔)、image(字符串或 null)、imageOpacity(0–1)、color(颜色整数)、bottomOverlayType(none / auto / custom,默认 auto)、bottomOverlayColor(颜色整数,默认 4280427042,仅在 custom 时使用) |
user_bubble、character_bubble | color、blur(0–100)、radius(0–50)、alignment(left / right) |
user_bubble_font、character_bubble_font | 下文的字体对象 |
user_avatar、character_avatar、group_user_avatar、group_character_avatar | avatar 和 name(布尔)、radius(0–100) |
thinking、status_bar | fontSize(1–100)、fontWeight(整数 100–900)、color、backgroundColor |
console | color、blur(0–100)、radius(0–50)、sendColor、fontSize(1–100)、fontWeight(整数 100–900)、fontColor、placeholderColor |
每个字体对象支持以下字段:
textStyle、toneTextStyle、quoteTextStyle:分别为正文、语气和引用文字样式。每项包含fontFamily(字符串或null,默认继承字体)、fontSize(1–100,默认 16)、fontWeight(整数 100–900,默认 400)、fontStyle(normal/italic,默认normal)和color。- 正文
color使用颜色整数。语气和引用的color可为null,表示继承。要保留继承语义,请显式写null。 toneHighlight、quoteHighlight:布尔值,默认true。toneDelimiters、quoteDelimiters:字符串数组,默认分别为["**", "()", "()"]与["“”", "「」", "\"\""]。toneSymbol、quoteSymbol:输出符号字符串,默认分别为none和两个双引号""。使用none表示不添加符号。
嵌套对象默认值可受字体迁移和语言设置影响,完整示例显式提供三套文字样式。创建新包时使用这些嵌套样式,不必添加旧版字体兼容字段。不要写入数据库 ID、官方标记或更新时间。
颜色与 API 的区别
所有包内颜色字段都是 JSON 十进制整数,含义为 32 位 0xAARRGGBB。例如不透明的 #202838 在包中写为 4280297528。JSON 不支持 0xFF202838 这样的数字写法,也不要使用 "#FF202838" 字符串。可让 AI 将 ARGB 十六进制颜色转换为十进制整数。
| 含义 | 包格式 | TavoJS / MCP 格式 |
|---|---|---|
| 自定义 CSS | custom_css | customCss |
| 用户气泡 | user_bubble | userBubble |
| 使用角色头像背景 | background.charAvatar | background.useAvatar |
| 背景图片透明度 | background.imageOpacity | background.opacity |
| 颜色 | 4280297528 | "#FF202838" |
CSS 字符串内部仍使用标准 CSS 颜色语法。不要把这些整数直接写进 CSS。
图片资源引用
建议将图片保存为 assets/ 下的独立文件,再通过 theme/assets/... 引用,避免将图片以 Base64 data URL 写入 theme.json,使配置文件更小、更易编辑。
ZIP 内的文件名是 assets/paper.png,在 CSS 和 background.image 中引用时使用 theme/assets/paper.png。文件名中的空格、中文等需要按 URL 路径段编码,例如 纸张 1.png 引用为 theme/assets/%E7%BA%B8%E5%BC%A0%201.png。仅对文件名编码,不编码整个路径。
{
"spec": "tavo_theme_v1",
"name": "Paper Texture",
"background": {
"charAvatar": false,
"image": "theme/assets/paper.png",
"imageOpacity": 1,
"color": 4280297528
},
"custom_css": ".tavo-character-bubble { background-image: url(\"theme/assets/paper.png\"); }"
}使用图片背景时设置 charAvatar: false,否则角色头像背景优先。CSS 纹理需要高级前端渲染。图片文件必须实际包含在包中,导入成功不代表 CSS 中所有资源引用都已经验证。
新制作的独立主题包使用 assets/ 目录,不要同时写入旧版 JSON 内嵌的 assets 字段。资源文件名不能包含路径分隔符、控制字符或 :*?"<>|,不能以空格或点结尾,也不能使用 Windows 保留名(如 CON、NUL)。资源不支持嵌套目录,文件名不能仅大小写不同。
打包与示例下载
示例纹理为本指南生成的原创程序纹理,可自由用于、修改和分享主题。可以直接导入示例包,也可以下载清单和 PNG 后自行打包,不需要 Python:
- 按上面的结构准备文件夹,包含
theme.json和可选的assets/。 - 打开文件夹,选中里面的
theme.json和assets/,用系统或压缩软件创建 ZIP。不要压缩外层文件夹,也不要选择 7z 或 RAR 格式。 - 将生成文件的扩展名从
.zip改为.thm,例如soft-night.thm。文件管理器隐藏扩展名时,先开启扩展名显示,避免得到soft-night.thm.zip。 - 在 Tavo 中选择 导入主题,导入并预览。
ZIP 根目录应直接看到 theme.json,图片位于 assets/。如果压缩工具附带了 __MACOSX/ 等额外目录,请移除后再导入。已有清单和素材无需额外转换,只需正确打包。
可以给 Agent 这样的任务:
请阅读主题开发参考中的“主题包格式”,在本地制作一个可导入 Tavo 的 .thm 文件。
以提供的完整示例清单为起点,保留正确的包字段和整数颜色格式。
使用随包提供的 paper.png 作为气泡纹理,CSS 只使用公开选择器。
用 ZIP Deflate 打包,theme.json 位于根目录,图片位于 assets/,不要额外套文件夹。
交付 .thm 文件以及可编辑的清单和资源,并说明需要开启高级前端渲染。限制与导入验证
当前压缩包最大 256 MiB,解压内容总计最大 1 GiB,根目录普通条目最多 64 个,assets/ 中资源最多 4096 个。theme.json 没有单独大小上限,但计入总大小。路径穿越、绝对路径、符号链接、重复条目以及 assets/ 之外的目录会被拒绝。
交付前,在目标版本的 Tavo 中导入并另存为测试副本。应用到测试聊天,检查基础样式、CSS 和图片,再导出、重新导入,确认资源仍可用。离线 Agent 可以验证 ZIP 和 JSON,只有实际导入及预览才能确认目标版本兼容性和视觉效果。
导入与导出
使用 Tavo 的导出功能生成 .thm 主题文件。同名导入时可选择覆盖或另存,与官方主题同名时只能另存。
通过 TavoJS 调用 theme.export 会返回当前聊天文件区的虚拟路径,不会自动打开系统分享界面。要保存到 Tavo 外部,前台脚本再调用 tavo.file.export(path)。具体调用和文件限制见TavoJS 主题接口。
没有效果或布局异常时
- 确认已开启高级渲染,并且当前聊天正在使用保存后的主题。
- 从 CSS Helper 重新选择目标,核对拼写。只在录音、生成或带附件时出现的元素,需要在相应状态下检查。
- 检查大括号、分号、属性单位和颜色格式。编辑器提示只是语法辅助。
- 检查是否被更具体的规则、内联样式或消息自己的样式覆盖。不要一开始就给所有规则加
!important。 - 图片图标不能直接用
color改色,原生界面和独立 iframe 内部也不会被这些规则修改。 - 无法定位时先备份 CSS,再清空并保存。确认恢复后逐段加回规则,定位造成问题的部分。