主题开发

本页供制作主题时查阅配置能力和约束。第一次制作主题,可以跟随主题开发指南。选择、应用和导入主题见主题。

主题组成与配置

主题包含基础外观、自定义 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 字符串,不是对象或文件路径。

接口写入方式
TavoJStavo.theme.create({ name, customCss }) 或 tavo.theme.update(id, { customCss })
MCPtavo_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_modemessage 或 visualNovel
visual_novel_bubble_height_ratio数值,0.25–1.0
bubble_display_typebubble 或 flat
custom_css原始 CSS 字符串,省略为 ""
backgroundcharAvatar(布尔)、image(字符串或 null)、imageOpacity(0–1)、color(颜色整数)、bottomOverlayType(none / auto / custom,默认 auto)、bottomOverlayColor(颜色整数,默认 4280427042,仅在 custom 时使用)
user_bubble、character_bubblecolor、blur(0–100)、radius(0–50)、alignment(left / right)
user_bubble_font、character_bubble_font下文的字体对象
user_avatar、character_avatar、group_user_avatar、group_character_avataravatar 和 name(布尔)、radius(0–100)
thinking、status_barfontSize(1–100)、fontWeight(整数 100–900)、color、backgroundColor
consolecolor、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 格式
自定义 CSScustom_csscustomCss
用户气泡user_bubbleuserBubble
使用角色头像背景background.charAvatarbackground.useAvatar
背景图片透明度background.imageOpacitybackground.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:

  1. 按上面的结构准备文件夹,包含 theme.json 和可选的 assets/。
  2. 打开文件夹,选中里面的 theme.json 和 assets/,用系统或压缩软件创建 ZIP。不要压缩外层文件夹,也不要选择 7z 或 RAR 格式。
  3. 将生成文件的扩展名从 .zip 改为 .thm,例如 soft-night.thm。文件管理器隐藏扩展名时,先开启扩展名显示,避免得到 soft-night.thm.zip。
  4. 在 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 主题接口。

没有效果或布局异常时

  1. 确认已开启高级渲染,并且当前聊天正在使用保存后的主题。
  2. 从 CSS Helper 重新选择目标,核对拼写。只在录音、生成或带附件时出现的元素,需要在相应状态下检查。
  3. 检查大括号、分号、属性单位和颜色格式。编辑器提示只是语法辅助。
  4. 检查是否被更具体的规则、内联样式或消息自己的样式覆盖。不要一开始就给所有规则加 !important。
  5. 图片图标不能直接用 color 改色,原生界面和独立 iframe 内部也不会被这些规则修改。
  6. 无法定位时先备份 CSS,再清空并保存。确认恢复后逐段加回规则,定位造成问题的部分。

目录