agent-wiki 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/utils.js ADDED
@@ -0,0 +1,156 @@
1
+ /**
2
+ * 工具函数:frontmatter 解析、安全文件名、日期格式化等
3
+ */
4
+ import * as path from "path";
5
+ import * as fs from "fs";
6
+ // ─── Frontmatter 解析 ───
7
+ /**
8
+ * 解析 Markdown 文件的 YAML frontmatter
9
+ * 返回 meta 对象和 body 正文内容
10
+ * 不依赖外部 YAML 库,手动解析简单的 key: value 格式
11
+ */
12
+ export function parseFrontmatter(content) {
13
+ // 匹配开头的 --- ... --- 块
14
+ const match = content.match(/^---\r?\n([\s\S]*?)\r?\n---\r?\n?([\s\S]*)$/);
15
+ if (!match) {
16
+ return { meta: {}, body: content };
17
+ }
18
+ const yamlStr = match[1];
19
+ const body = match[2];
20
+ const meta = {};
21
+ // 逐行解析简单的 YAML(key: value 和 key: [a, b, c] 格式)
22
+ for (const line of yamlStr.split("\n")) {
23
+ const trimmed = line.trim();
24
+ if (!trimmed || trimmed.startsWith("#"))
25
+ continue;
26
+ // 数组格式:tags: [a, b, c]
27
+ const arrMatch = trimmed.match(/^(\w+):\s*\[(.*)\]$/);
28
+ if (arrMatch) {
29
+ const key = arrMatch[1];
30
+ const values = arrMatch[2]
31
+ .split(",")
32
+ .map((v) => v.trim().replace(/^['"]|['"]$/g, ""))
33
+ .filter((v) => v);
34
+ meta[key] = values;
35
+ continue;
36
+ }
37
+ // 嵌套数组项(- value 格式),暂不处理
38
+ if (trimmed.startsWith("- "))
39
+ continue;
40
+ // 普通键值对:key: value
41
+ const kvMatch = trimmed.match(/^(\w+):\s*(.*)$/);
42
+ if (kvMatch) {
43
+ const key = kvMatch[1];
44
+ let value = kvMatch[2].trim().replace(/^['"]|['"]$/g, "");
45
+ // 尝试解析为数字或布尔
46
+ if (value === "true")
47
+ value = true;
48
+ else if (value === "false")
49
+ value = false;
50
+ else if (/^\d+$/.test(value))
51
+ value = Number(value);
52
+ meta[key] = value;
53
+ }
54
+ }
55
+ return { meta, body };
56
+ }
57
+ /**
58
+ * 将 meta 对象和 body 正文合成带 frontmatter 的 Markdown 字符串
59
+ */
60
+ export function writeFrontmatter(meta, body) {
61
+ const lines = ["---"];
62
+ for (const [key, value] of Object.entries(meta)) {
63
+ if (Array.isArray(value)) {
64
+ lines.push(`${key}: [${value.join(", ")}]`);
65
+ }
66
+ else {
67
+ lines.push(`${key}: ${value}`);
68
+ }
69
+ }
70
+ lines.push("---");
71
+ lines.push("");
72
+ lines.push(body.trim());
73
+ return lines.join("\n");
74
+ }
75
+ // ─── 安全文件名 ───
76
+ /**
77
+ * 将标题转为安全的文件名(保留中文、字母、数字、短横线)
78
+ */
79
+ export function safeFilename(title) {
80
+ return title
81
+ .replace(/[^a-zA-Z0-9\u4e00-\u9fff\u3000-\u303f\uff00-\uffef\-_ ]/g, "")
82
+ .replace(/\s+/g, "-")
83
+ .replace(/-+/g, "-")
84
+ .substring(0, 80);
85
+ }
86
+ // ─── 日期格式化 ───
87
+ /**
88
+ * 返回 YYYY-MM-DD 格式的日期字符串
89
+ */
90
+ export function todayStr() {
91
+ return new Date().toISOString().split("T")[0];
92
+ }
93
+ /**
94
+ * 返回 YYYYMMDD 格式的日期字符串(用于文件名)
95
+ */
96
+ export function dateCompact() {
97
+ return new Date().toISOString().split("T")[0].replace(/-/g, "");
98
+ }
99
+ /**
100
+ * 返回 ISO 格式的日期时间字符串(用于日志)
101
+ */
102
+ export function nowStr() {
103
+ return new Date().toISOString().replace("T", " ").substring(0, 19);
104
+ }
105
+ // ─── 文件操作 ───
106
+ /**
107
+ * 确保目录存在
108
+ */
109
+ export function ensureDir(dir) {
110
+ if (!fs.existsSync(dir)) {
111
+ fs.mkdirSync(dir, { recursive: true });
112
+ }
113
+ }
114
+ /**
115
+ * 读取文件内容,文件不存在返回 null
116
+ */
117
+ export function readFile_safe(filePath) {
118
+ try {
119
+ return fs.readFileSync(filePath, "utf-8");
120
+ }
121
+ catch {
122
+ return null;
123
+ }
124
+ }
125
+ /**
126
+ * 写入 JSON 文件
127
+ */
128
+ export function writeJSON(filePath, data) {
129
+ ensureDir(path.dirname(filePath));
130
+ fs.writeFileSync(filePath, JSON.stringify(data, null, 2), "utf-8");
131
+ }
132
+ /**
133
+ * 读取 JSON 文件,文件不存在或解析失败返回 null
134
+ */
135
+ export function readJSON(filePath) {
136
+ const content = readFile_safe(filePath);
137
+ if (!content)
138
+ return null;
139
+ try {
140
+ return JSON.parse(content);
141
+ }
142
+ catch {
143
+ return null;
144
+ }
145
+ }
146
+ /**
147
+ * 获取目录下所有 .md 文件(不含子目录)
148
+ */
149
+ export function listMdFiles(dir) {
150
+ if (!fs.existsSync(dir))
151
+ return [];
152
+ return fs
153
+ .readdirSync(dir)
154
+ .filter((f) => f.endsWith(".md"))
155
+ .sort();
156
+ }
package/package.json ADDED
@@ -0,0 +1,26 @@
1
+ {
2
+ "name": "agent-wiki",
3
+ "version": "0.1.0",
4
+ "description": "卡帕西智能知识库 MCP 插件 — 一行安装,纯对话交互,Agent 自动帮你管理知识库、写有人味儿的原创文章",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "bin": {
8
+ "agent-wiki": "dist/index.js"
9
+ },
10
+ "scripts": {
11
+ "build": "tsc",
12
+ "start": "node dist/index.js",
13
+ "dev": "tsc --watch"
14
+ },
15
+ "keywords": ["mcp", "wiki", "knowledge-base", "karpathy", "obsidian"],
16
+ "author": "",
17
+ "license": "MIT",
18
+ "dependencies": {
19
+ "@modelcontextprotocol/sdk": "^1.29.0",
20
+ "zod": "^4.3.6"
21
+ },
22
+ "devDependencies": {
23
+ "@types/node": "^25.5.2",
24
+ "typescript": "^6.0.2"
25
+ }
26
+ }