@astro-minimax/cli 0.5.0 → 0.7.1

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 (174) 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/podcast.d.ts +2 -0
  19. package/dist/commands/podcast.d.ts.map +1 -0
  20. package/dist/commands/podcast.js +89 -0
  21. package/dist/commands/podcast.js.map +1 -0
  22. package/dist/commands/post.d.ts +2 -0
  23. package/dist/commands/post.d.ts.map +1 -0
  24. package/dist/commands/post.js +190 -0
  25. package/dist/commands/post.js.map +1 -0
  26. package/dist/commands/profile.d.ts +2 -0
  27. package/dist/commands/profile.d.ts.map +1 -0
  28. package/dist/commands/profile.js +88 -0
  29. package/dist/commands/profile.js.map +1 -0
  30. package/dist/index.d.ts +3 -0
  31. package/dist/index.d.ts.map +1 -0
  32. package/dist/index.js +81 -0
  33. package/dist/index.js.map +1 -0
  34. package/dist/tools/ai-process.d.ts +20 -0
  35. package/dist/tools/ai-process.d.ts.map +1 -0
  36. package/dist/tools/ai-process.js +607 -0
  37. package/dist/tools/ai-process.js.map +1 -0
  38. package/dist/tools/build-author-context.d.ts +13 -0
  39. package/dist/tools/build-author-context.d.ts.map +1 -0
  40. package/dist/tools/build-author-context.js +313 -0
  41. package/dist/tools/build-author-context.js.map +1 -0
  42. package/dist/tools/build-voice-profile.d.ts +12 -0
  43. package/dist/tools/build-voice-profile.d.ts.map +1 -0
  44. package/dist/tools/build-voice-profile.js +270 -0
  45. package/dist/tools/build-voice-profile.js.map +1 -0
  46. package/dist/tools/eval-ai-chat.d.ts +17 -0
  47. package/dist/tools/eval-ai-chat.d.ts.map +1 -0
  48. package/dist/tools/eval-ai-chat.js +362 -0
  49. package/dist/tools/eval-ai-chat.js.map +1 -0
  50. package/dist/tools/generate-author-profile.d.ts +14 -0
  51. package/dist/tools/generate-author-profile.d.ts.map +1 -0
  52. package/dist/tools/generate-author-profile.js +289 -0
  53. package/dist/tools/generate-author-profile.js.map +1 -0
  54. package/dist/tools/generate-cover.d.ts +14 -0
  55. package/dist/tools/generate-cover.d.ts.map +1 -0
  56. package/dist/tools/generate-cover.js +95 -0
  57. package/dist/tools/generate-cover.js.map +1 -0
  58. package/dist/tools/generate-og.d.ts +3 -0
  59. package/dist/tools/generate-og.d.ts.map +1 -0
  60. package/dist/tools/generate-og.js +254 -0
  61. package/dist/tools/generate-og.js.map +1 -0
  62. package/dist/tools/generate-related.d.ts +11 -0
  63. package/dist/tools/generate-related.d.ts.map +1 -0
  64. package/dist/tools/generate-related.js +124 -0
  65. package/dist/tools/generate-related.js.map +1 -0
  66. package/dist/tools/generate-tags.d.ts +14 -0
  67. package/dist/tools/generate-tags.d.ts.map +1 -0
  68. package/dist/tools/generate-tags.js +182 -0
  69. package/dist/tools/generate-tags.js.map +1 -0
  70. package/dist/tools/lib/ai-provider.d.ts +43 -0
  71. package/dist/tools/lib/ai-provider.d.ts.map +1 -0
  72. package/dist/tools/lib/ai-provider.js +146 -0
  73. package/dist/tools/lib/ai-provider.js.map +1 -0
  74. package/dist/tools/lib/audio-processor.d.ts +46 -0
  75. package/dist/tools/lib/audio-processor.d.ts.map +1 -0
  76. package/dist/tools/lib/audio-processor.js +188 -0
  77. package/dist/tools/lib/audio-processor.js.map +1 -0
  78. package/dist/tools/lib/frontmatter.d.ts +11 -0
  79. package/dist/tools/lib/frontmatter.d.ts.map +1 -0
  80. package/dist/tools/lib/frontmatter.js +80 -0
  81. package/dist/tools/lib/frontmatter.js.map +1 -0
  82. package/dist/tools/lib/index.d.ts +7 -0
  83. package/dist/tools/lib/index.d.ts.map +1 -0
  84. package/{template/tools/lib/index.ts → dist/tools/lib/index.js} +1 -0
  85. package/dist/tools/lib/index.js.map +1 -0
  86. package/dist/tools/lib/markdown.d.ts +6 -0
  87. package/dist/tools/lib/markdown.d.ts.map +1 -0
  88. package/dist/tools/lib/markdown.js +34 -0
  89. package/dist/tools/lib/markdown.js.map +1 -0
  90. package/dist/tools/lib/posts.d.ts +25 -0
  91. package/dist/tools/lib/posts.d.ts.map +1 -0
  92. package/dist/tools/lib/posts.js +63 -0
  93. package/dist/tools/lib/posts.js.map +1 -0
  94. package/dist/tools/lib/script-generator.d.ts +61 -0
  95. package/dist/tools/lib/script-generator.d.ts.map +1 -0
  96. package/dist/tools/lib/script-generator.js +182 -0
  97. package/dist/tools/lib/script-generator.js.map +1 -0
  98. package/dist/tools/lib/tts-provider.d.ts +65 -0
  99. package/dist/tools/lib/tts-provider.d.ts.map +1 -0
  100. package/dist/tools/lib/tts-provider.js +116 -0
  101. package/dist/tools/lib/tts-provider.js.map +1 -0
  102. package/dist/tools/lib/types.d.ts +129 -0
  103. package/dist/tools/lib/types.d.ts.map +1 -0
  104. package/dist/tools/lib/types.js +64 -0
  105. package/dist/tools/lib/types.js.map +1 -0
  106. package/dist/tools/lib/utils.d.ts +18 -0
  107. package/dist/tools/lib/utils.d.ts.map +1 -0
  108. package/dist/tools/lib/utils.js +121 -0
  109. package/dist/tools/lib/utils.js.map +1 -0
  110. package/dist/tools/lib/vectors.d.ts +27 -0
  111. package/dist/tools/lib/vectors.d.ts.map +1 -0
  112. package/dist/tools/lib/vectors.js +64 -0
  113. package/dist/tools/lib/vectors.js.map +1 -0
  114. package/dist/tools/podcast-feed.d.ts +6 -0
  115. package/dist/tools/podcast-feed.d.ts.map +1 -0
  116. package/dist/tools/podcast-feed.js +121 -0
  117. package/dist/tools/podcast-feed.js.map +1 -0
  118. package/dist/tools/podcast-generate.d.ts +15 -0
  119. package/dist/tools/podcast-generate.d.ts.map +1 -0
  120. package/dist/tools/podcast-generate.js +318 -0
  121. package/dist/tools/podcast-generate.js.map +1 -0
  122. package/dist/tools/podcast-list.d.ts +6 -0
  123. package/dist/tools/podcast-list.d.ts.map +1 -0
  124. package/dist/tools/podcast-list.js +66 -0
  125. package/dist/tools/podcast-list.js.map +1 -0
  126. package/dist/tools/summarize.d.ts +16 -0
  127. package/dist/tools/summarize.d.ts.map +1 -0
  128. package/dist/tools/summarize.js +108 -0
  129. package/dist/tools/summarize.js.map +1 -0
  130. package/dist/tools/translate.d.ts +13 -0
  131. package/dist/tools/translate.d.ts.map +1 -0
  132. package/dist/tools/translate.js +46 -0
  133. package/dist/tools/translate.js.map +1 -0
  134. package/dist/tools/vectorize.d.ts +13 -0
  135. package/dist/tools/vectorize.d.ts.map +1 -0
  136. package/dist/tools/vectorize.js +87 -0
  137. package/dist/tools/vectorize.js.map +1 -0
  138. package/package.json +14 -9
  139. package/template/astro.config.ts +8 -28
  140. package/template/datas/ai-seo.json +8 -0
  141. package/template/datas/ai-skip-list.json +1 -0
  142. package/template/datas/author-profile-context.json +21 -0
  143. package/template/datas/author-profile-report.json +21 -0
  144. package/template/datas/eval/gold-set.json +72 -0
  145. package/template/functions/README.md +82 -0
  146. package/template/functions/api/ai-info.ts +2 -2
  147. package/template/functions/api/chat.ts +4 -1
  148. package/template/functions/api/notify/comment.ts +140 -68
  149. package/template/functions/api/notify/debug.ts +41 -0
  150. package/template/functions/api/notify/status.ts +97 -0
  151. package/template/functions/api/notify/test-ai-chat.ts +67 -0
  152. package/template/package.json +22 -25
  153. package/template/src/config.ts +11 -0
  154. package/template/src/content.config.ts +29 -16
  155. package/template/src/env.d.ts +0 -5
  156. package/index.js +0 -36
  157. package/template/tools/README.md +0 -169
  158. package/template/tools/ai-process.ts +0 -816
  159. package/template/tools/build-author-context.ts +0 -405
  160. package/template/tools/build-voice-profile.ts +0 -322
  161. package/template/tools/generate-author-profile.ts +0 -369
  162. package/template/tools/generate-cover.ts +0 -123
  163. package/template/tools/generate-og.ts +0 -280
  164. package/template/tools/generate-related.ts +0 -146
  165. package/template/tools/generate-tags.ts +0 -251
  166. package/template/tools/lib/ai-provider.ts +0 -240
  167. package/template/tools/lib/frontmatter.ts +0 -94
  168. package/template/tools/lib/markdown.ts +0 -40
  169. package/template/tools/lib/posts.ts +0 -89
  170. package/template/tools/lib/utils.ts +0 -138
  171. package/template/tools/lib/vectors.ts +0 -96
  172. package/template/tools/summarize.ts +0 -142
  173. package/template/tools/translate.ts +0 -60
  174. package/template/tools/vectorize.ts +0 -105
@@ -0,0 +1,43 @@
1
+ /**
2
+ * 通用 AI Provider 抽象层
3
+ *
4
+ * 统一管理所有 AI API 调用,支持多种 provider 和自定义端点。
5
+ * 工具脚本不应直接调用任何 AI API,而是通过此模块调用。
6
+ *
7
+ * 配置方式(环境变量):
8
+ * AI_PROVIDER — 使用的 provider: "openai" | "anthropic" | "custom" (默认 "openai")
9
+ * AI_API_KEY — API Key(也兼容 OPENAI_API_KEY / ANTHROPIC_API_KEY)
10
+ * AI_BASE_URL — 自定义 API 基础 URL(用于兼容 OpenAI 接口的第三方服务)
11
+ * AI_MODEL — 默认模型名称
12
+ */
13
+ export type AIProvider = "openai" | "anthropic" | "custom";
14
+ export interface AIConfig {
15
+ provider: AIProvider;
16
+ apiKey: string;
17
+ baseUrl: string;
18
+ model: string;
19
+ }
20
+ export interface ChatMessage {
21
+ role: "system" | "user" | "assistant";
22
+ content: string;
23
+ }
24
+ export interface ChatOptions {
25
+ model?: string;
26
+ maxTokens?: number;
27
+ responseFormat?: "text" | "json";
28
+ }
29
+ export interface EmbeddingOptions {
30
+ model?: string;
31
+ batchSize?: number;
32
+ }
33
+ export interface ImageOptions {
34
+ model?: string;
35
+ size?: string;
36
+ quality?: string;
37
+ }
38
+ export declare function getConfig(): AIConfig;
39
+ export declare function hasAPIKey(): boolean;
40
+ export declare function chatCompletion(messages: ChatMessage[], options?: ChatOptions): Promise<string>;
41
+ export declare function generateEmbeddings(texts: string[], options?: EmbeddingOptions): Promise<number[][]>;
42
+ export declare function generateImage(prompt: string, options?: ImageOptions): Promise<Uint8Array>;
43
+ //# sourceMappingURL=ai-provider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ai-provider.d.ts","sourceRoot":"","sources":["../../../src/tools/lib/ai-provider.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;GAWG;AAEH,MAAM,MAAM,UAAU,GAAG,QAAQ,GAAG,WAAW,GAAG,QAAQ,CAAC;AAE3D,MAAM,WAAW,QAAQ;IACvB,QAAQ,EAAE,UAAU,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,QAAQ,GAAG,MAAM,GAAG,WAAW,CAAC;IACtC,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,WAAW;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,cAAc,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;CAClC;AAED,MAAM,WAAW,gBAAgB;IAC/B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,YAAY;IAC3B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAmBD,wBAAgB,SAAS,IAAI,QAAQ,CAEpC;AAED,wBAAgB,SAAS,IAAI,OAAO,CAGnC;AAcD,wBAAsB,cAAc,CAClC,QAAQ,EAAE,WAAW,EAAE,EACvB,OAAO,CAAC,EAAE,WAAW,GACpB,OAAO,CAAC,MAAM,CAAC,CAuDjB;AAED,wBAAsB,kBAAkB,CACtC,KAAK,EAAE,MAAM,EAAE,EACf,OAAO,CAAC,EAAE,gBAAgB,GACzB,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CA0CrB;AAED,wBAAsB,aAAa,CACjC,MAAM,EAAE,MAAM,EACd,OAAO,CAAC,EAAE,YAAY,GACrB,OAAO,CAAC,UAAU,CAAC,CA6CrB"}
@@ -0,0 +1,146 @@
1
+ import { fetch, ProxyAgent } from "undici";
2
+ function resolveConfig() {
3
+ const provider = (process.env.AI_PROVIDER || "openai");
4
+ const apiKey = process.env.AI_API_KEY ||
5
+ process.env.OPENAI_API_KEY ||
6
+ process.env.ANTHROPIC_API_KEY ||
7
+ "";
8
+ const baseUrl = process.env.AI_BASE_URL ||
9
+ (provider === "anthropic"
10
+ ? "https://api.anthropic.com"
11
+ : "https://api.openai.com");
12
+ const model = process.env.AI_MODEL || "gpt-4o-mini";
13
+ return { provider, apiKey, baseUrl, model };
14
+ }
15
+ export function getConfig() {
16
+ return resolveConfig();
17
+ }
18
+ export function hasAPIKey() {
19
+ const cfg = resolveConfig();
20
+ return cfg.apiKey.length > 0;
21
+ }
22
+ /**
23
+ * 获取代理 dispatcher(如果配置了代理)
24
+ */
25
+ function getProxyDispatcher() {
26
+ const proxyUrl = process.env.HTTPS_PROXY || process.env.https_proxy ||
27
+ process.env.HTTP_PROXY || process.env.http_proxy;
28
+ if (proxyUrl) {
29
+ return new ProxyAgent(proxyUrl);
30
+ }
31
+ return undefined;
32
+ }
33
+ export async function chatCompletion(messages, options) {
34
+ const cfg = resolveConfig();
35
+ if (!cfg.apiKey) {
36
+ throw new Error("AI API Key 未设置。请设置 AI_API_KEY 或 OPENAI_API_KEY 环境变量。");
37
+ }
38
+ const model = options?.model || cfg.model;
39
+ const maxTokens = options?.maxTokens || 1024;
40
+ // 处理 baseUrl 可能已经包含 /v1 的情况
41
+ const baseUrl = cfg.baseUrl.replace(/\/v1\/?$/, '');
42
+ const url = `${baseUrl}/v1/chat/completions`;
43
+ const body = {
44
+ model,
45
+ messages,
46
+ max_tokens: maxTokens,
47
+ };
48
+ if (options?.responseFormat === "json") {
49
+ body.response_format = { type: "json_object" };
50
+ }
51
+ let response;
52
+ try {
53
+ const dispatcher = getProxyDispatcher();
54
+ response = await fetch(url, {
55
+ method: "POST",
56
+ headers: {
57
+ "Content-Type": "application/json",
58
+ Authorization: `Bearer ${cfg.apiKey}`,
59
+ },
60
+ body: JSON.stringify(body),
61
+ ...(dispatcher && { dispatcher }),
62
+ });
63
+ }
64
+ catch (fetchErr) {
65
+ const err = fetchErr;
66
+ throw new Error(`网络请求失败: ${err.message}\n` +
67
+ ` 请检查: API URL 是否正确 (${cfg.baseUrl})\n` +
68
+ ` 网络是否可访问该端点`);
69
+ }
70
+ if (!response.ok) {
71
+ const errText = await response.text();
72
+ throw new Error(`API 错误 (${response.status}): ${errText.slice(0, 200)}`);
73
+ }
74
+ const data = (await response.json());
75
+ return data.choices?.[0]?.message?.content?.trim() || "";
76
+ }
77
+ export async function generateEmbeddings(texts, options) {
78
+ const cfg = resolveConfig();
79
+ if (!cfg.apiKey) {
80
+ throw new Error("AI API Key 未设置。");
81
+ }
82
+ const model = options?.model || "text-embedding-3-small";
83
+ const batchSize = options?.batchSize || 20;
84
+ const allEmbeddings = [];
85
+ for (let i = 0; i < texts.length; i += batchSize) {
86
+ const batch = texts.slice(i, i + batchSize).map(t => t.slice(0, 8000));
87
+ const dispatcher = getProxyDispatcher();
88
+ const baseUrl = cfg.baseUrl.replace(/\/v1\/?$/, '');
89
+ const response = await fetch(`${baseUrl}/v1/embeddings`, {
90
+ method: "POST",
91
+ headers: {
92
+ "Content-Type": "application/json",
93
+ Authorization: `Bearer ${cfg.apiKey}`,
94
+ },
95
+ body: JSON.stringify({ model, input: batch }),
96
+ ...(dispatcher && { dispatcher }),
97
+ });
98
+ if (!response.ok) {
99
+ const errText = await response.text();
100
+ throw new Error(`Embeddings API 错误 (${response.status}): ${errText}`);
101
+ }
102
+ const data = (await response.json());
103
+ allEmbeddings.push(...data.data.map(d => d.embedding));
104
+ if (i + batchSize < texts.length) {
105
+ await new Promise(r => setTimeout(r, 200));
106
+ }
107
+ }
108
+ return allEmbeddings;
109
+ }
110
+ export async function generateImage(prompt, options) {
111
+ const cfg = resolveConfig();
112
+ if (!cfg.apiKey) {
113
+ throw new Error("AI API Key 未设置。");
114
+ }
115
+ const model = options?.model || "dall-e-3";
116
+ const size = options?.size || "1792x1024";
117
+ const quality = options?.quality || "standard";
118
+ const dispatcher = getProxyDispatcher();
119
+ const baseUrl = cfg.baseUrl.replace(/\/v1\/?$/, '');
120
+ const response = await fetch(`${baseUrl}/v1/images/generations`, {
121
+ method: "POST",
122
+ headers: {
123
+ "Content-Type": "application/json",
124
+ Authorization: `Bearer ${cfg.apiKey}`,
125
+ },
126
+ body: JSON.stringify({
127
+ model,
128
+ prompt,
129
+ n: 1,
130
+ size,
131
+ quality,
132
+ response_format: "b64_json",
133
+ }),
134
+ ...(dispatcher && { dispatcher }),
135
+ });
136
+ if (!response.ok) {
137
+ const errText = await response.text();
138
+ throw new Error(`Image API 错误 (${response.status}): ${errText}`);
139
+ }
140
+ const result = (await response.json());
141
+ if (result.data[0].revised_prompt) {
142
+ console.log(` 修正后的提示词: ${result.data[0].revised_prompt.slice(0, 100)}...`);
143
+ }
144
+ return new Uint8Array(Buffer.from(result.data[0].b64_json, "base64"));
145
+ }
146
+ //# sourceMappingURL=ai-provider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ai-provider.js","sourceRoot":"","sources":["../../../src/tools/lib/ai-provider.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Audio processing module for podcast generation.
3
+ * Uses FFmpeg to concatenate audio segments and get audio metadata.
4
+ *
5
+ * @module podcast/audio-processor
6
+ */
7
+ /**
8
+ * Concatenate multiple audio segments into a single audio file.
9
+ *
10
+ * @param segments - Array of audio data (Uint8Array, each should be MP3 format)
11
+ * @param outputFormat - Output format (default: "mp3")
12
+ * @returns Concatenated audio data
13
+ * @throws Error if segments array is empty or ffmpeg processing fails
14
+ *
15
+ * @example
16
+ * ```typescript
17
+ * const segments = [
18
+ * await textToSpeech("Hello", { voice: "alloy" }),
19
+ * await textToSpeech("World", { voice: "alloy" }),
20
+ * ];
21
+ * const combined = await concatenateAudio(segments);
22
+ * // combined is a single MP3 file
23
+ * ```
24
+ */
25
+ export declare function concatenateAudio(segments: Uint8Array[], outputFormat?: "mp3"): Promise<Uint8Array>;
26
+ /**
27
+ * Get the duration of an audio file in seconds.
28
+ *
29
+ * @param audio - Audio data (MP3 format)
30
+ * @returns Duration in seconds
31
+ * @throws Error if ffprobe fails to read the audio
32
+ */
33
+ export declare function getAudioDuration(audio: Uint8Array): Promise<number>;
34
+ /**
35
+ * Get audio metadata including duration and format information.
36
+ *
37
+ * @param audio - Audio data (MP3 format)
38
+ * @returns Audio metadata object
39
+ */
40
+ export declare function getAudioMetadata(audio: Uint8Array): Promise<{
41
+ duration: number;
42
+ format: string;
43
+ bitrate: number;
44
+ sampleRate: number;
45
+ }>;
46
+ //# sourceMappingURL=audio-processor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audio-processor.d.ts","sourceRoot":"","sources":["../../../src/tools/lib/audio-processor.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAyDH;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAsB,gBAAgB,CACpC,QAAQ,EAAE,UAAU,EAAE,EACtB,YAAY,GAAE,KAAa,GAC1B,OAAO,CAAC,UAAU,CAAC,CAqDrB;AAED;;;;;;GAMG;AACH,wBAAsB,gBAAgB,CAAC,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CAsBzE;AAED;;;;;GAKG;AACH,wBAAsB,gBAAgB,CAAC,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC;IACjE,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;CACpB,CAAC,CA6BD"}
@@ -0,0 +1,188 @@
1
+ /**
2
+ * Audio processing module for podcast generation.
3
+ * Uses FFmpeg to concatenate audio segments and get audio metadata.
4
+ *
5
+ * @module podcast/audio-processor
6
+ */
7
+ import ffmpeg from "fluent-ffmpeg";
8
+ import { tmpdir } from "node:os";
9
+ import { join } from "node:path";
10
+ import { writeFile, readFile, unlink, mkdir, rmdir } from "node:fs/promises";
11
+ import { randomUUID } from "node:crypto";
12
+ import ffmpegStatic from "ffmpeg-static";
13
+ let cachedFfmpegPath = null;
14
+ async function getFFmpegPath() {
15
+ if (!cachedFfmpegPath) {
16
+ const path = await Promise.resolve(ffmpegStatic);
17
+ cachedFfmpegPath = path || "ffmpeg";
18
+ }
19
+ return cachedFfmpegPath;
20
+ }
21
+ async function createTempDir() {
22
+ const workDir = join(tmpdir(), `podcast-${randomUUID()}`);
23
+ await mkdir(workDir, { recursive: true });
24
+ return workDir;
25
+ }
26
+ /**
27
+ * Clean up a temporary directory and its contents.
28
+ * @param dirPath - Path to the directory to clean up
29
+ */
30
+ async function cleanupTempDir(dirPath) {
31
+ try {
32
+ const files = await readFile(dirPath, "utf-8").catch(() => null);
33
+ if (files === null)
34
+ return;
35
+ // Remove all files in the directory
36
+ const entries = await import("node:fs/promises").then((fs) => fs.readdir(dirPath));
37
+ for (const entry of entries) {
38
+ try {
39
+ await unlink(join(dirPath, entry));
40
+ }
41
+ catch {
42
+ // Ignore errors when removing files
43
+ }
44
+ }
45
+ // Remove the directory
46
+ try {
47
+ await rmdir(dirPath);
48
+ }
49
+ catch {
50
+ // Ignore errors when removing directory
51
+ }
52
+ }
53
+ catch {
54
+ // Ignore all errors during cleanup
55
+ }
56
+ }
57
+ /**
58
+ * Concatenate multiple audio segments into a single audio file.
59
+ *
60
+ * @param segments - Array of audio data (Uint8Array, each should be MP3 format)
61
+ * @param outputFormat - Output format (default: "mp3")
62
+ * @returns Concatenated audio data
63
+ * @throws Error if segments array is empty or ffmpeg processing fails
64
+ *
65
+ * @example
66
+ * ```typescript
67
+ * const segments = [
68
+ * await textToSpeech("Hello", { voice: "alloy" }),
69
+ * await textToSpeech("World", { voice: "alloy" }),
70
+ * ];
71
+ * const combined = await concatenateAudio(segments);
72
+ * // combined is a single MP3 file
73
+ * ```
74
+ */
75
+ export async function concatenateAudio(segments, outputFormat = "mp3") {
76
+ // Validate input
77
+ if (segments.length === 0) {
78
+ throw new Error("No audio segments to concatenate");
79
+ }
80
+ // If only one segment, return it directly
81
+ if (segments.length === 1) {
82
+ return segments[0];
83
+ }
84
+ const workDir = await createTempDir();
85
+ const inputFiles = [];
86
+ const outputFile = join(workDir, `output.${outputFormat}`);
87
+ try {
88
+ // Write each segment to a temporary file
89
+ for (let i = 0; i < segments.length; i++) {
90
+ const inputFile = join(workDir, `segment-${i}.mp3`);
91
+ await writeFile(inputFile, segments[i]);
92
+ inputFiles.push(inputFile);
93
+ }
94
+ const ffmpegBin = await getFFmpegPath();
95
+ // Use ffmpeg to concatenate audio files
96
+ await new Promise((resolve, reject) => {
97
+ const command = ffmpeg();
98
+ command.setFfmpegPath(ffmpegBin);
99
+ // Add all input files
100
+ for (const file of inputFiles) {
101
+ command.input(file);
102
+ }
103
+ // Set up error and completion handlers
104
+ command
105
+ .on("error", (err) => {
106
+ reject(new Error(`FFmpeg error: ${err.message}`));
107
+ })
108
+ .on("end", () => {
109
+ resolve();
110
+ })
111
+ // Use mergeToFile for concatenating inputs
112
+ .mergeToFile(outputFile, workDir);
113
+ });
114
+ // Read the output file
115
+ return await readFile(outputFile);
116
+ }
117
+ finally {
118
+ // Clean up temporary files
119
+ await cleanupTempDir(workDir);
120
+ }
121
+ }
122
+ /**
123
+ * Get the duration of an audio file in seconds.
124
+ *
125
+ * @param audio - Audio data (MP3 format)
126
+ * @returns Duration in seconds
127
+ * @throws Error if ffprobe fails to read the audio
128
+ */
129
+ export async function getAudioDuration(audio) {
130
+ const workDir = await createTempDir();
131
+ const inputFile = join(workDir, "input.mp3");
132
+ try {
133
+ await writeFile(inputFile, audio);
134
+ const ffmpegBin = await getFFmpegPath();
135
+ return await new Promise((resolve, reject) => {
136
+ ffmpeg(inputFile)
137
+ .setFfmpegPath(ffmpegBin)
138
+ .ffprobe((err, data) => {
139
+ if (err) {
140
+ reject(new Error(`FFprobe error: ${err.message}`));
141
+ }
142
+ else {
143
+ resolve(data.format?.duration || 0);
144
+ }
145
+ });
146
+ });
147
+ }
148
+ finally {
149
+ await cleanupTempDir(workDir);
150
+ }
151
+ }
152
+ /**
153
+ * Get audio metadata including duration and format information.
154
+ *
155
+ * @param audio - Audio data (MP3 format)
156
+ * @returns Audio metadata object
157
+ */
158
+ export async function getAudioMetadata(audio) {
159
+ const workDir = await createTempDir();
160
+ const inputFile = join(workDir, "input.mp3");
161
+ try {
162
+ await writeFile(inputFile, audio);
163
+ const ffmpegBin = await getFFmpegPath();
164
+ return await new Promise((resolve, reject) => {
165
+ ffmpeg(inputFile)
166
+ .setFfmpegPath(ffmpegBin)
167
+ .ffprobe((err, data) => {
168
+ if (err) {
169
+ reject(new Error(`FFprobe error: ${err.message}`));
170
+ }
171
+ else {
172
+ resolve({
173
+ duration: data.format?.duration || 0,
174
+ format: data.format?.format_name || "unknown",
175
+ bitrate: data.format?.bit_rate
176
+ ? parseInt(String(data.format.bit_rate), 10)
177
+ : 0,
178
+ sampleRate: data.streams?.[0]?.sample_rate || 0,
179
+ });
180
+ }
181
+ });
182
+ });
183
+ }
184
+ finally {
185
+ await cleanupTempDir(workDir);
186
+ }
187
+ }
188
+ //# sourceMappingURL=audio-processor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audio-processor.js","sourceRoot":"","sources":["../../../src/tools/lib/audio-processor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Frontmatter 解析与更新工具
3
+ */
4
+ export interface FrontmatterResult {
5
+ raw: string;
6
+ body: string;
7
+ data: Record<string, unknown>;
8
+ }
9
+ export declare function extractFrontmatter(content: string): FrontmatterResult;
10
+ export declare function updateFrontmatterField(content: string, field: string, value: string | string[]): string;
11
+ //# sourceMappingURL=frontmatter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"frontmatter.d.ts","sourceRoot":"","sources":["../../../src/tools/lib/frontmatter.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,WAAW,iBAAiB;IAChC,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC/B;AAED,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,iBAAiB,CA8CrE;AAED,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,GACvB,MAAM,CA+BR"}
@@ -0,0 +1,80 @@
1
+ /**
2
+ * Frontmatter 解析与更新工具
3
+ */
4
+ export function extractFrontmatter(content) {
5
+ const match = content.match(/^(---\n[\s\S]*?\n---)\n?([\s\S]*)/);
6
+ if (!match)
7
+ return { raw: "", body: content, data: {} };
8
+ const raw = match[1];
9
+ const body = match[2];
10
+ const data = {};
11
+ const lines = raw.replace(/^---\n/, "").replace(/\n---$/, "").split("\n");
12
+ let currentKey = "";
13
+ let arrayValues = [];
14
+ let inArray = false;
15
+ for (const line of lines) {
16
+ if (inArray) {
17
+ if (line.match(/^\s+-\s+/)) {
18
+ arrayValues.push(line.replace(/^\s+-\s+/, "").trim());
19
+ continue;
20
+ }
21
+ else {
22
+ data[currentKey] = arrayValues;
23
+ inArray = false;
24
+ arrayValues = [];
25
+ }
26
+ }
27
+ const colonIndex = line.indexOf(":");
28
+ if (colonIndex === -1)
29
+ continue;
30
+ const key = line.slice(0, colonIndex).trim();
31
+ const value = line.slice(colonIndex + 1).trim();
32
+ if (value === "") {
33
+ currentKey = key;
34
+ inArray = true;
35
+ arrayValues = [];
36
+ continue;
37
+ }
38
+ if (value === "true")
39
+ data[key] = true;
40
+ else if (value === "false")
41
+ data[key] = false;
42
+ else
43
+ data[key] = value;
44
+ }
45
+ if (inArray)
46
+ data[currentKey] = arrayValues;
47
+ return { raw, body, data };
48
+ }
49
+ export function updateFrontmatterField(content, field, value) {
50
+ const lines = content.split("\n");
51
+ const closingIdx = lines.indexOf("---", 1);
52
+ if (closingIdx < 0)
53
+ return content;
54
+ const fieldRegex = new RegExp(`^${field}:`);
55
+ const existingIdx = lines.findIndex((l, i) => i > 0 && i < closingIdx && fieldRegex.test(l));
56
+ if (Array.isArray(value)) {
57
+ const yamlArray = value.map(v => ` - ${v}`).join("\n");
58
+ const newBlock = `${field}:\n${yamlArray}`;
59
+ if (existingIdx >= 0) {
60
+ let endIdx = existingIdx + 1;
61
+ while (endIdx < closingIdx && lines[endIdx].match(/^\s+-\s+/))
62
+ endIdx++;
63
+ lines.splice(existingIdx, endIdx - existingIdx, newBlock);
64
+ }
65
+ else {
66
+ lines.splice(closingIdx, 0, newBlock);
67
+ }
68
+ }
69
+ else {
70
+ const newLine = `${field}: ${value}`;
71
+ if (existingIdx >= 0) {
72
+ lines[existingIdx] = newLine;
73
+ }
74
+ else {
75
+ lines.splice(closingIdx, 0, newLine);
76
+ }
77
+ }
78
+ return lines.join("\n");
79
+ }
80
+ //# sourceMappingURL=frontmatter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"frontmatter.js","sourceRoot":"","sources":["../../../src/tools/lib/frontmatter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ export * from "./frontmatter.js";
2
+ export * from "./markdown.js";
3
+ export * from "./posts.js";
4
+ export * from "./ai-provider.js";
5
+ export * from "./vectors.js";
6
+ export * from "./utils.js";
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/tools/lib/index.ts"],"names":[],"mappings":"AAAA,cAAc,kBAAkB,CAAC;AACjC,cAAc,eAAe,CAAC;AAC9B,cAAc,YAAY,CAAC;AAC3B,cAAc,kBAAkB,CAAC;AACjC,cAAc,cAAc,CAAC;AAC7B,cAAc,YAAY,CAAC"}
@@ -4,3 +4,4 @@ export * from "./posts.js";
4
4
  export * from "./ai-provider.js";
5
5
  export * from "./vectors.js";
6
6
  export * from "./utils.js";
7
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/tools/lib/index.ts"],"names":[],"mappings":"AAAA,cAAc,kBAAkB,CAAC;AACjC,cAAc,eAAe,CAAC;AAC9B,cAAc,YAAY,CAAC;AAC3B,cAAc,kBAAkB,CAAC;AACjC,cAAc,cAAc,CAAC;AAC7B,cAAc,YAAY,CAAC"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Markdown 文本处理工具
3
+ */
4
+ export declare function stripMarkdown(content: string): string;
5
+ export declare function chunkText(text: string, size?: number, overlap?: number): string[];
6
+ //# sourceMappingURL=markdown.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"markdown.d.ts","sourceRoot":"","sources":["../../../src/tools/lib/markdown.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAgBrD;AAED,wBAAgB,SAAS,CACvB,IAAI,EAAE,MAAM,EACZ,IAAI,GAAE,MAAY,EAClB,OAAO,GAAE,MAAW,GACnB,MAAM,EAAE,CAaV"}
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Markdown 文本处理工具
3
+ */
4
+ export function stripMarkdown(content) {
5
+ return content
6
+ .replace(/^---[\s\S]*?---\n?/, "")
7
+ .replace(/^import\s+.*$/gm, "")
8
+ .replace(/<[^>]+\/>/g, "")
9
+ .replace(/<[^>]+>[\s\S]*?<\/[^>]+>/g, "")
10
+ .replace(/```[\s\S]*?```/g, "")
11
+ .replace(/`[^`]*`/g, "")
12
+ .replace(/!\[.*?\]\(.*?\)/g, "")
13
+ .replace(/\[([^\]]*)\]\(.*?\)/g, "$1")
14
+ .replace(/#{1,6}\s+/g, "")
15
+ .replace(/[*_~]+/g, "")
16
+ .replace(/^\s*[-*+]\s+/gm, "")
17
+ .replace(/^\s*\d+\.\s+/gm, "")
18
+ .replace(/\n{3,}/g, "\n\n")
19
+ .trim();
20
+ }
21
+ export function chunkText(text, size = 500, overlap = 50) {
22
+ const words = text.split(/\s+/);
23
+ const chunks = [];
24
+ for (let i = 0; i < words.length; i += size - overlap) {
25
+ const chunk = words.slice(i, i + size).join(" ");
26
+ if (chunk.trim().length > 20) {
27
+ chunks.push(chunk.trim());
28
+ }
29
+ if (i + size >= words.length)
30
+ break;
31
+ }
32
+ return chunks.length > 0 ? chunks : [text.slice(0, 2000)];
33
+ }
34
+ //# sourceMappingURL=markdown.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"markdown.js","sourceRoot":"","sources":["../../../src/tools/lib/markdown.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,UAAU,aAAa,CAAC,OAAe;IAC3C,OAAO,OAAO;SACX,OAAO,CAAC,oBAAoB,EAAE,EAAE,CAAC;SACjC,OAAO,CAAC,iBAAiB,EAAE,EAAE,CAAC;SAC9B,OAAO,CAAC,YAAY,EAAE,EAAE,CAAC;SACzB,OAAO,CAAC,2BAA2B,EAAE,EAAE,CAAC;SACxC,OAAO,CAAC,iBAAiB,EAAE,EAAE,CAAC;SAC9B,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC;SACvB,OAAO,CAAC,kBAAkB,EAAE,EAAE,CAAC;SAC/B,OAAO,CAAC,sBAAsB,EAAE,IAAI,CAAC;SACrC,OAAO,CAAC,YAAY,EAAE,EAAE,CAAC;SACzB,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC;SACtB,OAAO,CAAC,gBAAgB,EAAE,EAAE,CAAC;SAC7B,OAAO,CAAC,gBAAgB,EAAE,EAAE,CAAC;SAC7B,OAAO,CAAC,SAAS,EAAE,MAAM,CAAC;SAC1B,IAAI,EAAE,CAAC;AACZ,CAAC;AAED,MAAM,UAAU,SAAS,CACvB,IAAY,EACZ,OAAe,GAAG,EAClB,UAAkB,EAAE;IAEpB,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IAChC,MAAM,MAAM,GAAa,EAAE,CAAC;IAE5B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,IAAI,IAAI,GAAG,OAAO,EAAE,CAAC;QACtD,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACjD,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,EAAE,EAAE,CAAC;YAC7B,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;QAC5B,CAAC;QACD,IAAI,CAAC,GAAG,IAAI,IAAI,KAAK,CAAC,MAAM;YAAE,MAAM;IACtC,CAAC;IAED,OAAO,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC;AAC5D,CAAC"}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * 博客文章读取与遍历工具
3
+ */
4
+ export declare const BLOG_PATH: string;
5
+ export interface PostMeta {
6
+ id: string;
7
+ filePath: string;
8
+ lang: string;
9
+ title: string;
10
+ description: string;
11
+ tags: string[];
12
+ category: string;
13
+ body: string;
14
+ draft?: boolean;
15
+ }
16
+ export declare function getPostURL(id: string): string;
17
+ export declare function getAllPosts(opts?: {
18
+ includeDrafts?: boolean;
19
+ stripBody?: boolean;
20
+ }): Promise<PostMeta[]>;
21
+ export declare function getExistingTaxonomy(posts: PostMeta[]): {
22
+ tags: string[];
23
+ categories: string[];
24
+ };
25
+ //# sourceMappingURL=posts.d.ts.map