日期: 2026-07-26
状态: 已批准
kb-cli(Go 实现)已完成基础功能,与 Python 版 kb-search.py 对比测试显示:
- kb-cli 优势: 索引正常(768 文件),搜索快速(8ms),结果准确
- kb-search.py 问题: 索引为空(update-index 返回 0 条),搜索返回空结果
用户决策:优先使用 kb-cli,Python 脚本暂时保留作为备选。
--with-content:搜索时返回完整文件内容--with-links:搜索时显示关联文档链接| 方案 | 描述 | 优点 | 缺点 |
|---|---|---|---|
| A. 最小改动 | 在 SearchResult 结构体上加可选字段 | 改动小,向后兼容,逻辑清晰 | 无 |
| B. 分层增强 | 创建 Enhancer 接口,搜索管道模式 | 扩展性强 | 过度设计 |
| C. 独立命令 | 新增 kb search-detail 子命令 |
职责清晰 | 重复代码多 |
选择方案 A:最小改动
理由:
1. 改动最小,只改 search.go 和 output/formatter.go
2. 向后兼容,现有脚本不受影响
3. 逻辑简单,容易理解和维护
4. 不需要过度设计
文件: internal/search/engine.go
type SearchResult struct {
ID int64 `json:"id"`
Path string `json:"path"`
Title string `json:"title"`
Section string `json:"section"`
Score int `json:"score"`
// 新增可选字段
Content string `json:"content,omitempty"` // --with-content 时填充
Links []string `json:"links,omitempty"` // --with-links 时填充
}
文件: internal/search/engine.go
type SearchOptions struct {
Expanded []string
Symptom []string
TopN int
WithContent bool // 新增
WithLinks bool // 新增
}
func Search(store *index.Store, keywords []string, opts SearchOptions) ([]SearchResult, error) {
// 1. 执行 FTS5 搜索
ftsResults, err := store.FTSSearch(allKeywords, 100)
if err != nil {
return nil, err
}
// 2. 评分和排序
results := scoreAndSort(ftsResults, keywords, opts)
// 3. 限制返回数量
if opts.TopN > 0 && len(results) > opts.TopN {
results = results[:opts.TopN]
}
// 4. 增强结果(新增)
for i := range results {
// 获取内容
if opts.WithContent {
content, _, _, err := store.GetNodeContent(results[i].ID)
if err == nil {
results[i].Content = content
}
}
// 获取关联链接
if opts.WithLinks {
links, err := store.GetNodeLinks(results[i].ID)
if err == nil {
results[i].Links = links
}
}
}
return results, nil
}
已有方法: store.GetNodeContent(id)
func (s *Store) GetNodeContent(id int64) (string, []string, []string, error)
返回:(content, tags, entities, error)
新增方法: store.GetNodeLinks(nodeID)
func (s *Store) GetNodeLinks(nodeID int64) ([]string, error) {
query := `
SELECT n.path
FROM edges e
JOIN nodes n ON n.id = e.to_node
WHERE e.from_node = ? AND e.relation = 'wikilink'
`
rows, err := s.db.Query(query, nodeID)
if err != nil {
return nil, err
}
defer rows.Close()
var links []string
for rows.Next() {
var path string
if err := rows.Scan(&path); err != nil {
return nil, err
}
links = append(links, path)
}
return links, nil
}
查询逻辑:
- 查询 edges 表,relation='wikilink'
- 返回目标节点的 path(即关联文档路径)
文件: cmd/search.go
var (
withContent bool
withLinks bool
)
func init() {
// ... 现有 flag
searchCmd.Flags().BoolVar(&withContent, "with-content", false, "返回完整文件内容")
searchCmd.Flags().BoolVar(&withLinks, "with-links", false, "显示关联文档链接")
}
func runSearch(cmd *cobra.Command, args []string) error {
opts := search.SearchOptions{
Expanded: expanded,
Symptom: symptom,
TopN: topN,
WithContent: withContent,
WithLinks: withLinks,
}
results, err := search.Search(store, args, opts)
// ...
}
文件: internal/output/formatter.go
基础输出(无增强): 路径 标题 板块 得分 -------------------------------------------------- FAQ/充装类/087-xxx.md 扫码验证气瓶充装 FAQ 6
带内容(--with-content):
```
FAQ/充装类/087-xxx.md 扫码验证气瓶充装 FAQ 6
--- 内容 ---
...
```
带链接(--with-links):
```
FAQ/充装类/087-xxx.md 扫码验证气瓶充装 FAQ 6
--- 关联文档 ---
- 典型案例/充装异常案例.md
- 文档/电子秤平台/平台文档/023-充装统计与票据核对.md
```
两者都有(--with-content --with-links):
```
FAQ/充装类/087-xxx.md 扫码验证气瓶充装 FAQ 6
--- 内容 ---
...
--- 关联文档 ---
- 典型案例/充装异常案例.md
```
[
{
"id": 1577,
"path": "FAQ/充装类/087-xxx.md",
"title": "扫码验证气瓶充装",
"section": "FAQ",
"score": 6,
"content": "# 扫码验证气瓶充装\n\n## 问题描述\n...",
"links": [
"典型案例/充装异常案例.md",
"文档/电子秤平台/平台文档/023-充装统计与票据核对.md"
]
}
]
kb search "关键词" --with-content --top 3核心工具:
- 从 kb-search.py 改为 kb
命令示例:
```bash
kb search "充装规格" --top 5
kb search "充装规格" --with-content --top 3
kb search "充装规格" --with-links --top 3
kb search "充装" --expanded "重量 规格" --symptom "报错 无法启动" --with-content --top 3
```
保留内容:
- --expanded、--symptom 用法说明
- 搜索策略(术语映射、关键词选择)
- 最佳实践(决策树、案例)
移到降级方案:
- kb-search.py 完整用法移到"降级方案"章节
## 降级方案
仅当 kb-cli 不可用时,使用 kb-search.py:
export KB_VAULT=/home/aisim-p/aisim/note/001/笔记001
python3 ~/.hermes/skills/kb-knowledge/kb-search/scripts/kb-search.py search "关键词" --with-content --top 3
```
注意:kb-search.py 当前有索引问题,可能返回空结果。
```
SearchResult 结构体的 JSON 序列化(omitempty 行为)GetNodeLinks 方法# 测试基础搜索
kb search "充装" --top 5
# 测试带内容
kb search "充装" --with-content --top 3
# 测试带链接
kb search "充装" --with-links --top 3
# 测试两者都有
kb search "充装" --with-content --with-links --top 3
# 测试 JSON 输出
kb search "充装" --with-content --json --top 3
与 Python 版对比:
```bash
kb search "充装" --with-content --top 3
python3 kb-search.py search "充装" --with-content --top 3
```
SearchResult 结构体SearchOptions 结构体GetNodeLinks 方法Search 函数,增加内容获取和链接获取逻辑--with-content 和 --with-links flagSearchOptionsFormatTable 和 FormatJSON 方法| 风险 | 缓解措施 |
|---|---|
| 内容获取慢(大量文件) | 限制 --top N,默认 10 |
| 链接查询慢 | 使用索引,查询 edges 表 |
| JSON 输出过大 | omitempty 标签,不填充时不输出 |
| 向后兼容 | 新增字段为可选,不影响现有脚本 |
--with-content 和 --with-linksinternal/search/engine.go - 搜索逻辑internal/index/sqlite.go - 数据库操作internal/output/formatter.go - 输出格式化cmd/search.go - CLI 命令~/.hermes/skills/kb-knowledge/kb-search/SKILL.md - 技能文档~/.hermes/skills/kb-knowledge/kb-search/scripts/kb-search.pydocs/superpowers/specs/2026-07-26-kb-cli-design.md