feat(skills): 新增 Skill 调用统计(账本 + 页面总览/详情)

后端:
- 新表 skill_usage(无外键,任务/会话删除后统计保留),一次 Skill()
  调用记一行,只记维度不记 args 正文;含 found 标记未命中调用
- 用 RunInfo 经 ctx 把 task/exploration/intent/session 传到工具装配层,
  在 Skill meta-tool 外包一层做埋点(可记 args 长度与不存在的 skill)
- fsListSkills 返回附带调用次数/覆盖任务/最近调用;新增
  GET /api/skills/missing 与 GET /api/skills/{name}/usage

前端(/system/skills):
- 树节点显示调用次数 badge;目录优先排序 + 子项缩进错开一级
- 空态改为技能库总览(指标卡 + 调用排行 + 最近/未使用)
- 选中 skill 的详情面板改为响应式左右分栏(配置在左、统计在右,
  窄屏回落上下),含最近调用明细与未命中缺口清单

Claude-Session: https://claude.ai/code/session_01BNN7npEJs4X6LfTtgniMd8
This commit is contained in:
Autumn-27 committed 2026-08-20 12:30:01 -04:00
1 parent 43f40dd74f
commit 834e94535a
16 files changed
+831 -52

No files matched your search

+20
View File
@@ -501,6 +501,26 @@ CREATE TABLE IF NOT EXISTS agent_skill_visibility (
);
CREATE INDEX IF NOT EXISTS idx_askv_skill ON agent_skill_visibility(skill_name);
-- Skill 调用账本(见 db/skill_usage.go)。一次 Skill() 调用一行,只记维度不记正文。
-- 刻意不设外键:任务/会话删除后统计仍要保留(与 llm_usage 同理),skill 本身也只是
-- 文件系统上的目录名,没有对应的表。
CREATE TABLE IF NOT EXISTS skill_usage (
id BIGSERIAL PRIMARY KEY,
ts TIMESTAMPTZ NOT NULL DEFAULT now(),
skill TEXT NOT NULL,
agent_key TEXT,
task_id BIGINT,
exploration_id BIGINT,
intent_id BIGINT,
session_id TEXT,
args_len INTEGER NOT NULL DEFAULT 0,
-- false = 模型点名了一个不存在的 skill(未命中)。这类行同样保留:它反映"想用但没有"
-- 的缺口,是补 skill 的依据。
found BOOLEAN NOT NULL DEFAULT true
);
CREATE INDEX IF NOT EXISTS idx_skill_usage_skill ON skill_usage(skill, ts DESC);
CREATE INDEX IF NOT EXISTS idx_skill_usage_task ON skill_usage(task_id);
-- =====================================================================
-- H. 内置工具目录
-- =====================================================================