ai_xiaopei
9 days ago f83abc3b530f0dbde23332b0b67b9467a69b952b
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
package cmd
 
import (
    "fmt"
    "os"
 
    "github.com/aisim/kb-cli/internal/draft"
    "github.com/aisim/kb-cli/internal/index"
    "github.com/spf13/cobra"
)
 
var draftCmd = &cobra.Command{
    Use:   "draft",
    Short: "草稿管理",
    Long:  `kb-cli draft create # 创建草稿(AI 生成 tags + 合并指示)`,
}
 
var draftCreateCmd = &cobra.Command{
    Use:   "create",
    Short: "创建草稿",
    Long: `kb-cli draft create --type <类型> --title <标题> --content-file <内容文件> [--source <来源>] [--force]
 
创建草稿,自动提取 tags 并生成合并指示。
 
类型: 售后/产品/运营/行业/TAPD
示例:
  kb-cli draft create --type 售后 --title "充不进气问题" --content-file /tmp/draft.md
  kb-cli draft create --type TAPD --title "档案下载失败" --content-file /tmp/bug.md --source "TAPD#12345"`,
    RunE: runDraftCreate,
}
 
var tagsCmd = &cobra.Command{
    Use:   "tags",
    Short: "标签管理",
    Long:  `kb-cli tags rebuild # 批量重建现有文档的 tags`,
}
 
var tagsRebuildCmd = &cobra.Command{
    Use:   "rebuild",
    Short: "批量重建 tags",
    Long: `kb-cli tags rebuild [--vault <路径>] [--limit <数量>] [--dry-run]
 
批量重建现有文档的 tags,使用 LLM 重新提取。
 
示例:
  kb-cli tags rebuild --limit 10           # 重建前 10 个文档的 tags
  kb-cli tags rebuild --dry-run            # 仅预览,不实际更新`,
    RunE: runTagsRebuild,
}
 
var (
    draftType       string
    draftTitle      string
    draftContentFile string
    draftSource     string
    draftForce      bool
    tagsLimit       int
    tagsDryRun      bool
)
 
func init() {
    // draft create 命令
    draftCreateCmd.Flags().StringVar(&draftType, "type", "", "草稿类型(售后/产品/运营/行业/TAPD)")
    draftCreateCmd.Flags().StringVar(&draftTitle, "title", "", "草稿标题")
    draftCreateCmd.Flags().StringVar(&draftContentFile, "content-file", "", "草稿内容文件路径")
    draftCreateCmd.Flags().StringVar(&draftSource, "source", "", "来源标识")
    draftCreateCmd.Flags().BoolVar(&draftForce, "force", false, "强制创建(跳过重复检查)")
    draftCreateCmd.MarkFlagRequired("type")
    draftCreateCmd.MarkFlagRequired("title")
    draftCreateCmd.MarkFlagRequired("content-file")
 
    draftCmd.AddCommand(draftCreateCmd)
 
    // tags rebuild 命令
    tagsRebuildCmd.Flags().IntVar(&tagsLimit, "limit", 0, "限制处理文档数量(0=全部)")
    tagsRebuildCmd.Flags().BoolVar(&tagsDryRun, "dry-run", false, "仅预览,不实际更新")
 
    tagsCmd.AddCommand(tagsRebuildCmd)
 
    rootCmd.AddCommand(draftCmd)
    rootCmd.AddCommand(tagsCmd)
}
 
func runDraftCreate(cmd *cobra.Command, args []string) error {
    // 读取内容文件
    content, err := os.ReadFile(draftContentFile)
    if err != nil {
        return fmt.Errorf("读取内容文件失败: %w", err)
    }
 
    if len(content) == 0 {
        return fmt.Errorf("内容文件为空")
    }
 
    // 打开索引
    store, err := index.Open(dbPath)
    if err != nil {
        return fmt.Errorf("打开索引失败: %w", err)
    }
    defer store.Close()
 
    // 创建草稿录入器
    intake := draft.NewIntake(vaultPath, store)
 
    // 创建草稿
    if err := intake.CreateDraft(draftType, draftTitle, string(content), draftSource, draftForce); err != nil {
        return fmt.Errorf("创建草稿失败: %w", err)
    }
 
    return nil
}
 
func runTagsRebuild(cmd *cobra.Command, args []string) error {
    // 打开索引
    store, err := index.Open(dbPath)
    if err != nil {
        return fmt.Errorf("打开索引失败: %w", err)
    }
    defer store.Close()
 
    // 创建草稿录入器
    intake := draft.NewIntake(vaultPath, store)
 
    // 重建 tags
    if err := intake.RebuildTags(tagsLimit, tagsDryRun); err != nil {
        return fmt.Errorf("重建 tags 失败: %w", err)
    }
 
    return nil
}