openclaw-github-trending 1.0.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 (75) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +480 -0
  3. package/dist/channels/email.d.ts +61 -0
  4. package/dist/channels/email.d.ts.map +1 -0
  5. package/dist/channels/email.js +599 -0
  6. package/dist/channels/email.js.map +1 -0
  7. package/dist/channels/feishu.d.ts +50 -0
  8. package/dist/channels/feishu.d.ts.map +1 -0
  9. package/dist/channels/feishu.js +322 -0
  10. package/dist/channels/feishu.js.map +1 -0
  11. package/dist/channels/types.d.ts +66 -0
  12. package/dist/channels/types.d.ts.map +1 -0
  13. package/dist/channels/types.js +12 -0
  14. package/dist/channels/types.js.map +1 -0
  15. package/dist/cli.d.ts +2 -0
  16. package/dist/cli.d.ts.map +1 -0
  17. package/dist/cli.js.map +1 -0
  18. package/dist/core/config.d.ts +83 -0
  19. package/dist/core/config.d.ts.map +1 -0
  20. package/dist/core/config.js +145 -0
  21. package/dist/core/config.js.map +1 -0
  22. package/dist/core/fetcher.d.ts +43 -0
  23. package/dist/core/fetcher.d.ts.map +1 -0
  24. package/dist/core/fetcher.js +306 -0
  25. package/dist/core/fetcher.js.map +1 -0
  26. package/dist/core/file-storage.d.ts +62 -0
  27. package/dist/core/file-storage.d.ts.map +1 -0
  28. package/dist/core/file-storage.js +253 -0
  29. package/dist/core/file-storage.js.map +1 -0
  30. package/dist/core/history.d.ts +71 -0
  31. package/dist/core/history.d.ts.map +1 -0
  32. package/dist/core/history.js +133 -0
  33. package/dist/core/history.js.map +1 -0
  34. package/dist/core/summarizer.d.ts +64 -0
  35. package/dist/core/summarizer.d.ts.map +1 -0
  36. package/dist/core/summarizer.js +324 -0
  37. package/dist/core/summarizer.js.map +1 -0
  38. package/dist/index.d.ts +2 -0
  39. package/dist/index.d.ts.map +1 -0
  40. package/dist/index.js +668 -0
  41. package/dist/index.js.map +1 -0
  42. package/dist/models/config.d.ts +93 -0
  43. package/dist/models/config.d.ts.map +1 -0
  44. package/dist/models/config.js +3 -0
  45. package/dist/models/config.js.map +1 -0
  46. package/dist/models/history.d.ts +6 -0
  47. package/dist/models/history.d.ts.map +1 -0
  48. package/dist/models/history.js +7 -0
  49. package/dist/models/history.js.map +1 -0
  50. package/dist/models/repository.d.ts +28 -0
  51. package/dist/models/repository.d.ts.map +1 -0
  52. package/dist/models/repository.js +3 -0
  53. package/dist/models/repository.js.map +1 -0
  54. package/dist/models/service.types.d.ts +87 -0
  55. package/dist/models/service.types.d.ts.map +1 -0
  56. package/dist/models/service.types.js +3 -0
  57. package/dist/models/service.types.js.map +1 -0
  58. package/dist/services/trending.service.d.ts +29 -0
  59. package/dist/services/trending.service.d.ts.map +1 -0
  60. package/dist/services/trending.service.js +306 -0
  61. package/dist/services/trending.service.js.map +1 -0
  62. package/dist/tool.d.ts +47 -0
  63. package/dist/tool.d.ts.map +1 -0
  64. package/dist/tool.js +314 -0
  65. package/dist/tool.js.map +1 -0
  66. package/dist/utils/logger.d.ts +77 -0
  67. package/dist/utils/logger.d.ts.map +1 -0
  68. package/dist/utils/logger.js +214 -0
  69. package/dist/utils/logger.js.map +1 -0
  70. package/dist/utils/markdown.d.ts +9 -0
  71. package/dist/utils/markdown.d.ts.map +1 -0
  72. package/dist/utils/markdown.js +40 -0
  73. package/dist/utils/markdown.js.map +1 -0
  74. package/openclaw.plugin.json +152 -0
  75. package/package.json +78 -0
package/dist/tool.js ADDED
@@ -0,0 +1,314 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.githubTrendingTool = exports.HistoryManager = void 0;
4
+ const fetcher_1 = require("./core/fetcher");
5
+ const summarizer_1 = require("./core/summarizer");
6
+ const history_1 = require("./core/history");
7
+ Object.defineProperty(exports, "HistoryManager", { enumerable: true, get: function () { return history_1.HistoryManager; } });
8
+ const feishu_1 = require("./channels/feishu");
9
+ const email_1 = require("./channels/email");
10
+ const config_1 = require("./core/config");
11
+ /**
12
+ * Process repositories with AI summaries concurrently
13
+ * @param repositories Repositories to process
14
+ * @param summarizer AISummarizer instance
15
+ * @param maxWorkers Maximum concurrent workers
16
+ * @returns Repositories with AI summaries
17
+ */
18
+ async function processRepositoriesWithAI(repositories, summarizer, maxWorkers = 5) {
19
+ const results = [];
20
+ // Use configured max workers, cap at 10 to avoid overwhelming the API
21
+ const actualMaxWorkers = Math.min(maxWorkers, 10);
22
+ // Process in batches to limit concurrency
23
+ for (let i = 0; i < repositories.length; i += actualMaxWorkers) {
24
+ const batch = repositories.slice(i, i + actualMaxWorkers);
25
+ console.log(`[AI Summarizer] Processing batch ${Math.floor(i / actualMaxWorkers) + 1}/${Math.ceil(repositories.length / actualMaxWorkers)} (${batch.length} repos with ${actualMaxWorkers} workers)...`);
26
+ // Use Promise.allSettled to handle individual failures gracefully
27
+ const batchResults = await Promise.allSettled(batch.map(async (repo) => {
28
+ try {
29
+ // Add timeout for each summary request (3 minutes max to match OpenClaw CLI limit)
30
+ const startTime = Date.now();
31
+ const summary = await Promise.race([
32
+ summarizer.generateSummary(repo),
33
+ new Promise((_, reject) => setTimeout(() => reject(new Error('Summary timeout')), 180000))
34
+ ]);
35
+ const duration = Date.now() - startTime;
36
+ console.log(`✅ ${repo.full_name} summary generated (${duration}ms, ${summary.length} chars)`);
37
+ return { ...repo, ai_summary: summary };
38
+ }
39
+ catch (error) {
40
+ console.log(`⚠️ ${repo.full_name} 摘要生成失败:${error instanceof Error ? error.message : 'Unknown error'}`);
41
+ return { ...repo, ai_summary: '' };
42
+ }
43
+ }));
44
+ // Collect successful results
45
+ for (const result of batchResults) {
46
+ if (result.status === 'fulfilled') {
47
+ results.push(result.value);
48
+ }
49
+ }
50
+ }
51
+ return results;
52
+ }
53
+ /**
54
+ * Main handler for GitHub Trending Tool
55
+ */
56
+ async function githubTrendingHandler(params, pluginConfig = {}, openclawConfig = {}, historyData) {
57
+ console.log('\n[GitHub Trending Tool] Handler called');
58
+ console.log('[GitHub Trending Tool] pluginConfig:', JSON.stringify(pluginConfig, null, 2));
59
+ console.log('[GitHub Trending Tool] pluginConfig.proxy:', pluginConfig.proxy);
60
+ console.log('[GitHub Trending Tool] params:', params);
61
+ console.log('[GitHub Trending Tool] openclawConfig available:', !!openclawConfig);
62
+ const { since, channels, email_to, feishu_webhook } = params;
63
+ // 解析通道配置(仅使用 channels 参数)
64
+ const targetChannels = channels || [];
65
+ if (targetChannels.length === 0) {
66
+ return {
67
+ success: false,
68
+ pushed_count: 0,
69
+ new_count: 0,
70
+ seen_count: 0,
71
+ total_count: 0,
72
+ pushed_to: '',
73
+ timestamp: new Date().toISOString(),
74
+ message: '请指定至少一个推送通道:channels 参数'
75
+ };
76
+ }
77
+ // Step 1: Resolve AI configuration with fallback logic
78
+ const aiConfig = config_1.ConfigManager.getAIConfig(pluginConfig, openclawConfig);
79
+ const summarizer = new summarizer_1.AISummarizer(aiConfig);
80
+ // Step 2: Initialize fetcher and fetch trending repositories
81
+ const fetcher = new fetcher_1.GitHubFetcher(pluginConfig);
82
+ let repositories;
83
+ try {
84
+ repositories = await fetcher.fetchTrending(since);
85
+ }
86
+ catch (error) {
87
+ return {
88
+ success: false,
89
+ pushed_count: 0,
90
+ new_count: 0,
91
+ seen_count: 0,
92
+ total_count: 0,
93
+ pushed_to: targetChannels.join(','),
94
+ timestamp: new Date().toISOString(),
95
+ message: `Failed to fetch trending: ${error instanceof Error ? error.message : 'Unknown error'}`
96
+ };
97
+ }
98
+ // Step 3: Initialize history manager and separate new/seen repositories
99
+ const historyManager = new history_1.HistoryManager();
100
+ if (historyData) {
101
+ historyManager.importData(historyData);
102
+ }
103
+ // Categorize repositories with proper history config from plugin
104
+ const historyConfig = {
105
+ enabled: pluginConfig?.history?.enabled ?? true,
106
+ star_threshold: pluginConfig?.history?.star_threshold ?? 100
107
+ };
108
+ const historyStatsBefore = historyManager.getStats();
109
+ console.log('[History Manager] Configuration:', JSON.stringify(historyConfig, null, 2));
110
+ console.log('[History Manager] History loaded from storage:', historyData ? '✅ Yes' : '❌ No');
111
+ console.log('[History Manager] Total repositories in history:', Object.keys(historyManager['data'].repositories).length);
112
+ console.log('[History Manager] Statistics before processing:');
113
+ console.log(` - Total repositories tracked: ${historyStatsBefore.total_repositories}`);
114
+ console.log(` - Total pushes: ${historyStatsBefore.total_pushes}`);
115
+ console.log(` - Oldest entry: ${historyStatsBefore.oldest_entry || 'N/A'}`);
116
+ console.log(` - Newest entry: ${historyStatsBefore.newest_entry || 'N/A'}`);
117
+ const { newlySeen, shouldPush, alreadySeen } = historyManager.categorizeRepositories(repositories, historyConfig);
118
+ console.log(`[History Manager] Results - New: ${newlySeen.length}, Should Push: ${shouldPush.length}, Already Seen: ${alreadySeen.length}`);
119
+ if (newlySeen.length > 0) {
120
+ console.log('[History Manager] Newly seen repositories:');
121
+ newlySeen.forEach((repo, i) => console.log(` ${i + 1}. ${repo.full_name} (${repo.stars} stars)`));
122
+ }
123
+ if (alreadySeen.length > 0) {
124
+ console.log('[History Manager] Already seen repositories:');
125
+ alreadySeen.forEach((repo, i) => {
126
+ const history = historyManager.getProject(repo.full_name);
127
+ const starsDiff = repo.stars - (history?.last_stars || 0);
128
+ console.log(` ${i + 1}. ${repo.full_name} (${repo.stars} stars, +${starsDiff} since last push)`);
129
+ });
130
+ }
131
+ // Step 4: Get max workers from config and generate AI summaries for repositories to push
132
+ const maxWorkers = config_1.ConfigManager.getMaxWorkers(pluginConfig);
133
+ console.log(`[AI Summarizer] Using ${maxWorkers} concurrent workers for ${shouldPush.length} repositories`);
134
+ let processedRepositories = [];
135
+ const startTime = Date.now();
136
+ try {
137
+ processedRepositories = await processRepositoriesWithAI(shouldPush, summarizer, maxWorkers);
138
+ }
139
+ catch (error) {
140
+ // Continue with empty summaries if AI processing fails
141
+ processedRepositories = shouldPush.map((r) => ({ ...r, ai_summary: '' }));
142
+ }
143
+ const summaryDuration = Date.now() - startTime;
144
+ console.log(`[AI Summarizer] ✅ All summaries generated in ${summaryDuration}ms (${summaryDuration / shouldPush.length}ms per repo on average)`);
145
+ // Update history
146
+ historyManager.markPushed(processedRepositories);
147
+ // Prepare seen repositories with AI summaries from history (skip AI generation)
148
+ const seenReposWithSummary = alreadySeen.map((r) => {
149
+ const history = historyManager.getProject(r.full_name);
150
+ const summary = history?.ai_summary || '';
151
+ if (summary) {
152
+ console.log(`[History Manager] ✅ Using cached summary for ${r.full_name} (${summary.length} chars)`);
153
+ }
154
+ else {
155
+ console.log(`[History Manager] ⚠️ No cached summary for ${r.full_name}`);
156
+ }
157
+ return {
158
+ ...r,
159
+ ai_summary: summary
160
+ };
161
+ });
162
+ // Display summary statistics
163
+ console.log(`\n[Summary Statistics]`);
164
+ console.log(` - New repositories processed with AI: ${processedRepositories.length}`);
165
+ console.log(` - Already seen repositories (using cached summaries): ${alreadySeen.length}`);
166
+ console.log(` - Total repositories to push: ${processedRepositories.length}`);
167
+ console.log(` - Total repositories shown: ${processedRepositories.length + alreadySeen.length}`);
168
+ // Step 5: Push to each channel
169
+ const pushResults = [];
170
+ const pushLogs = []; // 收集推送日志
171
+ // Display history statistics
172
+ const historyStats = historyManager.getStats();
173
+ console.log('\n[History Statistics]');
174
+ console.log(` - Total repositories tracked: ${historyStats.total_repositories}`);
175
+ console.log(` - Total pushes: ${historyStats.total_pushes}`);
176
+ console.log(` - Oldest entry: ${historyStats.oldest_entry || 'N/A'}`);
177
+ console.log(` - Newest entry: ${historyStats.newest_entry || 'N/A'}`);
178
+ for (const targetChannel of targetChannels) {
179
+ try {
180
+ if (targetChannel === 'feishu') {
181
+ const webhookUrl = feishu_webhook || pluginConfig?.channels?.feishu?.webhook_url;
182
+ if (!webhookUrl) {
183
+ pushResults.push({ channel: 'feishu', success: false, error: 'Feishu webhook URL not provided' });
184
+ pushLogs.push('[Feishu Channel] ❌ 推送失败: Feishu webhook URL not provided');
185
+ continue;
186
+ }
187
+ const result = await feishu_1.FeishuChannel.push(webhookUrl, processedRepositories, seenReposWithSummary);
188
+ pushResults.push({
189
+ channel: 'feishu',
190
+ success: result.success,
191
+ messageId: result.messageId,
192
+ error: result.error
193
+ });
194
+ pushLogs.push(`[Feishu Channel] ${result.success ? '✅ 推送成功' : '❌ 推送失败'}${result.error ? ': ' + result.error : ''}`);
195
+ }
196
+ else if (targetChannel === 'email') {
197
+ const emailTo = email_to || pluginConfig?.channels?.email?.recipient || pluginConfig?.channels?.email?.sender;
198
+ if (!emailTo) {
199
+ pushResults.push({ channel: 'email', success: false, error: 'Email recipient not provided' });
200
+ pushLogs.push('[Email Channel] ❌ 推送失败: Email recipient not provided');
201
+ continue;
202
+ }
203
+ // Detect email configuration
204
+ const emailConfig = config_1.ConfigManager.getEmailConfig(emailTo, pluginConfig?.channels?.email?.password || '', pluginConfig?.channels?.email);
205
+ const internalEmailConfig = {
206
+ from: emailConfig.sender,
207
+ to: emailTo,
208
+ subject: `GitHub ${since === 'daily' ? '今日' : since === 'weekly' ? '本周' : '本月'}热榜推送`,
209
+ smtp: {
210
+ host: emailConfig.smtp_host,
211
+ port: emailConfig.smtp_port,
212
+ secure: false, // Use STARTTLS
213
+ auth: {
214
+ user: emailConfig.sender,
215
+ pass: emailConfig.password
216
+ }
217
+ }
218
+ };
219
+ const result = await email_1.EmailChannel.send(internalEmailConfig, processedRepositories, seenReposWithSummary, since);
220
+ pushResults.push({
221
+ channel: 'email',
222
+ success: result.success,
223
+ messageId: result.messageId,
224
+ error: result.error
225
+ });
226
+ pushLogs.push(`[Email Channel] ${result.success ? '✅ 推送成功' : '❌ 推送失败'}${result.error ? ': ' + result.error : ''}`);
227
+ }
228
+ }
229
+ catch (error) {
230
+ pushResults.push({
231
+ channel: targetChannel,
232
+ success: false,
233
+ error: error instanceof Error ? error.message : 'Unknown error'
234
+ });
235
+ pushLogs.push(`[${targetChannel} Channel] ❌ 推送失败: ${error instanceof Error ? error.message : 'Unknown error'}`);
236
+ }
237
+ }
238
+ // 统一输出推送日志在最后
239
+ console.log('\n========== 推送结果汇总 ==========');
240
+ pushLogs.forEach(log => console.log(log));
241
+ console.log('====================================\n');
242
+ // Step 6: Return result
243
+ const successCount = pushResults.filter(r => r.success).length;
244
+ const failedChannels = pushResults.filter(r => !r.success).map(r => r.channel);
245
+ const successChannels = pushResults.filter(r => r.success).map(r => r.channel);
246
+ // 构建详细的消息
247
+ let message = '';
248
+ if (successCount === targetChannels.length) {
249
+ message = `成功推送到所有 ${successCount} 个通道`;
250
+ }
251
+ else if (successCount > 0) {
252
+ const failedDetails = pushResults
253
+ .filter(r => !r.success)
254
+ .map(r => `${r.channel}: ${r.error}`)
255
+ .join(', ');
256
+ message = `部分成功:${successCount}/${targetChannels.length} 个通道推送成功,失败:${failedDetails}`;
257
+ }
258
+ else {
259
+ const failedDetails = pushResults
260
+ .filter(r => !r.success)
261
+ .map(r => `${r.channel}: ${r.error}`)
262
+ .join(', ');
263
+ message = `所有通道推送失败:${failedDetails}`;
264
+ }
265
+ return {
266
+ success: successCount > 0,
267
+ pushed_count: processedRepositories.length,
268
+ new_count: newlySeen.length,
269
+ seen_count: alreadySeen.length,
270
+ total_count: repositories.length,
271
+ pushed_to: successChannels.join(','),
272
+ timestamp: new Date().toISOString(),
273
+ message,
274
+ history_data: historyManager.exportData() // Return updated history for persistence
275
+ };
276
+ }
277
+ /**
278
+ * Export the GitHub Trending Tool
279
+ */
280
+ exports.githubTrendingTool = {
281
+ name: 'openclaw-github-trending',
282
+ description: 'Fetch GitHub trending repositories and push to Feishu or Email',
283
+ parameters: {
284
+ type: 'object',
285
+ properties: {
286
+ since: {
287
+ type: 'string',
288
+ enum: ['daily', 'weekly', 'monthly'],
289
+ description: 'Time period for trending'
290
+ },
291
+ channels: {
292
+ type: 'array',
293
+ items: {
294
+ type: 'string',
295
+ enum: ['feishu', 'email']
296
+ },
297
+ description: 'Push channels (array: ["email"], ["feishu"], or ["email", "feishu"])'
298
+ },
299
+ email_to: {
300
+ type: 'string',
301
+ format: 'email',
302
+ description: 'Email recipient (required for email channel)'
303
+ },
304
+ feishu_webhook: {
305
+ type: 'string',
306
+ description: 'Feishu webhook URL (required for feishu channel)'
307
+ }
308
+ },
309
+ required: ['since']
310
+ },
311
+ handler: githubTrendingHandler
312
+ };
313
+ exports.default = exports.githubTrendingTool;
314
+ //# sourceMappingURL=tool.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tool.js","sourceRoot":"","sources":["../src/tool.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,77 @@
1
+ /**
2
+ * Unified Logger with Console + File support
3
+ *
4
+ * Features:
5
+ * - Console logging with timestamp, prefix, and level
6
+ * - File logging to ~/.openclaw/logs/github-trending/trending-YYYY-MM.log
7
+ * - Single instance per module (prefix-based)
8
+ * - Static methods for convenience
9
+ * - Unified log format
10
+ */
11
+ export declare class Logger {
12
+ private static instances;
13
+ private prefix;
14
+ private logDir;
15
+ private enabled;
16
+ private logLevel;
17
+ constructor(prefix?: string);
18
+ /**
19
+ * Get logger instance for a specific module
20
+ * Singleton per prefix
21
+ */
22
+ static get(prefix: string): Logger;
23
+ /**
24
+ * Set minimum log level (default: INFO)
25
+ */
26
+ setLogLevel(level: LogLevel): void;
27
+ /**
28
+ * Get log file path (monthly rotation)
29
+ */
30
+ private getLogFilePath;
31
+ /**
32
+ * Format argument for logging
33
+ */
34
+ private formatArg;
35
+ /**
36
+ * Check if log level is enabled
37
+ */
38
+ private isLevelEnabled;
39
+ /**
40
+ * Format message with timestamp and prefix
41
+ */
42
+ private formatMessage;
43
+ /**
44
+ * Write to file
45
+ */
46
+ private logToFile;
47
+ /**
48
+ * Internal log method
49
+ */
50
+ private log;
51
+ debug(message: string, ...args: any[]): void;
52
+ info(message: string, ...args: any[]): void;
53
+ success(message: string, ...args: any[]): void;
54
+ warn(message: string, ...args: any[]): void;
55
+ error(message: string | Error, ...args: any[]): void;
56
+ /**
57
+ * Get the logger prefix (for testing)
58
+ */
59
+ getPrefix(): string;
60
+ /**
61
+ * Create a timer function for measuring execution time
62
+ */
63
+ timer(operation: string): () => number;
64
+ static debug(message: string, ...args: any[]): void;
65
+ static info(message: string, ...args: any[]): void;
66
+ static success(message: string, ...args: any[]): void;
67
+ static warn(message: string, ...args: any[]): void;
68
+ static error(message: string | Error, ...args: any[]): void;
69
+ }
70
+ export declare enum LogLevel {
71
+ DEBUG = "debug",
72
+ INFO = "info",
73
+ WARN = "warn",
74
+ ERROR = "error",
75
+ SUCCESS = "success"
76
+ }
77
+ //# sourceMappingURL=logger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":"AAIA;;;;;;;;;GASG;AACH,qBAAa,MAAM;IACjB,OAAO,CAAC,MAAM,CAAC,SAAS,CAAkC;IAC1D,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,OAAO,CAAiB;IAChC,OAAO,CAAC,QAAQ,CAA2B;gBAE/B,MAAM,GAAE,MAAc;IAkBlC;;;OAGG;IACH,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM;IAOlC;;OAEG;IACH,WAAW,CAAC,KAAK,EAAE,QAAQ,GAAG,IAAI;IAIlC;;OAEG;IACH,OAAO,CAAC,cAAc;IAOtB;;OAEG;IACH,OAAO,CAAC,SAAS;IAajB;;OAEG;IACH,OAAO,CAAC,cAAc;IAWtB;;OAEG;IACH,OAAO,CAAC,aAAa;IAYrB;;OAEG;IACH,OAAO,CAAC,SAAS;IAWjB;;OAEG;IACH,OAAO,CAAC,GAAG;IA8BX,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,IAAI;IAI5C,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,IAAI;IAI3C,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,IAAI;IAO9C,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,IAAI;IAI3C,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,KAAK,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,IAAI;IAQpD;;OAEG;IACH,SAAS,IAAI,MAAM;IAInB;;OAEG;IACH,KAAK,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,MAAM;IAWtC,MAAM,CAAC,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,IAAI;IAInD,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,IAAI;IAIlD,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,IAAI;IAIrD,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,IAAI;IAIlD,MAAM,CAAC,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,KAAK,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,IAAI;CAG5D;AAED,oBAAY,QAAQ;IAClB,KAAK,UAAU;IACf,IAAI,SAAS;IACb,IAAI,SAAS;IACb,KAAK,UAAU;IACf,OAAO,YAAY;CACpB"}
@@ -0,0 +1,214 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.LogLevel = exports.Logger = void 0;
7
+ const fs_1 = __importDefault(require("fs"));
8
+ const path_1 = __importDefault(require("path"));
9
+ const os_1 = __importDefault(require("os"));
10
+ /**
11
+ * Unified Logger with Console + File support
12
+ *
13
+ * Features:
14
+ * - Console logging with timestamp, prefix, and level
15
+ * - File logging to ~/.openclaw/logs/github-trending/trending-YYYY-MM.log
16
+ * - Single instance per module (prefix-based)
17
+ * - Static methods for convenience
18
+ * - Unified log format
19
+ */
20
+ class Logger {
21
+ constructor(prefix = 'App') {
22
+ this.enabled = true;
23
+ this.logLevel = LogLevel.INFO;
24
+ this.prefix = `[${prefix}]`;
25
+ this.logDir = ''; // Initialize
26
+ // Setup log directory (same as old FileLogger)
27
+ try {
28
+ const openclawDataDir = process.env.OPENCLAW_DATA_DIR || path_1.default.join(os_1.default.homedir(), '.openclaw');
29
+ this.logDir = path_1.default.join(openclawDataDir, 'logs', 'github-trending');
30
+ if (!fs_1.default.existsSync(this.logDir)) {
31
+ fs_1.default.mkdirSync(this.logDir, { recursive: true });
32
+ }
33
+ }
34
+ catch (error) {
35
+ console.error('[Logger] Failed to create log directory:', error);
36
+ this.enabled = false;
37
+ }
38
+ }
39
+ /**
40
+ * Get logger instance for a specific module
41
+ * Singleton per prefix
42
+ */
43
+ static get(prefix) {
44
+ if (!Logger.instances.has(prefix)) {
45
+ Logger.instances.set(prefix, new Logger(prefix));
46
+ }
47
+ return Logger.instances.get(prefix);
48
+ }
49
+ /**
50
+ * Set minimum log level (default: INFO)
51
+ */
52
+ setLogLevel(level) {
53
+ this.logLevel = level;
54
+ }
55
+ /**
56
+ * Get log file path (monthly rotation)
57
+ */
58
+ getLogFilePath() {
59
+ const date = new Date();
60
+ const year = date.getFullYear();
61
+ const month = String(date.getMonth() + 1).padStart(2, '0');
62
+ return path_1.default.join(this.logDir, `trending-${year}-${month}.log`);
63
+ }
64
+ /**
65
+ * Format argument for logging
66
+ */
67
+ formatArg(arg) {
68
+ if (arg instanceof Error) {
69
+ return arg.message + (arg.stack ? `\n${arg.stack}` : '');
70
+ }
71
+ if (typeof arg === 'object') {
72
+ return JSON.stringify(arg, null, 2);
73
+ }
74
+ if (typeof arg === 'function') {
75
+ return '[Function]';
76
+ }
77
+ return String(arg);
78
+ }
79
+ /**
80
+ * Check if log level is enabled
81
+ */
82
+ isLevelEnabled(level) {
83
+ const levelOrder = {
84
+ [LogLevel.DEBUG]: 0,
85
+ [LogLevel.INFO]: 1,
86
+ [LogLevel.WARN]: 2,
87
+ [LogLevel.ERROR]: 3,
88
+ [LogLevel.SUCCESS]: 1, // Same as INFO for filtering
89
+ };
90
+ return levelOrder[level] >= levelOrder[this.logLevel];
91
+ }
92
+ /**
93
+ * Format message with timestamp and prefix
94
+ */
95
+ formatMessage(level, message, args) {
96
+ const timestamp = new Date().toISOString();
97
+ const levelStr = level.toString().toUpperCase();
98
+ let formattedMessage = `${timestamp} ${this.prefix} [${levelStr}] ${message}`;
99
+ if (args && args.length > 0) {
100
+ formattedMessage += ' ' + args.map(arg => this.formatArg(arg)).join(' ');
101
+ }
102
+ return formattedMessage;
103
+ }
104
+ /**
105
+ * Write to file
106
+ */
107
+ logToFile(message) {
108
+ if (!this.enabled)
109
+ return;
110
+ try {
111
+ const logFilePath = this.getLogFilePath();
112
+ fs_1.default.appendFileSync(logFilePath, message + '\n', 'utf8');
113
+ }
114
+ catch (error) {
115
+ // Fail silently - don't crash the app if logging fails
116
+ }
117
+ }
118
+ /**
119
+ * Internal log method
120
+ */
121
+ log(level, message, ...args) {
122
+ if (!this.isLevelEnabled(level))
123
+ return;
124
+ const formattedMessage = this.formatMessage(level, message, args);
125
+ // Console output with color
126
+ switch (level) {
127
+ case LogLevel.DEBUG:
128
+ console.log(formattedMessage);
129
+ break;
130
+ case LogLevel.INFO:
131
+ console.log(formattedMessage);
132
+ break;
133
+ case LogLevel.WARN:
134
+ console.warn(formattedMessage);
135
+ break;
136
+ case LogLevel.ERROR:
137
+ console.error(formattedMessage);
138
+ break;
139
+ case LogLevel.SUCCESS:
140
+ console.log(formattedMessage); // Green color in terminal
141
+ break;
142
+ }
143
+ // File logging
144
+ this.logToFile(formattedMessage);
145
+ }
146
+ // Public logging methods
147
+ debug(message, ...args) {
148
+ this.log(LogLevel.DEBUG, message, ...args);
149
+ }
150
+ info(message, ...args) {
151
+ this.log(LogLevel.INFO, message, ...args);
152
+ }
153
+ success(message, ...args) {
154
+ const successMsg = message.includes('✅') || message.includes('succeed')
155
+ ? message
156
+ : `✅ ${message}`;
157
+ this.log(LogLevel.SUCCESS, successMsg, ...args);
158
+ }
159
+ warn(message, ...args) {
160
+ this.log(LogLevel.WARN, message, ...args);
161
+ }
162
+ error(message, ...args) {
163
+ if (message instanceof Error) {
164
+ this.log(LogLevel.ERROR, message.message, [message, ...args]);
165
+ }
166
+ else {
167
+ this.log(LogLevel.ERROR, message, ...args);
168
+ }
169
+ }
170
+ /**
171
+ * Get the logger prefix (for testing)
172
+ */
173
+ getPrefix() {
174
+ return this.prefix;
175
+ }
176
+ /**
177
+ * Create a timer function for measuring execution time
178
+ */
179
+ timer(operation) {
180
+ const startTime = Date.now();
181
+ return () => {
182
+ const elapsed = Date.now() - startTime;
183
+ this.info(`${operation} completed in ${elapsed}ms`);
184
+ return elapsed;
185
+ };
186
+ }
187
+ // Static convenience methods (uses 'App' as default prefix)
188
+ static debug(message, ...args) {
189
+ Logger.get('App').debug(message, ...args);
190
+ }
191
+ static info(message, ...args) {
192
+ Logger.get('App').info(message, ...args);
193
+ }
194
+ static success(message, ...args) {
195
+ Logger.get('App').success(message, ...args);
196
+ }
197
+ static warn(message, ...args) {
198
+ Logger.get('App').warn(message, ...args);
199
+ }
200
+ static error(message, ...args) {
201
+ Logger.get('App').error(message, ...args);
202
+ }
203
+ }
204
+ exports.Logger = Logger;
205
+ Logger.instances = new Map();
206
+ var LogLevel;
207
+ (function (LogLevel) {
208
+ LogLevel["DEBUG"] = "debug";
209
+ LogLevel["INFO"] = "info";
210
+ LogLevel["WARN"] = "warn";
211
+ LogLevel["ERROR"] = "error";
212
+ LogLevel["SUCCESS"] = "success";
213
+ })(LogLevel || (exports.LogLevel = LogLevel = {}));
214
+ //# sourceMappingURL=logger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Convert markdown text to HTML
3
+ * This function sanitizes the output to prevent XSS attacks
4
+ *
5
+ * @param markdown - Markdown text to convert
6
+ * @returns Sanitized HTML string
7
+ */
8
+ export declare function markdownToHTML(markdown: string): string;
9
+ //# sourceMappingURL=markdown.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"markdown.d.ts","sourceRoot":"","sources":["../../src/utils/markdown.ts"],"names":[],"mappings":"AAGA;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAyBvD"}