1use std::collections::{HashMap, HashSet};
5use std::env::var_os;
6use std::path::PathBuf;
7
8use serde::{Deserialize, Serialize};
9
10use super::types::MemoryCategory;
11
12fn home_dir() -> Option<PathBuf> {
13 var_os("HOME").or_else(|| var_os("USERPROFILE")).map(PathBuf::from)
14}
15
16pub fn get_default_keywords() -> KeywordsConfig {
21 KeywordsConfig {
22 version: 1,
23 patterns: default_patterns(),
24 stop_words: default_stop_words(),
25 contradiction_signals: default_contradiction_signals(),
26 }
27}
28
29fn default_patterns() -> HashMap<String, Vec<String>> {
30 let data: [(&str, &[&str]); 6] = [
31 ("decision", &["决定", "选择", "采用", "定下", "decided", "chose"]),
32 ("preference", &["偏好", "习惯", "喜欢", "首选", "prefer", "like"]),
33 ("solution", &["解决", "修复", "搞定", "改成", "fixed", "solved"]),
34 ("finding", &["发现", "原来", "原因", "定位", "found", "reason"]),
35 ("technical", &["技术栈", "框架", "用的", "基于", "stack", "using"]),
36 ("structure", &["入口", "主文件", "目录", "位于", "entry", "main"]),
37 ];
38 data.into_iter()
39 .map(|(k, v)| (k.to_string(), v.iter().map(|s| s.to_string()).collect()))
40 .collect()
41}
42
43fn default_stop_words() -> Vec<String> {
44 vec![
46 "的", "了", "是", "在", "我", "有", "和", "就", "不", "都", "一", "也", "很", "到", "要", "去",
48 "你", "会", "着", "没有", "看", "好", "这", "那", "什么", "怎么", "请", "能", "可以", "需要",
49 "the", "a", "an", "is", "are", "was", "were", "be", "have", "has", "do", "will", "would",
51 "could", "should", "can", "to", "of", "in", "for", "on", "with", "at", "by", "from", "and",
52 "but", "or", "not", "if", "then", "this", "that", "it", "i", "me", "my", "we", "you", "he",
53 "she", "they", "please", "help", "need", "want", "let", "use",
54 ].into_iter().map(|s| s.to_string()).collect()
55}
56
57fn default_contradiction_signals() -> Vec<String> {
58 vec!["改用", "换成", "改为", "不再", "弃用", "switched", "changed", "replaced", "deprecated"]
59 .into_iter().map(|s| s.to_string()).collect()
60}
61
62#[derive(Debug, Clone, Serialize, Deserialize)]
67pub struct KeywordsConfig {
68 pub version: u32,
69 pub patterns: HashMap<String, Vec<String>>,
70 pub stop_words: Vec<String>,
71 pub contradiction_signals: Vec<String>,
72}
73
74impl KeywordsConfig {
75 pub fn load() -> Self {
76 if let Some(home) = home_dir() {
78 let path = home.join(".matrix").join("keywords.json");
79 if path.exists() {
80 if let Ok(content) = std::fs::read_to_string(&path) {
81 if let Ok(config) = serde_json::from_str::<Self>(&content) {
82 return config;
83 }
84 }
85 }
86 }
87 get_default_keywords()
88 }
89
90 pub fn get_patterns(&self, category: MemoryCategory) -> &[String] {
91 let key = match category {
92 MemoryCategory::Decision | MemoryCategory::KeyDecision => "decision",
93 MemoryCategory::Preference | MemoryCategory::UserIntentPattern => "preference",
94 MemoryCategory::Solution | MemoryCategory::FailedApproach | MemoryCategory::TaskPattern => "solution",
95 MemoryCategory::Finding => "finding",
96 MemoryCategory::Technical => "technical",
97 MemoryCategory::Structure => "structure",
98 };
99 self.patterns.get(key).map(|v| v.as_slice()).unwrap_or(&[])
100 }
101
102 pub fn get_stop_words_set(&self) -> HashSet<&str> {
103 self.stop_words.iter().map(|s| s.as_str()).collect()
104 }
105
106 pub fn get_aliases() -> Vec<(&'static str, &'static str)> {
107 vec![
109 ("数据库", "database"), ("db", "database"),
110 ("前端", "frontend"), ("ui", "frontend"),
111 ("后端", "backend"), ("服务", "service"),
112 ("接口", "api"), ("配置", "config"),
113 ("测试", "test"), ("缓存", "cache"),
114 ("认证", "auth"), ("登录", "login"),
115 ]
116 }
117}
118
119impl Default for KeywordsConfig {
120 fn default() -> Self {
121 Self::load()
122 }
123}