Tentarc Logo文档

标签

标签配置

标签是可以应用于会话的附加标记。与状态(互斥——每个会话只能有一个)不同,标签是多选的(每个会话可以有多个)。它们支持通过嵌套 JSON 树进行层次化组织。

存储位置

  • 配置文件: ~/.tentarc/workspaces/{id}/labels/config.json

无默认值(常规标签)

与状态不同,常规标签一开始是空的。用户可以创建他们需要的任何标签。没有内置或必需的常规标签。

视觉表示

标签仅有颜色——在 UI 中渲染为彩色圆圈。不支持图标或表情符号。

层次化标签(嵌套树)

标签形成嵌套的 JSON 树。层次结构就是结构本身——父/子关系通过 children 数组表示。数组位置决定显示顺序(不需要 order 字段)。

示例:

{
  "version": 1,
  "labels": [
    {
      "id": "eng",
      "name": "Engineering",
      "color": "info",
      "children": [
        {
          "id": "frontend",
          "name": "Frontend",
          "children": [
            { "id": "react", "name": "React", "color": { "light": "#3B82F6", "dark": "#60A5FA" } }
          ]
        },
        { "id": "backend", "name": "Backend" }
      ]
    },
    { "id": "bug", "name": "Bug", "color": "destructive" }
  ]
}

这会在侧边栏中渲染为树形结构:

Engineering
  ├─ Frontend
  │    └─ React
  └─ Backend
Bug

规则:

  • ID 是简单的 slug(小写字母数字 + 连字符)
  • ID 必须在整个树中全局唯一
  • 最大嵌套深度:5 层
  • 数组位置 = 显示顺序(无 order 字段)
  • 按父标签筛选会包含所有子孙标签

config.json 结构

{
  "version": 1,
  "labels": [
    {
      "id": "bug",
      "name": "Bug",
      "color": "destructive"
    },
    {
      "id": "feature",
      "name": "Feature",
      "color": "accent",
      "children": [
        { "id": "ui", "name": "UI", "color": { "light": "#6366F1", "dark": "#818CF8" } },
        { "id": "api", "name": "API", "color": { "light": "#10B981", "dark": "#34D399" } }
      ]
    }
  ]
}

标签属性

属性类型描述
idstring唯一 slug,在整个树中全局唯一(例如 "bug""frontend")。小写字母数字 + 连字符。
namestring显示名称
colorEntityColor?可选颜色。系统颜色字符串(例如 "accent""info/80")或自定义对象({ "light": "#hex", "dark": "#hex" })。在 UI 中渲染为彩色圆圈。
valueType'string' | 'number' | 'date'?可选的值类型提示。告诉 UI 显示什么输入控件,以及代理应该写入什么格式。布尔(仅存在)标签可省略。
childrenLabelConfig[]?可选的嵌套子标签。数组位置 = 显示顺序。

颜色格式

与状态相同——参见状态文档了解支持的格式和常见错误的完整详情。

系统颜色: "accent""info""success""destructive""foreground"(可选 /opacity 0–100)

自定义颜色: { "light": "#EF4444", "dark": "#F87171" } — 支持 hex、OKLCH、RGB、HSL 格式

会话标签

会话将标签存储为字符串数组。布尔标签是纯 ID;带值标签使用 :: 分隔符:

{
  "labels": ["bug", "priority::3", "due::2026-01-30", "linear::https://linear.app/issue/ENG-456"]
}
  • 标签是累加的(会话可以有零个或多个标签)
  • 布尔标签:"bug" — 仅存在,无值
  • 带值标签:"priority::3" — ID + 值用 :: 分隔
  • :: 分割仅在第一次出现时进行(值可以包含 ::
  • 无效的标签 ID 在读取时会被静默过滤掉
  • 删除标签会自动从所有会话中移除它(子标签也会被移除)
  • 层次化筛选:点击父标签会显示标记了它或任何子孙的会话

值类型

值在解析时从原始字符串推断:

类型格式示例
number有限数字"priority::3""effort::0.5"
dateISO 日期 (YYYY-MM-DD)"due::2026-01-30"
string其他任何内容"link::https://example.com"

推断顺序: ISO 日期检查 → 数字检查 → 字符串后备。

配置中的可选 valueType 仅是提示——解析器始终从原始值推断,不管配置如何。

添加标签

编辑工作区的 labels/config.json

{
  "version": 1,
  "labels": [
    {
      "id": "bug",
      "name": "Bug",
      "color": "destructive"
    },
    {
      "id": "priority",
      "name": "Priority",
      "color": "accent",
      "valueType": "number"
    },
    {
      "id": "due",
      "name": "Due Date",
      "color": "info",
      "valueType": "date"
    },
    {
      "id": "project",
      "name": "Project",
      "color": "foreground/60",
      "children": [
        { "id": "alpha", "name": "Alpha", "color": "info" },
        { "id": "beta", "name": "Beta", "color": "success" }
      ]
    }
  ]
}

颜色约定

创建或修改标签时,除非用户明确要求,否则请遵循以下约定:

  1. 始终添加颜色。 每个标签都应该有 color 用于视觉识别(渲染为彩色圆圈)。

  2. 在类别内使用互补色。 同级标签(同一父级的子标签)应使用相同色系或色调范围的颜色,创建视觉上协调的组。例如,"Backend" 组可能为其子标签(API、Database)使用绿色/青色,而 "Frontend" 使用靛蓝/蓝色(React、CSS)。

  3. 对语义含义使用语义颜色:

    • Bug/错误 → "destructive" 或红色调
    • 功能/增强 → "accent" 或蓝色/靛蓝色调
    • 成功/完成 → "success" 或绿色调
    • 信息/元数据 → "info" 或天蓝/青色调
    • 中性/杂项 → "foreground/60" 或灰色调

颜色格式提醒: 对子标签使用自定义 { "light": "#hex", "dark": "#hex" } 对象以获得精确的颜色控制。为顶级父类别保留系统颜色("accent""info""destructive" 等)。

验证

重要:创建或编辑标签后务必验证:

config_validate({ target: "labels" })

验证内容:

  • 有效的 JSON 和递归 schema 结构
  • 整个树中全局唯一的 ID
  • 有效的 slug 格式(小写字母数字加连字符)
  • 最大嵌套深度(5 层)

自动标签规则

自动标签规则自动扫描用户消息并应用带有提取值的标签。在任何标签上配置正则表达式模式以触发自动标记。

配置

config.json 中的任何标签上添加 autoRules

{
  "id": "linear-issue",
  "name": "Linear Issue",
  "color": "purple",
  "valueType": "string",
  "autoRules": [
    {
      "pattern": "linear\\.app/[\\w-]+/issue/([A-Z]+-\\d+)",
      "valueTemplate": "$1",
      "description": "Matches Linear issue URLs"
    },
    {
      "pattern": "\\b([A-Z]{2,5}-\\d+)\\b",
      "valueTemplate": "$1",
      "description": "Matches bare issue keys like CRA-123"
    }
  ]
}

AutoLabelRule 属性

属性类型描述
patternstring必需。 带捕获组的正则表达式。使用 flags(默认:gi)。
flagsstring正则表达式标志(默认:gi — 全局、不区分大小写)。g 始终强制执行。
valueTemplatestring使用 $1$2 进行捕获组替换的模板。如果省略,使用第一个捕获组。
descriptionstring人类可读的此规则匹配内容的描述。

正则表达式模式

规则使用带捕获组的 JavaScript 正则表达式:

{
  "pattern": "github\\.com/([\\w-]+/[\\w-]+)/pull/(\\d+)",
  "valueTemplate": "$1#$2",
  "description": "Matches GitHub PR URLs"
}
  • 全局匹配g 标志始终强制执行,因此会找到消息中的所有出现
  • 捕获组$1$2 等在 valueTemplate 中被匹配的组替换
  • 多个匹配:"CRA-1 and CRA-2" 在同一标签上产生两个标签条目
  • 代码块剥离:围栏代码块和内联代码中的内容被忽略

值标准化

提取的值根据标签的 valueType 进行标准化:

valueType原始捕获标准化后
stringCRA-123CRA-123(直接传递)
number$45,00045000(去除符号 + 逗号)
number1.5M1500000(展开后缀)
number50k50000(展开后缀)
date2026-01-302026-01-30(直接传递)

评估行为

  • 时机:当用户消息发送时评估规则(新消息和排队消息)
  • 仅用户消息:不扫描助手输出和工具结果
  • 代码剥离:评估前剥离围栏代码块和内联代码
  • 去重:相同的标签+值不会被添加到会话两次
  • 匹配限制:每条消息最多 10 个匹配(防止粘贴数据导致标签爆炸)
  • 持久性:自动应用的标签存储在会话上
  • 多个规则:标签上的所有规则都会被评估;收集所有匹配
  • 验证:在配置保存时验证模式(无效的正则表达式和 ReDoS 模式被拒绝)
  • 错误处理:无效的正则表达式模式在运行时被跳过(记录为警告)

完整示例

一个自动标记 Linear 问题、截止日期、联系人和预算的工作区:

{
  "version": 1,
  "labels": [
    {
      "id": "linear-issue",
      "name": "Linear Issue",
      "color": "purple",
      "valueType": "string",
      "autoRules": [
        { "pattern": "linear\\.app/[\\w-]+/issue/([A-Z]+-\\d+)", "valueTemplate": "$1", "description": "Linear URLs" },
        { "pattern": "\\b([A-Z]{2,5}-\\d+)\\b", "valueTemplate": "$1", "description": "Bare issue keys" }
      ]
    },
    {
      "id": "deadline",
      "name": "Deadline",
      "color": "orange",
      "valueType": "date",
      "autoRules": [
        { "pattern": "(\\d{4}-\\d{2}-\\d{2}(?:T\\d{2}:\\d{2})?)", "valueTemplate": "$1", "description": "ISO dates" }
      ]
    },
    {
      "id": "contact",
      "name": "Contact",
      "color": "blue",
      "valueType": "string",
      "autoRules": [
        { "pattern": "([\\w.+-]+@[\\w.-]+\\.[a-zA-Z]{2,})", "valueTemplate": "$1", "description": "Email addresses" }
      ]
    },
    {
      "id": "budget",
      "name": "Budget",
      "color": "green",
      "valueType": "number",
      "autoRules": [
        { "pattern": "\\$([\\d,.]+[kKmMbB]?)", "valueTemplate": "$1", "description": "Dollar amounts" }
      ]
    }
  ]
}

侧边栏行为

标签在左侧边栏中显示为多级可展开部分:

All Chats    (平铺,总数)
Flagged      (平铺,标记数)
States       (可展开 → 状态子项)
Labels       (可展开)
  ├─ Views       (可展开 → 视图子项)
  ├─ Engineering (标签)
  └─ Bug         (标签)
────────────
Sources      (可展开 → API/MCP/Local)
Skills       (平铺)
────────────
Settings     (平铺)

点击标签会筛选会话列表。点击父标签会包含标记了任何子孙的会话。

设计决策

  • 嵌套 JSON 树:层次结构就是结构本身——无需学习约定
  • 数组位置 = 顺序:无需 order 字段,数组位置决定显示顺序
  • 全局唯一 ID:简单的 slug,在整个树中唯一
  • 仅颜色的视觉效果:标签使用彩色圆圈——无图标,保持 UI 简洁一致
  • 无类别:标签不影响收件箱/归档筛选(那是状态的用途)
  • 无默认值:工作区从零个标签开始
  • 无固定标签:所有标签完全由用户控制(可删除、可重命名)
  • 多选:会话存储 labels: string[],而非单个值
  • 删除级联:删除标签会从会话中移除它和所有子孙
  • 最大深度 5:防止过深的层次结构
  • 层次化筛选:父标签点击包含所有子孙会话
  • 通过 :: 分隔符的值:简单、扁平的字符串存储——无需更改会话格式的 schema
  • 解析时的类型推断:解析器始终推断(日期 → 数字 → 字符串),valueType 只是 UI 提示
  • 仅日期格式:ISO YYYY-MM-DD — 无时间组件,避免时区复杂性