| | |
| | | import ( |
| | | "fmt" |
| | | "os" |
| | | "path/filepath" |
| | | "strings" |
| | | |
| | | "github.com/aisim/kb-cli/internal/index" |
| | | "github.com/spf13/cobra" |
| | |
| | | var indexCmd = &cobra.Command{ |
| | | Use: "index", |
| | | Short: "索引管理", |
| | | Long: `管理知识库索引`, |
| | | } |
| | | |
| | | var indexBuildCmd = &cobra.Command{ |
| | | Use: "build", |
| | | Short: "构建/重建索引", |
| | | Long: `构建或重建知识库索引`, |
| | | Short: "构建或重建知识库索引", |
| | | RunE: runIndexBuild, |
| | | } |
| | | |
| | | var indexStatusCmd = &cobra.Command{ |
| | | Use: "status", |
| | | Short: "查看索引状态", |
| | | Long: `查看索引状态信息`, |
| | | Short: "查看索引状态信息", |
| | | RunE: runIndexStatus, |
| | | } |
| | | |
| | | var indexGcCmd = &cobra.Command{ |
| | | Use: "gc", |
| | | Short: "清理孤立节点和边", |
| | | RunE: runIndexGc, |
| | | } |
| | | |
| | | func init() { |
| | | rootCmd.AddCommand(indexCmd) |
| | | indexCmd.AddCommand(indexBuildCmd) |
| | | indexCmd.AddCommand(indexStatusCmd) |
| | | indexCmd.AddCommand(indexGcCmd) |
| | | } |
| | | |
| | | func runIndexBuild(cmd *cobra.Command, args []string) error { |
| | |
| | | |
| | | return nil |
| | | } |
| | | |
| | | func runIndexGc(cmd *cobra.Command, args []string) error { |
| | | // 展开 ~ 为实际路径 |
| | | expandedVaultPath := vaultPath |
| | | if strings.HasPrefix(vaultPath, "~/") { |
| | | home, err := os.UserHomeDir() |
| | | if err != nil { |
| | | return fmt.Errorf("获取用户目录失败: %w", err) |
| | | } |
| | | expandedVaultPath = filepath.Join(home, vaultPath[2:]) |
| | | } |
| | | |
| | | // 打开索引 |
| | | store, err := index.Open(dbPath) |
| | | if err != nil { |
| | | return fmt.Errorf("打开索引失败: %w", err) |
| | | } |
| | | defer store.Close() |
| | | |
| | | fmt.Fprintln(os.Stderr, "正在清理孤立节点和边...") |
| | | |
| | | // 获取所有节点路径 |
| | | nodes, err := store.GetAllNodes() |
| | | if err != nil { |
| | | return fmt.Errorf("获取节点失败: %w", err) |
| | | } |
| | | |
| | | // 检查文件是否存在 |
| | | var orphanPaths []string |
| | | for _, node := range nodes { |
| | | fullPath := filepath.Join(expandedVaultPath, node.Path) |
| | | if _, err := os.Stat(fullPath); os.IsNotExist(err) { |
| | | orphanPaths = append(orphanPaths, node.Path) |
| | | } |
| | | } |
| | | |
| | | if len(orphanPaths) == 0 { |
| | | fmt.Fprintln(os.Stderr, "没有发现孤立节点") |
| | | return nil |
| | | } |
| | | |
| | | fmt.Fprintf(os.Stderr, "发现 %d 个孤立节点,正在清理...\n", len(orphanPaths)) |
| | | |
| | | // 删除孤立节点 |
| | | deletedCount, err := store.DeleteNodesByPaths(orphanPaths) |
| | | if err != nil { |
| | | return fmt.Errorf("删除节点失败: %w", err) |
| | | } |
| | | |
| | | fmt.Fprintf(os.Stderr, "已清理 %d 个孤立节点\n", deletedCount) |
| | | return nil |
| | | } |