@astro-minimax/cli 0.5.0 → 0.7.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.
Files changed (142) hide show
  1. package/README.md +69 -0
  2. package/dist/commands/ai.d.ts +2 -0
  3. package/dist/commands/ai.d.ts.map +1 -0
  4. package/dist/commands/ai.js +99 -0
  5. package/dist/commands/ai.js.map +1 -0
  6. package/dist/commands/data.d.ts +2 -0
  7. package/dist/commands/data.d.ts.map +1 -0
  8. package/dist/commands/data.js +111 -0
  9. package/dist/commands/data.js.map +1 -0
  10. package/dist/commands/hooks.d.ts +2 -0
  11. package/dist/commands/hooks.d.ts.map +1 -0
  12. package/dist/commands/hooks.js +378 -0
  13. package/dist/commands/hooks.js.map +1 -0
  14. package/dist/commands/init.d.ts +2 -0
  15. package/dist/commands/init.d.ts.map +1 -0
  16. package/dist/commands/init.js +50 -0
  17. package/dist/commands/init.js.map +1 -0
  18. package/dist/commands/post.d.ts +2 -0
  19. package/dist/commands/post.d.ts.map +1 -0
  20. package/dist/commands/post.js +190 -0
  21. package/dist/commands/post.js.map +1 -0
  22. package/dist/commands/profile.d.ts +2 -0
  23. package/dist/commands/profile.d.ts.map +1 -0
  24. package/dist/commands/profile.js +88 -0
  25. package/dist/commands/profile.js.map +1 -0
  26. package/dist/index.d.ts +3 -0
  27. package/dist/index.d.ts.map +1 -0
  28. package/dist/index.js +81 -0
  29. package/dist/index.js.map +1 -0
  30. package/dist/tools/ai-process.d.ts +20 -0
  31. package/dist/tools/ai-process.d.ts.map +1 -0
  32. package/dist/tools/ai-process.js +607 -0
  33. package/dist/tools/ai-process.js.map +1 -0
  34. package/dist/tools/build-author-context.d.ts +13 -0
  35. package/dist/tools/build-author-context.d.ts.map +1 -0
  36. package/dist/tools/build-author-context.js +313 -0
  37. package/dist/tools/build-author-context.js.map +1 -0
  38. package/dist/tools/build-voice-profile.d.ts +12 -0
  39. package/dist/tools/build-voice-profile.d.ts.map +1 -0
  40. package/dist/tools/build-voice-profile.js +270 -0
  41. package/dist/tools/build-voice-profile.js.map +1 -0
  42. package/dist/tools/eval-ai-chat.d.ts +17 -0
  43. package/dist/tools/eval-ai-chat.d.ts.map +1 -0
  44. package/dist/tools/eval-ai-chat.js +332 -0
  45. package/dist/tools/eval-ai-chat.js.map +1 -0
  46. package/dist/tools/generate-author-profile.d.ts +14 -0
  47. package/dist/tools/generate-author-profile.d.ts.map +1 -0
  48. package/dist/tools/generate-author-profile.js +289 -0
  49. package/dist/tools/generate-author-profile.js.map +1 -0
  50. package/dist/tools/generate-cover.d.ts +14 -0
  51. package/dist/tools/generate-cover.d.ts.map +1 -0
  52. package/dist/tools/generate-cover.js +95 -0
  53. package/dist/tools/generate-cover.js.map +1 -0
  54. package/dist/tools/generate-og.d.ts +3 -0
  55. package/dist/tools/generate-og.d.ts.map +1 -0
  56. package/dist/tools/generate-og.js +254 -0
  57. package/dist/tools/generate-og.js.map +1 -0
  58. package/dist/tools/generate-related.d.ts +11 -0
  59. package/dist/tools/generate-related.d.ts.map +1 -0
  60. package/dist/tools/generate-related.js +124 -0
  61. package/dist/tools/generate-related.js.map +1 -0
  62. package/dist/tools/generate-tags.d.ts +14 -0
  63. package/dist/tools/generate-tags.d.ts.map +1 -0
  64. package/dist/tools/generate-tags.js +182 -0
  65. package/dist/tools/generate-tags.js.map +1 -0
  66. package/dist/tools/lib/ai-provider.d.ts +43 -0
  67. package/dist/tools/lib/ai-provider.d.ts.map +1 -0
  68. package/dist/tools/lib/ai-provider.js +146 -0
  69. package/dist/tools/lib/ai-provider.js.map +1 -0
  70. package/dist/tools/lib/frontmatter.d.ts +11 -0
  71. package/dist/tools/lib/frontmatter.d.ts.map +1 -0
  72. package/dist/tools/lib/frontmatter.js +80 -0
  73. package/dist/tools/lib/frontmatter.js.map +1 -0
  74. package/dist/tools/lib/index.d.ts +7 -0
  75. package/dist/tools/lib/index.d.ts.map +1 -0
  76. package/{template/tools/lib/index.ts → dist/tools/lib/index.js} +1 -0
  77. package/dist/tools/lib/index.js.map +1 -0
  78. package/dist/tools/lib/markdown.d.ts +6 -0
  79. package/dist/tools/lib/markdown.d.ts.map +1 -0
  80. package/dist/tools/lib/markdown.js +34 -0
  81. package/dist/tools/lib/markdown.js.map +1 -0
  82. package/dist/tools/lib/posts.d.ts +25 -0
  83. package/dist/tools/lib/posts.d.ts.map +1 -0
  84. package/dist/tools/lib/posts.js +63 -0
  85. package/dist/tools/lib/posts.js.map +1 -0
  86. package/dist/tools/lib/utils.d.ts +18 -0
  87. package/dist/tools/lib/utils.d.ts.map +1 -0
  88. package/dist/tools/lib/utils.js +121 -0
  89. package/dist/tools/lib/utils.js.map +1 -0
  90. package/dist/tools/lib/vectors.d.ts +27 -0
  91. package/dist/tools/lib/vectors.d.ts.map +1 -0
  92. package/dist/tools/lib/vectors.js +64 -0
  93. package/dist/tools/lib/vectors.js.map +1 -0
  94. package/dist/tools/summarize.d.ts +16 -0
  95. package/dist/tools/summarize.d.ts.map +1 -0
  96. package/dist/tools/summarize.js +108 -0
  97. package/dist/tools/summarize.js.map +1 -0
  98. package/dist/tools/translate.d.ts +13 -0
  99. package/dist/tools/translate.d.ts.map +1 -0
  100. package/dist/tools/translate.js +46 -0
  101. package/dist/tools/translate.js.map +1 -0
  102. package/dist/tools/vectorize.d.ts +13 -0
  103. package/dist/tools/vectorize.d.ts.map +1 -0
  104. package/dist/tools/vectorize.js +87 -0
  105. package/dist/tools/vectorize.js.map +1 -0
  106. package/package.json +14 -9
  107. package/template/astro.config.ts +8 -28
  108. package/template/datas/ai-seo.json +8 -0
  109. package/template/datas/ai-skip-list.json +1 -0
  110. package/template/datas/author-profile-context.json +21 -0
  111. package/template/datas/author-profile-report.json +21 -0
  112. package/template/datas/eval/gold-set.json +72 -0
  113. package/template/functions/README.md +82 -0
  114. package/template/functions/api/ai-info.ts +2 -2
  115. package/template/functions/api/chat.ts +4 -1
  116. package/template/functions/api/notify/comment.ts +140 -68
  117. package/template/functions/api/notify/debug.ts +41 -0
  118. package/template/functions/api/notify/status.ts +97 -0
  119. package/template/functions/api/notify/test-ai-chat.ts +67 -0
  120. package/template/package.json +22 -25
  121. package/template/src/config.ts +11 -0
  122. package/template/src/content.config.ts +29 -16
  123. package/template/src/env.d.ts +0 -5
  124. package/index.js +0 -36
  125. package/template/tools/README.md +0 -169
  126. package/template/tools/ai-process.ts +0 -816
  127. package/template/tools/build-author-context.ts +0 -405
  128. package/template/tools/build-voice-profile.ts +0 -322
  129. package/template/tools/generate-author-profile.ts +0 -369
  130. package/template/tools/generate-cover.ts +0 -123
  131. package/template/tools/generate-og.ts +0 -280
  132. package/template/tools/generate-related.ts +0 -146
  133. package/template/tools/generate-tags.ts +0 -251
  134. package/template/tools/lib/ai-provider.ts +0 -240
  135. package/template/tools/lib/frontmatter.ts +0 -94
  136. package/template/tools/lib/markdown.ts +0 -40
  137. package/template/tools/lib/posts.ts +0 -89
  138. package/template/tools/lib/utils.ts +0 -138
  139. package/template/tools/lib/vectors.ts +0 -96
  140. package/template/tools/summarize.ts +0 -142
  141. package/template/tools/translate.ts +0 -60
  142. package/template/tools/vectorize.ts +0 -105
@@ -0,0 +1,607 @@
1
+ #!/usr/bin/env npx tsx
2
+ /**
3
+ * AI 文章批处理脚本 (适配 astro-minimax)
4
+ *
5
+ * 用法:
6
+ * pnpm ai:process 处理所有文章(跳过已缓存且未变更的)
7
+ * pnpm ai:process --force 强制重新处理所有文章
8
+ * pnpm ai:process --slug=xxx 只处理指定文章(如 zh/getting-started)
9
+ * pnpm ai:process --task=summary 只运行摘要任务
10
+ * pnpm ai:process --task=seo 只运行 SEO 任务
11
+ * pnpm ai:process --recent=10 处理最近 10 篇文章
12
+ * pnpm ai:process --new-only 只处理没有缓存的文章
13
+ * pnpm ai:process --dry-run 只显示会处理哪些文章
14
+ * pnpm ai:process --concurrency=10 设置并发数(默认 10)
15
+ * pnpm ai:process --no-skip 忽略跳过列表,重试所有文章
16
+ * pnpm ai:process --clear-skip 清空跳过列表后再处理
17
+ * pnpm ai:process --lang=zh 只处理指定语言的文章
18
+ */
19
+ import { mkdir, readFile, writeFile } from "node:fs/promises";
20
+ import { join } from "node:path";
21
+ import crypto from "node:crypto";
22
+ import { getAllPosts, } from "./lib/posts.js";
23
+ import { extractFrontmatter } from "./lib/frontmatter.js";
24
+ import { chatCompletion, hasAPIKey, getConfig } from "./lib/ai-provider.js";
25
+ // ─── 常量 ─────────────────────────────────────────────────────
26
+ const DATA_DIR = join(process.cwd(), "datas");
27
+ const SKIP_LIST_FILE = join(DATA_DIR, "ai-skip-list.json");
28
+ function parseArgs() {
29
+ const args = process.argv.slice(2);
30
+ const flags = {
31
+ force: false,
32
+ slug: null,
33
+ task: null,
34
+ recent: null,
35
+ newOnly: false,
36
+ dryRun: false,
37
+ concurrency: 10,
38
+ noSkip: false,
39
+ clearSkip: false,
40
+ lang: null,
41
+ };
42
+ for (const arg of args) {
43
+ if (arg === "--force")
44
+ flags.force = true;
45
+ else if (arg === "--new-only")
46
+ flags.newOnly = true;
47
+ else if (arg === "--dry-run")
48
+ flags.dryRun = true;
49
+ else if (arg === "--no-skip")
50
+ flags.noSkip = true;
51
+ else if (arg === "--clear-skip")
52
+ flags.clearSkip = true;
53
+ else if (arg.startsWith("--slug="))
54
+ flags.slug = arg.split("=")[1];
55
+ else if (arg.startsWith("--task="))
56
+ flags.task = arg.split("=")[1];
57
+ else if (arg.startsWith("--recent="))
58
+ flags.recent = parseInt(arg.split("=")[1], 10);
59
+ else if (arg.startsWith("--concurrency="))
60
+ flags.concurrency = parseInt(arg.split("=")[1], 10);
61
+ else if (arg.startsWith("--lang="))
62
+ flags.lang = arg.split("=")[1];
63
+ }
64
+ return flags;
65
+ }
66
+ function createCacheManager(cacheFile) {
67
+ let cache = null;
68
+ let writeQueue = Promise.resolve();
69
+ return {
70
+ async load() {
71
+ const cachePath = join(DATA_DIR, cacheFile);
72
+ try {
73
+ const raw = await readFile(cachePath, "utf-8");
74
+ cache = JSON.parse(raw);
75
+ }
76
+ catch {
77
+ cache = {
78
+ meta: { lastUpdated: null, model: null, totalProcessed: 0 },
79
+ articles: {},
80
+ };
81
+ }
82
+ return cache;
83
+ },
84
+ getCache() {
85
+ return cache;
86
+ },
87
+ /** 串行写入:无论多少并发 worker 同时调用,写操作排队执行 */
88
+ async writeEntry(slug, entry, model) {
89
+ writeQueue = writeQueue.then(async () => {
90
+ if (!cache)
91
+ return;
92
+ cache.articles[slug] = entry;
93
+ cache.meta.lastUpdated = new Date().toISOString();
94
+ cache.meta.model = model;
95
+ cache.meta.totalProcessed = Object.keys(cache.articles).length;
96
+ await mkdir(DATA_DIR, { recursive: true });
97
+ const cachePath = join(DATA_DIR, cacheFile);
98
+ await writeFile(cachePath, JSON.stringify(cache, null, 2), "utf-8");
99
+ });
100
+ return writeQueue;
101
+ },
102
+ };
103
+ }
104
+ async function loadSkipList() {
105
+ try {
106
+ const raw = await readFile(SKIP_LIST_FILE, "utf-8");
107
+ return JSON.parse(raw);
108
+ }
109
+ catch {
110
+ return {};
111
+ }
112
+ }
113
+ async function saveSkipList(skipList) {
114
+ await mkdir(DATA_DIR, { recursive: true });
115
+ await writeFile(SKIP_LIST_FILE, JSON.stringify(skipList, null, 2), "utf-8");
116
+ }
117
+ async function addToSkipList(skipList, taskName, slug, errorMsg) {
118
+ const key = `${taskName}:${slug}`;
119
+ const existing = skipList[key];
120
+ skipList[key] = {
121
+ slug,
122
+ task: taskName,
123
+ reason: errorMsg,
124
+ failCount: (existing?.failCount ?? 0) + 1,
125
+ lastFailedAt: new Date().toISOString(),
126
+ firstFailedAt: existing?.firstFailedAt ?? new Date().toISOString(),
127
+ };
128
+ await saveSkipList(skipList);
129
+ }
130
+ // ─── 工具函数 ────────────────────────────────────────────────
131
+ function sleep(ms) {
132
+ return new Promise((resolve) => setTimeout(resolve, ms));
133
+ }
134
+ /** 去重、去空的字符串数组清洗 */
135
+ function cleanStringArray(arr) {
136
+ if (!Array.isArray(arr))
137
+ return [];
138
+ return [...new Set(arr.map((s) => String(s).trim()).filter(Boolean))];
139
+ }
140
+ async function scanArticles(flags) {
141
+ const allPosts = await getAllPosts({ includeDrafts: false, stripBody: false });
142
+ const articles = [];
143
+ for (const post of allPosts) {
144
+ // 跳过草稿
145
+ if (post.draft)
146
+ continue;
147
+ // 语言过滤
148
+ if (flags.lang && post.lang !== flags.lang)
149
+ continue;
150
+ // 读取完整内容用于计算 hash
151
+ const rawContent = await readFile(post.filePath, "utf-8");
152
+ const fm = extractFrontmatter(rawContent);
153
+ const contentHash = crypto
154
+ .createHash("md5")
155
+ .update(fm.body)
156
+ .digest("hex")
157
+ .slice(0, 8);
158
+ const pubDatetime = fm.data.pubDatetime;
159
+ const pubTimestamp = pubDatetime
160
+ ? new Date(pubDatetime).getTime()
161
+ : 0;
162
+ articles.push({
163
+ ...post,
164
+ contentHash,
165
+ fullContent: fm.body,
166
+ pubTimestamp,
167
+ });
168
+ }
169
+ // 按发布时间降序排列
170
+ articles.sort((a, b) => b.pubTimestamp - a.pubTimestamp);
171
+ return articles;
172
+ }
173
+ // ─── AI API 调用 ─────────────────────────────────────────────
174
+ const RATE_LIMIT_MAX_RETRIES = 8;
175
+ async function callAIWithRetry(systemPrompt, userPrompt, options) {
176
+ let lastError = null;
177
+ for (let attempt = 0; attempt <= RATE_LIMIT_MAX_RETRIES; attempt++) {
178
+ try {
179
+ const result = await chatCompletion([
180
+ { role: "system", content: systemPrompt },
181
+ { role: "user", content: userPrompt },
182
+ ], { maxTokens: options?.maxTokens ?? 2048 });
183
+ return result;
184
+ }
185
+ catch (err) {
186
+ lastError = err;
187
+ const is429 = err.message?.includes("429");
188
+ if (is429) {
189
+ // 429 限速:指数退避 + 随机抖动
190
+ const baseSec = Math.min(2 ** attempt, 30);
191
+ const jitter = Math.random() * baseSec * 0.5;
192
+ await sleep((baseSec + jitter) * 1000);
193
+ continue;
194
+ }
195
+ // 非 429 的网络错误,重试 1 次
196
+ if (attempt === 0) {
197
+ await sleep(2000);
198
+ continue;
199
+ }
200
+ throw err;
201
+ }
202
+ }
203
+ throw lastError ?? new Error("超过最大重试次数");
204
+ }
205
+ const TASKS = {
206
+ summary: {
207
+ name: "summary",
208
+ cacheFile: "ai-summaries.json",
209
+ buildPrompt(article) {
210
+ const langHint = article.lang === "en"
211
+ ? "Please respond in English."
212
+ : "请使用中文回复。";
213
+ return {
214
+ system: `你是一位专业的博客内容分析师。请分析给定博客文章,并只返回**严格合法的 JSON**(RFC8259),不得输出任何额外文字或 Markdown 代码块。
215
+
216
+ 请生成以下字段:
217
+
218
+ 1) summary:
219
+ 一句话总结文章核心内容(50-80字)。
220
+ 应包含:主题 + 关键动作/方法 + 结论/收益(若文中存在)。
221
+
222
+ 2) abstract:
223
+ 详细摘要(150-300字)。
224
+ 要求:
225
+ - 客观覆盖文章的背景/问题
226
+ - 核心方案或步骤
227
+ - 关键技术点(如代码、配置、命令、架构)
228
+ - 结论或效果(如有)
229
+ - 不粘贴大段代码
230
+
231
+ 3) keyPoints:
232
+ 3-6条要点列表,用于结构化索引与语义检索。
233
+ 要求:
234
+ - 每条≤30字
235
+ - 陈述句
236
+ - 信息密度高
237
+ - 覆盖:问题/背景、方案、关键技术点、结果/坑点
238
+ - 不要与summary重复
239
+ - 不要空泛表达(避免"经验分享""技术总结"等)
240
+
241
+ 4) tags:
242
+ 3-5个标签。
243
+ 要求:
244
+ - 去重
245
+ - 尽量具体
246
+ - 允许中文或通用英文技术术语
247
+ - 避免泛标签(如"技术""随笔")
248
+ - 英文术语采用常见标准写法(如 Next.js、Docker、Kubernetes)
249
+
250
+ 5) readingTime:
251
+ 整数分钟。
252
+ 估算规则:
253
+ - 中文阅读速度按350字/分钟
254
+ - 若代码块较多或技术细节密集,乘以1.3
255
+ - 若为叙事或轻量内容,乘以1.0
256
+ - 向上取整,最小为1
257
+
258
+ 重要约束:
259
+ - 不添加原文不存在的信息
260
+ - 不引用外部知识补全
261
+ - 忽略 Markdown 噪声(图片引用、代码块标记等)
262
+ - 输出必须可直接 JSON.parse 解析
263
+ - ${langHint}
264
+
265
+ 输出格式必须严格如下(字段齐全):
266
+ {"summary":"...","abstract":"...","keyPoints":["...","..."],"tags":["...","..."],"readingTime":5}`,
267
+ user: `文章标题:${article.title}
268
+ 文章分类:${article.category || "无"}
269
+ 文章标签:${article.tags.join(", ") || "无"}
270
+
271
+ 文章正文:
272
+ ${article.fullContent.slice(0, 8000)}`,
273
+ };
274
+ },
275
+ parseResponse(raw) {
276
+ const jsonMatch = raw.match(/```(?:json)?\s*([\s\S]*?)```/);
277
+ const jsonStr = (jsonMatch ? jsonMatch[1] : raw).trim();
278
+ const parsed = JSON.parse(jsonStr);
279
+ if (!parsed.summary || !parsed.abstract || !Array.isArray(parsed.tags)) {
280
+ throw new Error("摘要数据格式不完整");
281
+ }
282
+ const readingTimeRaw = parsed.readingTime;
283
+ const readingTime = typeof readingTimeRaw === "number"
284
+ ? readingTimeRaw
285
+ : typeof readingTimeRaw === "string"
286
+ ? parseInt(readingTimeRaw, 10) || undefined
287
+ : undefined;
288
+ return {
289
+ summary: parsed.summary,
290
+ abstract: parsed.abstract,
291
+ keyPoints: cleanStringArray(parsed.keyPoints),
292
+ tags: cleanStringArray(parsed.tags),
293
+ readingTime,
294
+ };
295
+ },
296
+ },
297
+ seo: {
298
+ name: "seo",
299
+ cacheFile: "ai-seo.json",
300
+ buildPrompt(article) {
301
+ const langHint = article.lang === "en"
302
+ ? "Please respond in English."
303
+ : "请使用中文回复。";
304
+ return {
305
+ system: `你是一位资深 SEO 与内容增长专家。请基于给定博客文章生成 SEO 文案与关键词数据,并只返回**严格合法的 JSON**(RFC8259),不得输出任何额外文字或 Markdown 代码块。
306
+
307
+ 请输出以下字段:
308
+
309
+ 1) metaDescription:
310
+ 用于网页 <meta name="description"> 的描述(120-160字)。
311
+ 要求:
312
+ - 自然包含 1-2 个核心关键词(不要堆砌)
313
+ - 信息结构建议:主题/对象 + 解决的问题/收益 + 关键方法/亮点(若有)
314
+ - 不要复读标题(不要以"本文/这篇文章"开头)
315
+ - 不要换行,不要引号,不要使用夸张营销词(如"史上最强/必看")
316
+
317
+ 2) keywords:
318
+ 5-8 个 SEO 关键词或短语(字符串数组),按重要性从高到低排序。
319
+ 要求:
320
+ - 组合:2-3 个核心短词 + 3-5 个长尾短语(更像用户会搜的表达)
321
+ - 避免过泛词(如"技术/教程/经验/分享/博客")
322
+ - 去重,避免同义重复
323
+ - 中文优先;通用技术名词可用英文/标准写法(如 Next.js、Cloudflare Workers、Docker)
324
+ - 长尾短语可包含"怎么做/报错/排查/对比/最佳实践/配置"等意图词(仅在文章内容支持时使用)
325
+
326
+ 3) ogDescription:
327
+ 用于 Open Graph / 社交媒体分享的描述(60-100字)。
328
+ 要求:
329
+ - 比 metaDescription 更口语化、更吸引点击
330
+ - 强调"读者能得到什么"或"解决什么痛点"
331
+ - 不要标题复读,不要换行,不要用引号
332
+
333
+ 重要约束:
334
+ - 只能使用文章中出现或可直接概括出的信息;不得凭空补充工具/数据/结论
335
+ - 输入可能包含 Markdown、代码块、链接;请忽略格式噪声,聚焦内容
336
+ - 输出必须可直接 JSON.parse 解析
337
+ - ${langHint}
338
+
339
+ 输出格式必须严格如下(字段齐全):
340
+ {"metaDescription":"...","keywords":["...","..."],"ogDescription":"..."}`,
341
+ user: `文章标题:${article.title}
342
+ 文章分类:${article.category || "无"}
343
+ 文章标签:${article.tags.join(", ") || "无"}
344
+
345
+ 文章正文:
346
+ ${article.fullContent.slice(0, 8000)}`,
347
+ };
348
+ },
349
+ parseResponse(raw) {
350
+ const jsonMatch = raw.match(/```(?:json)?\s*([\s\S]*?)```/);
351
+ const jsonStr = (jsonMatch ? jsonMatch[1] : raw).trim();
352
+ const parsed = JSON.parse(jsonStr);
353
+ if (!parsed.metaDescription ||
354
+ !Array.isArray(parsed.keywords) ||
355
+ !parsed.ogDescription) {
356
+ throw new Error("SEO 数据格式不完整");
357
+ }
358
+ return {
359
+ metaDescription: parsed.metaDescription,
360
+ keywords: cleanStringArray(parsed.keywords),
361
+ ogDescription: parsed.ogDescription,
362
+ };
363
+ },
364
+ },
365
+ };
366
+ async function processQueue(queue, task, cacheManager, concurrency, skipList) {
367
+ let success = 0;
368
+ let failed = 0;
369
+ let completed = 0;
370
+ const failures = [];
371
+ let consecutiveFailures = 0;
372
+ let stopped = false;
373
+ const startTime = Date.now();
374
+ const config = getConfig();
375
+ // 实时状态行
376
+ function printStatus() {
377
+ const elapsed = ((Date.now() - startTime) / 1000).toFixed(0);
378
+ const rate = completed > 0
379
+ ? ((completed / (Date.now() - startTime)) * 1000).toFixed(1)
380
+ : "0";
381
+ const remaining = completed > 0
382
+ ? Math.round(((queue.length - completed) / completed) *
383
+ ((Date.now() - startTime) / 1000))
384
+ : "?";
385
+ const pct = Math.round((completed / queue.length) * 100);
386
+ const barWidth = 25;
387
+ const filled = Math.round((completed / queue.length) * barWidth);
388
+ const bar = "█".repeat(filled) + "░".repeat(barWidth - filled);
389
+ process.stdout.write(`\r [${bar}] ${completed}/${queue.length} (${pct}%) | ✅ ${success} ❌ ${failed} | ${elapsed}s | ~${remaining}s left | ${rate}/s `);
390
+ }
391
+ // 队列索引,每个 worker 原子地取下一个任务
392
+ let nextIndex = 0;
393
+ async function worker() {
394
+ while (!stopped) {
395
+ const idx = nextIndex++;
396
+ if (idx >= queue.length)
397
+ break;
398
+ const article = queue[idx];
399
+ try {
400
+ const prompt = task.buildPrompt(article);
401
+ const raw = await callAIWithRetry(prompt.system, prompt.user);
402
+ const data = task.parseResponse(raw);
403
+ await cacheManager.writeEntry(article.id, {
404
+ data: data,
405
+ contentHash: article.contentHash,
406
+ processedAt: new Date().toISOString(),
407
+ }, config.model);
408
+ // 处理成功,从跳过列表中移除(如果之前失败过)
409
+ const skipKey = `${task.name}:${article.id}`;
410
+ if (skipList[skipKey]) {
411
+ delete skipList[skipKey];
412
+ await saveSkipList(skipList);
413
+ }
414
+ success++;
415
+ consecutiveFailures = 0;
416
+ }
417
+ catch (err) {
418
+ failed++;
419
+ failures.push({
420
+ slug: article.id,
421
+ error: err.message,
422
+ });
423
+ // 将失败的文章加入跳过列表
424
+ await addToSkipList(skipList, task.name, article.id, err.message);
425
+ // 429 是限速,不计入连续失败
426
+ const is429 = err.message?.includes("429");
427
+ if (!is429) {
428
+ consecutiveFailures++;
429
+ // 连续失败 10 次可能是 API 级别的问题
430
+ if (consecutiveFailures >= 10) {
431
+ stopped = true;
432
+ console.error(`\n\n ❌ 连续失败 10 次(非限速错误),暂停处理。最后错误: ${err.message}`);
433
+ console.error(` 💡 失败的文章已记录到跳过列表,下次运行将自动跳过`);
434
+ }
435
+ }
436
+ }
437
+ completed++;
438
+ printStatus();
439
+ }
440
+ }
441
+ // 启动 N 个 worker 并发处理
442
+ const workers = [];
443
+ const workerCount = Math.min(concurrency, queue.length);
444
+ for (let i = 0; i < workerCount; i++) {
445
+ workers.push(worker());
446
+ }
447
+ await Promise.all(workers);
448
+ const elapsed = ((Date.now() - startTime) / 1000).toFixed(1);
449
+ // 清除状态行
450
+ process.stdout.write("\r" + " ".repeat(100) + "\r");
451
+ return { success, failed, failures, elapsed };
452
+ }
453
+ // ─── 主流程 ──────────────────────────────────────────────────
454
+ async function main() {
455
+ const flags = parseArgs();
456
+ // 检查 API Key
457
+ if (!hasAPIKey()) {
458
+ console.error("❌ 缺少 AI API Key,请在 .env 中设置:");
459
+ console.error(" AI_API_KEY=your_api_key_here");
460
+ console.error(" AI_BASE_URL=https://api.openai.com # 可选,默认 OpenAI");
461
+ console.error(" AI_MODEL=gpt-4o-mini # 可选,默认 gpt-4o-mini");
462
+ process.exit(1);
463
+ }
464
+ const config = getConfig();
465
+ // 加载跳过列表
466
+ let skipList = await loadSkipList();
467
+ // 检查跳过列表状态,给出提示
468
+ const skipListEntries = Object.keys(skipList);
469
+ if (skipListEntries.length > 0 && !flags.noSkip && !flags.clearSkip) {
470
+ // 收集常见的失败原因
471
+ const reasons = new Map();
472
+ for (const entry of Object.values(skipList)) {
473
+ const key = entry.reason.slice(0, 50);
474
+ reasons.set(key, (reasons.get(key) || 0) + 1);
475
+ }
476
+ const topReason = [...reasons.entries()].sort((a, b) => b[1] - a[1])[0];
477
+ console.log(`⚠️ 检测到 ${skipListEntries.length} 篇文章在跳过列表中`);
478
+ console.log(` 最常见失败原因: ${topReason[0]}... (${topReason[1]} 次)`);
479
+ console.log(` `);
480
+ console.log(` 💡 解决方案:`);
481
+ console.log(` - 使用 --clear-skip 清空跳过列表后重试`);
482
+ console.log(` - 使用 --no-skip 忽略跳过列表强制重试`);
483
+ console.log(` - 检查 API 配置是否正确 (AI_API_KEY, AI_BASE_URL)`);
484
+ console.log("");
485
+ }
486
+ console.log("🤖 AI 文章处理器 (astro-minimax)");
487
+ console.log("━".repeat(50));
488
+ console.log(` 模型: ${config.model}`);
489
+ console.log(` API: ${config.baseUrl}`);
490
+ console.log(` 并发: ${flags.concurrency}`);
491
+ if (flags.noSkip)
492
+ console.log(` 跳过列表: 已忽略 (--no-skip)`);
493
+ if (flags.lang)
494
+ console.log(` 语言: ${flags.lang}`);
495
+ console.log("");
496
+ // 1. 扫描文章
497
+ console.log("📂 扫描文章...");
498
+ let articles = await scanArticles(flags);
499
+ console.log(` 找到 ${articles.length} 篇文章`);
500
+ // 2. 过滤
501
+ if (flags.slug) {
502
+ articles = articles.filter((a) => a.id === flags.slug);
503
+ if (articles.length === 0) {
504
+ console.error(`❌ 未找到文章: ${flags.slug}`);
505
+ console.error(` 提示: 使用完整 ID,如 zh/getting-started`);
506
+ process.exit(1);
507
+ }
508
+ console.log(` 指定文章: ${flags.slug}`);
509
+ }
510
+ if (flags.recent) {
511
+ articles = articles.slice(0, flags.recent);
512
+ console.log(` 最近 ${flags.recent} 篇`);
513
+ }
514
+ // 3. 确定要运行的任务
515
+ const taskNames = flags.task ? [flags.task] : ["summary", "seo"];
516
+ const invalidTask = taskNames.find((t) => !TASKS[t]);
517
+ if (invalidTask) {
518
+ console.error(`❌ 未知任务: ${invalidTask}(可选: summary, seo)`);
519
+ process.exit(1);
520
+ }
521
+ console.log(` 任务: ${taskNames.join(", ")}`);
522
+ console.log("");
523
+ // 4. 逐任务处理
524
+ for (const taskName of taskNames) {
525
+ const task = TASKS[taskName];
526
+ console.log(`📋 任务: ${task.name}`);
527
+ console.log("─".repeat(50));
528
+ const cacheManager = createCacheManager(task.cacheFile);
529
+ const cache = await cacheManager.load();
530
+ // 确定需要处理的文章
531
+ const queue = [];
532
+ let skipped = 0;
533
+ let skippedBySkipList = 0;
534
+ const skippedSlugs = [];
535
+ for (const article of articles) {
536
+ const cached = cache.articles[article.id];
537
+ const skipKey = `${taskName}:${article.id}`;
538
+ // 检查跳过列表(--slug 指定的文章不受跳过列表影响)
539
+ if (!flags.noSkip && !flags.slug && skipList[skipKey]) {
540
+ skippedBySkipList++;
541
+ skippedSlugs.push(article.id);
542
+ continue;
543
+ }
544
+ if (flags.force) {
545
+ queue.push(article);
546
+ }
547
+ else if (!cached) {
548
+ queue.push(article);
549
+ }
550
+ else if (flags.newOnly) {
551
+ skipped++;
552
+ }
553
+ else if (cached.contentHash !== article.contentHash) {
554
+ queue.push(article);
555
+ }
556
+ else {
557
+ skipped++;
558
+ }
559
+ }
560
+ console.log(` 跳过: ${skipped} 篇(缓存有效)`);
561
+ if (skippedBySkipList > 0) {
562
+ console.log(` 跳过: ${skippedBySkipList} 篇(之前处理失败,已标记跳过)`);
563
+ console.log(` 使用 --no-skip 可重试这些文章,--clear-skip 可清空跳过列表`);
564
+ if (skippedBySkipList <= 20) {
565
+ for (const slug of skippedSlugs) {
566
+ const info = skipList[`${taskName}:${slug}`];
567
+ // 截断错误信息,避免过长
568
+ const reasonShort = info.reason.length > 80 ? info.reason.slice(0, 80) + '...' : info.reason;
569
+ console.log(` - ${slug} (失败 ${info.failCount} 次: ${reasonShort})`);
570
+ }
571
+ }
572
+ }
573
+ console.log(` 待处理: ${queue.length} 篇`);
574
+ if (flags.dryRun) {
575
+ if (queue.length > 0) {
576
+ console.log("\n 将处理以下文章:");
577
+ for (const a of queue) {
578
+ const reason = cache.articles[a.id] ? "内容变更" : "新文章";
579
+ console.log(` - ${a.id} (${reason})`);
580
+ }
581
+ }
582
+ console.log("");
583
+ continue;
584
+ }
585
+ if (queue.length === 0) {
586
+ console.log(" ✅ 无需处理\n");
587
+ continue;
588
+ }
589
+ // 并发处理
590
+ console.log("");
591
+ const result = await processQueue(queue, task, cacheManager, flags.concurrency, skipList);
592
+ console.log(` ✅ 成功: ${result.success} ❌ 失败: ${result.failed} ⏱️ ${result.elapsed}s`);
593
+ if (result.failures.length > 0) {
594
+ console.log(` 失败文章(已加入跳过列表,下次运行将自动跳过):`);
595
+ for (const f of result.failures) {
596
+ console.log(` - ${f.slug}: ${f.error}`);
597
+ }
598
+ }
599
+ console.log("");
600
+ }
601
+ console.log("🏁 处理完成");
602
+ }
603
+ main().catch((err) => {
604
+ console.error("❌ 致命错误:", err.message);
605
+ process.exit(1);
606
+ });
607
+ //# sourceMappingURL=ai-process.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ai-process.js","sourceRoot":"","sources":["../../src/tools/ai-process.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env npx tsx
2
+ /**
3
+ * 构建作者上下文数据
4
+ *
5
+ * 聚合博客文章数据为统一的 author-context.json,
6
+ * 为 AI 博客分身对话提供上下文。
7
+ *
8
+ * 用法:
9
+ * pnpm context:build 构建作者上下文
10
+ * pnpm context:build --include-body 包含文章正文内容
11
+ */
12
+ export {};
13
+ //# sourceMappingURL=build-author-context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build-author-context.d.ts","sourceRoot":"","sources":["../../src/tools/build-author-context.ts"],"names":[],"mappings":";AACA;;;;;;;;;GASG"}