1use anyhow::Result;
9
10use crate::wiki::Wiki;
11
12#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
14pub struct InitResult {
15 pub ok: bool,
16 pub wiki_dir: String,
17 pub workspace_dir: String,
18 pub system_md: String,
19 pub created: Vec<String>,
20}
21
22const DEFAULT_SYSTEM_MD: &str = r#"# Wiki AI 行为准则
24
25你是一个专业的知识库助手,擅长将源文档转化为结构化、精确的 Wiki 页面。
26
27## 写作原则
28
291. **准确性**:只陈述原文中有明确依据的内容,不推测、不编造
302. **结构化**:使用 Markdown 标题层级组织内容
313. **可链接**:识别相关主题,用 `[[主题名]]` 格式添加内链
324. **简洁性**:每个 Wiki 页面聚焦单一主题,不堆砌无关信息
33
34## Wikilink 使用规范
35
36- 链接到相关主题时使用 `[[主题名]]`
37- 主题名使用简短、清晰的文件名风格
38- 如果不确定某个主题是否存在,宁可不链接也不要创建断链
39- 每个页面至少链接到 1 个相关主题
40
41## 格式要求
42
43- 每个页面以 `<!-- source: filename -->` 元数据注释开头
44- 包含 `<!-- generated: timestamp -->` 时间戳
45- 使用中文撰写
46"#;
47
48pub fn run(wiki: &Wiki) -> Result<InitResult> {
50 let config = wiki.config();
51 let wiki_dir = config.wiki_dir()?;
52 let workspace_dir = config.workspace_dir();
53 let system_md_path = config.system_md_path();
54
55 let mut created = Vec::new();
56
57 if !wiki_dir.exists() {
59 std::fs::create_dir_all(&wiki_dir)?;
60 created.push(wiki_dir.to_string_lossy().to_string());
61 }
62
63 if !workspace_dir.exists() {
64 std::fs::create_dir_all(&workspace_dir)?;
65 created.push(workspace_dir.to_string_lossy().to_string());
66 }
67
68 let _system_md_created = if !system_md_path.exists() {
70 std::fs::write(&system_md_path, DEFAULT_SYSTEM_MD)?;
71 created.push(system_md_path.to_string_lossy().to_string());
72 true
73 } else {
74 false
75 };
76
77 Ok(InitResult {
78 ok: true,
79 wiki_dir: wiki_dir.to_string_lossy().to_string(),
80 workspace_dir: workspace_dir.to_string_lossy().to_string(),
81 system_md: system_md_path.to_string_lossy().to_string(),
82 created,
83 })
84}