词元之母TOK.MOM - 平台充值汇率 1:1 即 1 人民币充值到账 1 美元,支持一个 Key 调用近 600+ 海内外模型,限时特价模型低至 1 折,欢迎上岸!
hermes dashboard)在设计上支持换肤和扩展,无需 fork 代码库。对外暴露三个层次:~/.hermes/dashboard-themes/,即可在主题切换器中看到它。manifest.json 和 JavaScript bundle 的目录,可注册标签页、替换内置页面、通过页面级插槽增强内置页面,或向命名 shell 插槽注入组件。router; 路由挂载在 /api/plugins/<name>/ 下,由插件的 UI 调用。npm run build、无需修改 dashboard 源码。本页是三者的权威参考文档。strike-freedom-cockpit 演示正是如此。参见主题 + 插件组合演示。~/.hermes/dashboard-themes/ 中的 YAML 文件。文件名无关紧要(系统使用主题的 name: 字段),但惯例是 <name>.yaml。所有字段均为可选——缺失的键会回退到内置的 default 主题,因此一个主题可以只包含一个颜色。color-mix() 从这两个颜色自动计算得出。color-mix() 从这三层颜色派生出所有兼容 shadcn 的 token(card、popover、muted、border、primary、destructive、ring 等)。覆盖三个颜色即可级联影响整个 UI。| 键 | 描述 |
|---|---|
palette.background | 最深的画布颜色——通常接近黑色。驱动页面背景和卡片填充。 |
palette.midground | 主要文字和强调色。大多数 UI 外观读取此值(前景文字、按钮轮廓、焦点环)。 |
palette.foreground | 顶层高亮色。默认主题将其设为 alpha 为 0 的白色(不可见);需要顶层亮色强调的主题可提高其 alpha 值。 |
palette.warmGlow | rgba(...) 字符串,用作 <Backdrop /> 的晕光颜色。 |
palette.noiseOpacity | 0–1.2 的颗粒叠加层倍增器。越低越柔和,越高越粗粝。 |
{hex: "#RRGGBB", alpha: 0.0–1.0} 或裸十六进制字符串(alpha 默认为 1.0)。| 键 | 类型 | 描述 |
|---|---|---|
fontSans | string | 正文的 CSS font-family 栈(应用于 html、body)。 |
fontMono | string | 代码块、<code>、.font-mono 工具类的 CSS font-family 栈。 |
fontDisplay | string | 可选的标题/展示字体栈。回退到 fontSans。 |
fontUrl | string | 可选的外部样式表 URL。在主题切换时以 <link rel="stylesheet"> 注入 <head>。相同 URL 不会重复注入。支持 Google Fonts、Bunny Fonts、自托管 @font-face 样式表——任何可链接的资源均可。 |
baseSize | string | 根字体大小——控制 rem 比例。例如 "14px"、"16px"。 |
lineHeight | string | 默认行高。例如 "1.5"、"1.65"。 |
letterSpacing | string | 默认字间距。例如 "0"、"0.01em"、"-0.01em"。 |
| 键 | 值 | 描述 |
|---|---|---|
radius | 任意 CSS 长度("0"、"0.25rem"、"0.5rem"、"1rem" 等) | 圆角 token。映射到 --radius 并级联到 --radius-sm/md/lg/xl——所有圆角元素同步变化。 |
density | compact | comfortable | spacious | 间距倍增器,以 --spacing-mul CSS 变量形式应用。compact = 0.85×,comfortable = 1.0×(默认),spacious = 1.2×。缩放 Tailwind 的基础间距,因此 padding、gap 和 space-between 工具类均按比例调整。 |
layoutVariant 选择整体 shell 布局。缺省时默认为 "standard"。| 变体 | 行为 |
|---|---|
standard | 单列,最大宽度 1600px(默认)。 |
cockpit | 左侧边栏轨道(260px)+ 主内容区。由插件通过 sidebar 插槽填充——参见 Shell 插槽。没有插件时轨道显示占位符。 |
tiled | 取消最大宽度限制,页面可使用完整视口宽度。 |
document.documentElement.dataset.layoutVariant 暴露,因此 customCSS 中的原始 CSS 可通过 :root[data-layout-variant="cockpit"] ... 定向匹配。--theme-asset-<name>),内置 shell 和任何插件均可读取。bg 插槽自动接入 backdrop;其他插槽面向插件开放。url(...)。url(...)、linear-gradient(...)、radial-gradient(...) 表达式——直接使用。"none" ——明确禁用。--theme-asset-<name>-raw(未包装的 URL)形式输出,以便插件需要将其传给 <img src> 而非 background-image 时使用。componentStyles 可在不编写 CSS 选择器的情况下重新设置各 shell 组件的样式。每个桶(bucket)的条目会成为 CSS 变量(--component-<bucket>-<kebab-property>),shell 的共享组件会读取这些变量。因此 card: 的覆盖应用于所有 <Card>,header: 应用于应用栏,以此类推。card、header、footer、sidebar、tab、progress、badge、backdrop、page。clipPath),输出为 kebab-case(clip-path)。值为纯 CSS 字符串——CSS 接受的任何内容均可(clip-path、border-image、background、box-shadow、animation 等)。colorOverrides。card、cardForeground、popover、popoverForeground、primary、primaryForeground、secondary、secondaryForeground、muted、mutedForeground、accent、accentForeground、destructive、destructiveForeground、success、warning、border、input、ring。--color-<kebab> CSS 变量一一对应(例如 primaryForeground → --color-primary-foreground)。此处设置的任何键仅对当前激活主题生效,切换到其他主题时覆盖会被清除。customCSScomponentStyles 无法表达的选择器级外观——伪元素、动画、媒体查询、主题范围内的覆盖——可将原始 CSS 写入 customCSS:<style data-hermes-theme-css> 标签注入,主题切换时清除。每个主题上限为 32 KiB。| 主题 | 调色板 | 字体排版 | 布局 |
|---|---|---|---|
Hermes Teal(default) | 深青色 + 奶油色 | 系统字体栈,15px | 0.5rem 圆角,comfortable |
Hermes Teal (Large)(default-large) | 同 default | 系统字体栈,18px,行高 1.65 | 0.5rem 圆角,spacious |
Midnight(midnight) | 深蓝紫色 | Inter + JetBrains Mono,14px | 0.75rem 圆角,comfortable |
Ember(ember) | 暖深红 + 古铜色 | Spectral(衬线)+ IBM Plex Mono,15px | 0.25rem 圆角,comfortable |
Mono(mono) | 灰度 | IBM Plex Sans + IBM Plex Mono,13px | 0 圆角,compact |
Cyberpunk(cyberpunk) | 黑底霓虹绿 | Share Tech Mono 全局,14px | 0 圆角,compact |
Rosé(rose) | 粉色 + 象牙色 | Fraunces(衬线)+ DM Mono,16px | 1rem 圆角,spacious |
<head> 注入一个 <link> 标签。config.yaml 的 dashboard.theme 下,并在重载时恢复。manifest.json、预构建 JS bundle,以及可选的 CSS 文件和带 FastAPI 路由的 Python 文件的目录。插件与其他 Hermes 插件一起存放在 ~/.hermes/plugins/<name>/——dashboard 扩展是该插件目录内的 dashboard/ 子文件夹,因此一个插件可以从单次安装中同时扩展 CLI/gateway 和 dashboard。window.__HERMES_PLUGIN_SDK__ 上的 Plugin SDK。这使插件 bundle 保持极小体积(通常只有几 KB),并避免版本冲突。// ~/.hermes/plugins/my-plugin/dashboard/manifest.json
{
"name": "my-plugin",
"label": "My Plugin",
"icon": "Sparkles",
"version": "1.0.0",
"tab": {
"path": "/my-plugin",
"position": "after:skills"
},
"entry": "dist/index.js"
}<script> 加载的单个 JS 文件。React 永远不会被打包进去;它来自 SDK.React。~/.hermes/plugins/my-plugin/
├── plugin.yaml # optional — existing CLI/gateway plugin manifest
├── __init__.py # optional — existing CLI/gateway hooks
└── dashboard/ # dashboard extension
├── manifest.json # required — tab config, icon, entry point
├── dist/
│ ├── index.js # required — pre-built JS bundle (IIFE)
│ └── style.css # optional — custom CSS
└── plugin_api.py # optional — backend API routes (FastAPI)plugin.yaml + __init__.py — CLI/gateway 插件(参见插件页面)。dashboard/manifest.json + dashboard/dist/index.js — dashboard UI 插件。dashboard/plugin_api.py — dashboard 后端路由。{
"name": "my-plugin",
"label": "My Plugin",
"description": "What this plugin does",
"icon": "Sparkles",
"version": "1.0.0",
"tab": {
"path": "/my-plugin",
"position": "after:skills",
"override": "/",
"hidden": false
},
"slots": ["sidebar", "header-left"],
"entry": "dist/index.js",
"css": "dist/style.css",
"api": "plugin_api.py"
}| 字段 | 必填 | 描述 |
|---|---|---|
name | 是 | 唯一插件标识符。小写,可用连字符。用于 URL 和注册。 |
label | 是 | 导航标签页中显示的名称。 |
description | 否 | 简短描述(显示在 dashboard 管理界面)。 |
icon | 否 | Lucide 图标名称。默认为 Puzzle。未知名称回退到 Puzzle。 |
version | 否 | Semver 字符串。默认为 0.0.0。 |
tab.path | 是 | 标签页的 URL 路径(例如 /my-plugin)。 |
tab.position | 否 | 标签页插入位置。"end"(默认)、"after:<path>" 或 "before:<path>"——冒号后的值是目标标签页的路径段(无前导斜杠)。例如:"after:skills"、"before:config"。 |
tab.override | 否 | 设置为内置路由路径("/"、"/sessions"、"/config" 等)以替换该页面,而非添加新标签页。参见替换内置页面。 |
tab.hidden | 否 | 为 true 时,注册组件和所有插槽,但不向导航添加标签页。用于仅插槽插件。参见仅插槽插件。 |
slots | 否 | 此插件填充的命名 shell 插槽。仅作文档说明——实际注册通过 JS bundle 中的 registerSlot() 完成。在此列出插槽可使发现界面更具信息量。 |
entry | 是 | 相对于 dashboard/ 的 JS bundle 路径。默认为 dist/index.js。 |
css | 否 | 以 <link> 标签注入的 CSS 文件路径。 |
api | 否 | 包含 FastAPI 路由的 Python 文件路径。挂载在 /api/plugins/<name>/。 |
Puzzle。Activity、BarChart3、Clock、Code、Database、Eye、FileText、Globe、Heart、KeyRound、MessageSquare、Package、Puzzle、Settings、Shield、Sparkles、Star、Terminal、Wrench、Zap。web/src/App.tsx 的 ICON_MAP 提交 PR——纯增量修改。window.__HERMES_PLUGIN_SDK__ 上。插件不应直接导入 React。fetchJSON 会自动注入会话认证 token,将错误作为异常抛出,并自动解析 JSON。| 插槽 | 位置 |
|---|---|
backdrop | <Backdrop /> 层叠栈内,噪点层之上。 |
header-left | 顶栏 Hermes 品牌之前。 |
header-right | 顶栏主题/语言切换器之前。 |
header-banner | 导航栏下方的全宽条带。 |
sidebar | Cockpit 侧边栏轨 道——仅在 layoutVariant === "cockpit" 时渲染。 |
pre-main | 路由出口之上(<main> 内部)。 |
post-main | 路由出口之下(<main> 内部)。 |
footer-left | 底栏单元格内容(替换默认内容)。 |
footer-right | 底栏单元格内容(替换默认内容)。 |
overlay | 位于所有内容之上的固定定位层。适用于 customCSS 无法单独实现的外观效果(扫描线、晕影等)。 |
| 插槽 | 渲染位置 |
|---|---|
sessions:top / sessions:bottom | /sessions 页面顶部 / 底部。 |
analytics:top / analytics:bottom | /analytics 页面顶部 / 底部。 |
logs:top / logs:bottom | /logs 顶部(过滤工具栏之上)/ 底部(日志查看器之下)。 |
cron:top / cron:bottom | /cron 页面顶部 / 底部。 |
skills:top / skills:bottom | /skills 页面顶部 / 底部。 |
config:top / config:bottom | /config 页面顶部 / 底部。 |
env:top / env:bottom | /env(Keys)页面顶部 / 底部。 |
docs:top / docs:bottom | /docs 顶部(iframe 之上)/ 底部。 |
chat:top / chat:bottom | /chat 顶部 / 底部(仅在启用嵌入式聊天时有效)。 |
tab.hidden: true 结合使用。<PluginSlot name="..." />。注册表接受额外的名称用于嵌套插件 UI——插件可通过 SDK.components.PluginSlot 暴露自己的插槽。(plugin, slot) 对被注册两次,后一次调用会替换前一次——这与 React HMR 期望插件重新挂载时的行为一致。tab.override)tab.override 设置为内置路由路径,可使插件组件替换该页面,而非添加新标签页。适用于主题希望自定义首页(/)但保留 dashboard 其余部分的场景。{
"name": "my-home",
"label": "Home",
"tab": {
"path": "/my-home",
"override": "/",
"position": "end"
},
"entry": "dist/index.js"
}override 后:/ 处的原始页面组件被移除。/ 处渲染。tab.path 添加导航标签页(覆盖本身才是目的)。tab.override 完全替换页面代价较重——你的插件现在拥有整个页面,包括我们未来对其的所有更新。大多数情况下,你只是想向现有页面添加横幅、卡片或工具栏。这正是页面级插槽的用途。<page>:top 和 <page>:bottom 插槽。你的插件通过调用 registerSlot() 填充其中一个——内置页面正常工作,你的组件在其旁边渲染。sessions:*、analytics:*、logs:*、cron:*、skills:*、config:*、env:*、docs:*、chat:*(每个均有 :top 和 :bottom)。完整目录参见 Shell 插槽 → 插槽目录。// ~/.hermes/plugins/session-notes/dashboard/manifest.json
{
"name": "session-notes",
"label": "Session Notes",
"tab": { "path": "/session-notes", "hidden": true },
"slots": ["sessions:top"],
"entry": "dist/index.js"
}tab.hidden: true 使插件不出现在侧边栏——它没有独立页面。slots 字段仅作文档说明。实际绑定通过 JS bundle 中的 registerSlot() 完成。hermes-example-plugins 中的 example-dashboard)提供了一个向 sessions:top 注入横幅的实时演示——安装它可端到端了解该模式。tab.hidden)tab.hidden: true 时,插件注册其组件(用于直接 URL 访问)和所有插槽,但不向导航添加标签页。适用于仅用于注入插槽的插件——顶栏徽标、侧边栏 HUD、覆盖层。{
"name": "header-crest",
"label": "Header Crest",
"tab": {
"path": "/header-crest",
"position": "end",
"hidden": true
},
"slots": ["header-left"],
"entry": "dist/index.js"
}register()(以防有人直接访问该 URL),然后调用 registerSlot() 完成实际工作。api 来注册 FastAPI 路由。创建文件并导出 router:/api/plugins/<name>/ 下,因此上述路由变为:GET /api/plugins/my-plugin/dataPOST /api/plugins/my-plugin/action--host 0.0.0.0 将 dashboard 暴露在公共接口上——其路由也会变得可访问。style= 的样式,可添加 CSS 文件并在 manifest 中引用:{
"css": "dist/style.css"
}<link> 标签注入。使用特定类名以避免与 dashboard 样式冲突,并引用 dashboard 的 CSS 变量以保持主题感知:--color-*,以及主题额外变量(--theme-asset-*、--component-<bucket>-*、--radius、--spacing-mul)。引用这些变量后,你的插件会随激活主题自动换肤。dashboard/manifest.json:| 优先级 | 目录 | 来源标签 |
|---|---|---|
| 1(冲突时优先) | ~/.hermes/plugins/<name>/dashboard/ | user |
| 2 | <repo>/plugins/memory/<name>/dashboard/ | bundled |
| 2 | <repo>/plugins/<name>/dashboard/ | bundled |
| 3 | ./.hermes/plugins/<name>/dashboard/ | project——仅在设置 HERMES_ENABLE_PROJECT_PLUGINS 时生效 |
hermes dashboard。main.tsx 在 window.__HERMES_PLUGIN_SDK__ 上暴露 SDK,在 window.__HERMES_PLUGINS__ 上暴露注册表。App.tsx 调用 usePlugins() → 获取 GET /api/dashboard/plugins。<link>(如已声明),然后通过 <script> 标签加载 JS bundle。window.__HERMES_PLUGINS__.register(name, Component)——以及可选的 .registerSlot(name, slot, Component) 用于每个插槽。hidden),并将组件挂载为路由。register()。超时后 dashboard 停止等待并完成初始渲染。如果插件之后才注册,它仍会出现——导航是响应式的。strike-freedom-cockpit 插件(伴随仓库 hermes-example-plugins)是一个完整的换肤演示。它将主题 YAML 与仅插槽插件配对,在不 fork dashboard 的情况下生成驾驶舱风格的 HUD。fontUrl、layoutVariant: cockpit、assets、componentStyles(切角卡片、渐变背景)、colorOverrides 和 customCSS(扫描线叠加)。tab.hidden: true),注册到三个插槽:sidebar — 带有由 SDK.api.getStatus() 驱动的实时遥测条的 MS-STATUS 面板。header-left — 从激活主题读取 --theme-asset-crest 的派系徽标。footer-right — 替换默认组织行的自定义标语。sidebar 插槽仅在 cockpit 布局变体下渲染)。strike-freedom-cockpit/dashboard/dist/index.js),了解它如何读取 CSS 变量、防范不支持插槽的旧版 dashboard,以及如何从单个 bundle 注册三个插槽。| 端点 | 方法 | 描述 |
|---|---|---|
/api/dashboard/themes | GET | 列出可用主题及当前激活名称。内置主题返回 {name, label, description};用户主题还包含带有完整规范化主题对象的 definition 字段。 |
/api/dashboard/theme | PUT | 设置激活主题。请求体:{"name": "midnight"}。持久化到 config.yaml 的 dashboard.theme 下。 |
| 端点 | 方法 | 描述 |
|---|---|---|
/api/dashboard/plugins | GET | 列出已发现的插件(含 manifest,去除内部字段)。 |
/api/dashboard/plugins/rescan | GET | 强制重新扫描插件目录,无需重启。 |
/dashboard-plugins/<name>/<path> | GET | 从插件的 dashboard/ 目录提供静态资源。路径遍历已被阻止。 |
/api/plugins/<name>/* | * | 插件注册的后端路由。 |
window 上的 SDK| 全局变量 | 类型 | 提供方 |
|---|---|---|
window.__HERMES_PLUGIN_SDK__ | object | registry.ts — React、hooks、UI 组件、API 客户端、工具函数。 |
window.__HERMES_PLUGINS__.register(name, Component) | function | 注册插件的主组件。 |
window.__HERMES_PLUGINS__.registerSlot(name, slot, Component) | function | 注册到命名 shell 插槽。 |
~/.hermes/dashboard-themes/ 中且以 .yaml 或 .yml 结尾。刷新页面。运行 curl http://127.0.0.1:9119/api/dashboard/themes——你的主题应出现在响应中。如果 YAML 有解析错误,dashboard 会记录到 ~/.hermes/logs/ 下的 errors.log。~/.hermes/plugins/<name>/dashboard/manifest.json(注意 dashboard/ 子目录)。curl http://127.0.0.1:9119/api/dashboard/plugins/rescan 强制重新发现。manifest.json、index.js 和任何 CSS 均无 404 加载成功。window.__HERMES_PLUGINS__ is undefined(表示 SDK 未初始化,通常是更早的 React 渲染崩溃导致)。manifest.json:name 相同的名称调用 window.__HERMES_PLUGINS__.register(...)。sidebar 插槽仅在激活主题设置了 layoutVariant: cockpit 时渲染。其他插槽始终渲染。如果你注册到某个插槽但没有命中,在 registerSlot 内添加 console.log 以确认插件 bundle 是否已运行。"api": "plugin_api.py" 且指向 dashboard/ 内的现有文件。hermes dashboard——插件 API 路由在启动时挂载一次,不会在重新扫描时挂载。plugin_api.py 是否导出了模块级的 router = APIRouter()。其他导出名称不会被识别。~/.hermes/logs/errors.log 中的 Failed to load plugin <name> API routes——导入错误会记录在那里。colorOverrides 的作用域限于激活主题,切换主题时会被清除——这是设计行为。如果你希望覆盖持久化,请将其写入主题的 YAML,而非实时切换器。customCSS 块每个主题上限为 32 KiB。可将大型样式表拆分到多个主题中,或改用通过 css 字段注入完整样式表的插件(无大小限制)。~/.hermes/plugins/ 的 git 仓库。基于 pip 的 dashboard 插件安装器目前尚未实现。