From ac966af3d126d59081d119e05ba02f946257f669 Mon Sep 17 00:00:00 2001
From: ai_xiaopei <xiaopei@aisim.cn>
Date: Sun, 26 Jul 2026 23:22:36 +0800
Subject: [PATCH] fix: 移除所有help中的等号格式

---
 cmd/index.go |  249 +++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 249 insertions(+), 0 deletions(-)

diff --git a/cmd/index.go b/cmd/index.go
new file mode 100644
index 0000000..63ecbe2
--- /dev/null
+++ b/cmd/index.go
@@ -0,0 +1,249 @@
+package cmd
+
+import (
+	"fmt"
+	"os"
+	"os/exec"
+	"path/filepath"
+	"strings"
+	"time"
+
+	"github.com/aisim/kb-cli/internal/index"
+	"github.com/spf13/cobra"
+)
+
+var indexCmd = &cobra.Command{
+	Use:   "index",
+	Short: "索引管理",
+}
+
+var indexBuildCmd = &cobra.Command{
+	Use:   "build",
+	Short: "构建或重建知识库索引",
+	Long:  `kb-cli index build [--vault <路径>] [--db <路径>] # 构建或重建知识库索引`,
+	RunE:  runIndexBuild,
+}
+
+var indexStatusCmd = &cobra.Command{
+	Use:   "status",
+	Short: "查看索引状态信息",
+	Long:  `kb-cli index status [--vault <路径>] [--db <路径>] # 查看索引状态(节点数、边数、commit、构建时间)`,
+	RunE:  runIndexStatus,
+}
+
+var indexGcCmd = &cobra.Command{
+	Use:   "gc",
+	Short: "清理孤立节点和边",
+	Long:  `kb-cli index gc [--vault <路径>] [--db <路径>] # 清理索引中文件已删除的孤立节点和边`,
+	RunE:  runIndexGc,
+}
+
+var gitCmd = &cobra.Command{
+	Use:   "git",
+	Short: "Git 同步操作",
+}
+
+var gitSyncCmd = &cobra.Command{
+	Use:   "sync",
+	Short: "同步知识库到 Git 仓库",
+	Long:  `kb-cli git sync [--vault <路径>] # 执行 git add、commit、push 同步知识库`,
+	RunE:  runGitSync,
+}
+
+func init() {
+	rootCmd.AddCommand(indexCmd)
+	indexCmd.AddCommand(indexBuildCmd)
+	indexCmd.AddCommand(indexStatusCmd)
+	indexCmd.AddCommand(indexGcCmd)
+	
+	rootCmd.AddCommand(gitCmd)
+	gitCmd.AddCommand(gitSyncCmd)
+}
+
+func runIndexBuild(cmd *cobra.Command, args []string) error {
+	// 打开索引
+	store, err := index.Open(dbPath)
+	if err != nil {
+		return fmt.Errorf("打开索引失败: %w", err)
+	}
+	defer store.Close()
+
+	// 获取当前 commit
+	commit, err := index.GetGitCommit(vaultPath)
+	if err != nil {
+		fmt.Fprintln(os.Stderr, "警告: 无法获取 git commit:", err)
+		commit = ""
+	}
+
+	fmt.Fprintln(os.Stderr, "正在重建索引...")
+	if err := rebuildIndex(store, commit); err != nil {
+		return fmt.Errorf("重建索引失败: %w", err)
+	}
+
+	fmt.Fprintln(os.Stderr, "索引重建完成")
+	return nil
+}
+
+func runIndexStatus(cmd *cobra.Command, args []string) error {
+	// 打开索引
+	store, err := index.Open(dbPath)
+	if err != nil {
+		return fmt.Errorf("打开索引失败: %w", err)
+	}
+	defer store.Close()
+
+	// 获取元信息
+	gitCommit, err := store.GetMeta("git_commit")
+	if err != nil {
+		return fmt.Errorf("获取元信息失败: %w", err)
+	}
+	builtAt, _ := store.GetMeta("built_at")
+
+	// 获取节点数
+	nodeCount, err := store.NodeCount()
+	if err != nil {
+		return fmt.Errorf("获取节点数失败: %w", err)
+	}
+
+	// 获取边数
+	edgeCount, err := store.EdgeCount()
+	if err != nil {
+		return fmt.Errorf("获取边数失败: %w", err)
+	}
+
+	// 获取当前 commit
+	currentCommit, err := index.GetGitCommit(vaultPath)
+	if err != nil {
+		currentCommit = ""
+	}
+
+	// 输出状态
+	fmt.Printf("索引状态:\n")
+	fmt.Printf("  知识库路径: %s\n", vaultPath)
+	fmt.Printf("  索引文件: %s\n", dbPath)
+	fmt.Printf("  节点数: %d\n", nodeCount)
+	fmt.Printf("  边数: %d\n", edgeCount)
+	fmt.Printf("  索引 commit: %s\n", gitCommit)
+	fmt.Printf("  当前 commit: %s\n", currentCommit)
+	fmt.Printf("  构建时间: %s\n", builtAt)
+
+	// 检查是否需要更新
+	needsRebuild, _, err := index.NeedsRebuild(store, vaultPath)
+	if err != nil {
+		return fmt.Errorf("检查索引状态失败: %w", err)
+	}
+
+	if needsRebuild {
+		fmt.Printf("  状态: 需要更新\n")
+	} else {
+		fmt.Printf("  状态: 最新\n")
+	}
+
+	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
+}
+
+func runGitSync(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:])
+	}
+
+	fmt.Fprintln(os.Stderr, "正在同步知识库到 Git 仓库...")
+
+	// 检查是否是 git 仓库
+	gitDir := filepath.Join(expandedVaultPath, ".git")
+	if _, err := os.Stat(gitDir); os.IsNotExist(err) {
+		return fmt.Errorf("知识库目录不是 Git 仓库: %s", expandedVaultPath)
+	}
+
+	// 执行 git add -A
+	addCmd := exec.Command("git", "-C", expandedVaultPath, "add", "-A")
+	if output, err := addCmd.CombinedOutput(); err != nil {
+		return fmt.Errorf("git add 失败: %w\n%s", err, output)
+	}
+
+	// 检查是否有变更
+	statusCmd := exec.Command("git", "-C", expandedVaultPath, "status", "--porcelain")
+	statusOutput, err := statusCmd.Output()
+	if err != nil {
+		return fmt.Errorf("git status 失败: %w", err)
+	}
+
+	if len(statusOutput) == 0 {
+		fmt.Fprintln(os.Stderr, "没有变更需要提交")
+		return nil
+	}
+
+	// 生成 commit 信息
+	commitMsg := fmt.Sprintf("kb-cli: 自动同步 %s", time.Now().Format("2006-01-02 15:04:05"))
+	commitCmd := exec.Command("git", "-C", expandedVaultPath, "commit", "-m", commitMsg)
+	if output, err := commitCmd.CombinedOutput(); err != nil {
+		return fmt.Errorf("git commit 失败: %w\n%s", err, output)
+	}
+
+	// 执行 git push
+	pushCmd := exec.Command("git", "-C", expandedVaultPath, "push")
+	if output, err := pushCmd.CombinedOutput(); err != nil {
+		return fmt.Errorf("git push 失败: %w\n%s", err, output)
+	}
+
+	fmt.Fprintln(os.Stderr, "Git 同步完成")
+	return nil
+}

--
Gitblit v1.9.1