🎯 OpenCode插件系列: opencode-triage


类型: Skill Router Plugin(确定性技能路由器)


1. 这是什么插件?

opencode-triage 是一个为 OpenCode 添加确定性 Skill 路由能力的插件。核心概念:

  • 🎯 不依赖 LLM 解析 — 使用纯关键词匹配算法,零 PowerShell,零 LLM 解析开销
  • 💾 节省约 90% tokens — 将所有 skills 从 system prompt 中隐藏,按需加载
  • 🔍 智能路由 — 通过关键词评分自动发现并匹配最合适的 skill
  • ⚡ 即时响应 — 缓存机制 + 文件监听,5秒内自动刷新

想象一下:就像一个智能分诊台,根据你的描述自动把你派到正确的专家科室,而不是让每个医生都听你从头讲一遍病史。

Triage 路由 vs 传统全量注入:

方面 传统方式(全量注入) Triage 路由
**Token 消耗** 所有 skills 全部塞进 system prompt 仅加载匹配的 skill
**Context 污染** AI 看到所有 skills,容易混淆 AI 只看到相关的 skill
**匹配精度** AI 自己猜测用哪个 skill 关键词评分 + 阈值判定
**扩展性** Skills 越多越慢越贵 Skills 多少不影响性能
**延迟** 每次 prompt 都携带全部内容 按需加载,毫秒级

2. 用来做什么?

使用它来:

  • ✅ 管理 50+ 个 skills 而 token 消耗几乎为零
  • ✅ 自动匹配最佳 skill — 说"备份数据库"就路由到 backup skill
  • ✅ 独立控制全局/项目级 skills — 两套作用域互不干扰
  • ✅ 远程搜索缺失的 skills — 自动从 skills.sh 和 superpowers 推荐
  • ✅ Toast 通知 — 路由结果、完成状态实时反馈
  • ✅ 文件监听 — 新安装的 skill 自动隐藏(ON 模式下)

典型工作流:

你安装了 30 个 skills(测试、部署、数据库、文档、重构...)

没有 Triage:
┌─────────────────────────────────────┐
│ System Prompt: 50,000 tokens        │  ← 所有 skills 全在里面
│ - test-skill (2000 tokens)          │
│ - deploy-skill (3000 tokens)        │
│ - db-skill (2500 tokens)            │
│ ... (27 more)                       │
│                                     │
│ 你: "帮我备份一下数据库"              │
│ AI: [困惑地看着 30 个 skills]       │
└─────────────────────────────────────┘

有 Triage(ON 模式):
┌─────────────────────────────────────┐
│ System Prompt: 5,000 tokens         │  ← 干净清爽
│                                     │
│ 你: "帮我备份一下数据库"              │
│ Triage: 🔍 匹配中...                │
│         ✅ 路由到: db-backup        │  ← 仅加载这 1 个
│         Loaded: db-backup ✓         │
└─────────────────────────────────────┘

3. 如何使用?

安装

在 ~/.config/opencode/opencode.json 或 .opencode/opencode.json 中:

{
  "$schema": "https://opencode.ai/config.json",
  "plugin": ["opencode-triage"]
}

安装后运行 npm install(或 npm install -g),postinstall 脚本会自动创建 /triage 命令文件。

核心命令

① 启用 Triage(隐藏 skills)

/triage on              # 隐藏全局 + 项目 skills(推荐)
/triage on --local      # 仅隐藏项目级 skills
/triage on --global     # 仅隐藏全局 skills
/triage on --both       # 同 /triage on

② 禁用 Triage(暴露 skills)

/triage off             # 暴露全局 + 项目 skills
/triage off --local     # 仅暴露项目级 skills
/triage off --global    # 仅暴露全局 skills

③ 查看状态

/triage status          # 显示插件状态 + 所有 skills 列表

④ 去重

/triage dedupe          # 移除项目级重复 skills(保留全局版本)

⑤ 对比查看

/triage compare         # 并排对比 project vs global skills

⑥ 模式切换

/triage mode auto       # 自动模式:启动时自动隐藏(写入 autoHide: true)
/triage mode manual     # 手动模式:需要手动 /triage on/off

AI 侧使用(triage 工具)

插件注册了 triage() 工具,AI 可以在对话中直接调用:

用户: 我需要备份 PostgreSQL 数据库

AI: 让我查找合适的技能...
    triage({ query: "backup postgresql database" })

    → SKILL ROUTED: pg-backup
    → Matched by: name:backup, desc:postgresql, desc:database

    → [加载 pg-backup 的完整内容]

当多个 skills 匹配时,返回候选列表供选择:

→ Multiple matches for "deploy". Pick one:

  1. deploy-vercel    -- Deploy to Vercel edge network
  2. deploy-docker    -- Containerize and deploy with Docker
  3. deploy-aws       -- Deploy to AWS Lambda or ECS

  Example: triage({ query: "deploy-vercel" })

通知系统

插件还注册了 notify() 工具,AI 可以调用它显示 Toast 通知:

notify({ message: "Build complete", variant: "success" })   // 绿色
notify({ message: "Fetching data...", variant: "info" })     // 蓝色
notify({ message: "Operation failed", variant: "error" })    // 红色
notify({ message: "Disk almost full", variant: "warning" })  // 黄色

4. 扫描目录结构

Triage 会扫描 6 个目录(3 个项目级 + 3 个全局级):

目录 作用域 说明
`.agent/skills/` 项目 OpenCode agent skills
`.agents/skills/` 项目 复数形式兼容
`.claude/skills/` 项目 Claude Code 兼容
`.opencode/skills/` 项目 OpenCode 原生
`~/.agents/skills/` 全局 用户级 agent skills
`~/.claude/skills/` 全局 Claude Code 全局
`~/.config/opencode/skills/` 全局 OpenCode 全局

优先级: 项目级 > 全局级(同名 skill 以项目级为准)


5. 评分引擎详解

匹配算法

查询: "backup my database"

分词: ["backup", "database"]  (过滤了 "my",长度 < 3)

对每个 skill 计算:
┌─────────────────────────────────────────────────────┐
│ Skill: pg-backup                                    │
│ Name: "pg-backup"                                   │
│ Desc: "PostgreSQL backup and restore utilities"     │
│                                                     │
│ 名称匹配 (权重 ×3):                                  │
│   "backup" → 子串匹配 → 10 × 3 = 30                 │
│                                                     │
│ 描述匹配 (权重 ×1):                                  │
│   "backup" → 完整词匹配 → 15 × 1 = 15               │
│   "database" → 子串匹配 → 10 × 1 = 10               │
│                                                     │
│ 总分: 55                                            │
│ matchedBy: "name:backup, desc:backup, desc:database"│
└─────────────────────────────────────────────────────┘

评分规则

匹配类型 基础分 名称加权 (×3) 描述加权 (×1)
完整词边界匹配 (`\bword\b`) 15 pts **45** 15
子串匹配 (`includes`) 10 pts **30** 10
无匹配 0 0 0

自动路由阈值

  • THRESHOLD = 30 — 第一名与第二名的分数差 ≥ 30 时自动路由
  • 差值 < 30 → 返回候选列表让 AI/用户选择
  • 只有 1 个匹配 → 直接路由

一个名称完全匹配就能达到 45 分,超过阈值。所以精确命名非常重要!


6. Skill 文件格式

标准 SKILL.md 结构

---
name: my-skill-name           # 技能名称(可选,默认用目录名)
description: >                # 支持 folded 语法(多行折叠)
  这是一段较长的描述文字,
  可以写很多行,会被合并成一行
---

# 这里是 skill 的实际内容
# 会被加载到 AI context 中
# 支持完整的 Markdown 格式

## 使用说明
...

Frontmatter 解析支持

  • 单行:description: Some text here
  • Folded 块:description: > + 缩进行
  • 自动去除 UTF-8 BOM(Windows 兼容)

文件状态

文件 状态 是否出现在 system prompt
`SKILL.md` **Exposed**(暴露)
`SKILL.md.disabled` **Hidden**(隐藏)

Triage 的魔法: 即使 skill 被 hidden(.disabled),路由器仍然可以发现和加载它!只是不会污染 system prompt。


7. 何时使用?

在以下情况使用:

  • 安装了 10+ 个 skills,token 消耗成为问题
  • Skills 有明确的功能边界(名称和描述清晰)
  • 需要精准路由而不是让 AI 猜测
  • 多个项目间切换,每个项目有不同的 skills
  • 想要干净的 system prompt
  • 使用免费/低价模型,对 token 敏感

不要在以下情况使用:

  • 只有 1-3 个 skills(不值得折腾)
  • Skills 命名混乱、描述不清(匹配率低)
  • 需要 skills 始终可见(如核心工具链)
  • 使用需要全量上下文的特殊工作流

8. 高级配置

环境变量

变量 说明 示例
`OPENCODE_TRIAGE_EXCLUDED` 排除指定 skills(逗号分隔) `"triage,debug,test"`

配置持久化

/triage on 和 /triage off 会自动写入配置文件:

// ~/.config/opencode/opencode.jsonc
{
  "plugin": [
    ["opencode-triage", { "autoHide": true }]   // ON 状态
    // "opencode-triage"                        // OFF 状态(无选项)
  ]
}

启动流程:

  1. 插件加载 → 读取 autoHide 配置