@timmeck/brain-core 2.36.12 → 2.36.14

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 (125) hide show
  1. package/dist/cross-brain/__tests__/borg-sync-engine.test.d.ts +1 -0
  2. package/dist/cross-brain/__tests__/borg-sync-engine.test.js +240 -0
  3. package/dist/cross-brain/__tests__/borg-sync-engine.test.js.map +1 -0
  4. package/dist/cross-brain/borg-sync-engine.d.ts +62 -0
  5. package/dist/cross-brain/borg-sync-engine.js +215 -0
  6. package/dist/cross-brain/borg-sync-engine.js.map +1 -0
  7. package/dist/cross-brain/borg-types.d.ts +37 -0
  8. package/dist/cross-brain/borg-types.js +9 -0
  9. package/dist/cross-brain/borg-types.js.map +1 -0
  10. package/dist/embeddings/engine.js +2 -1
  11. package/dist/embeddings/engine.js.map +1 -1
  12. package/dist/index.d.ts +18 -1
  13. package/dist/index.js +14 -0
  14. package/dist/index.js.map +1 -1
  15. package/dist/llm/__tests__/anthropic-provider.test.d.ts +1 -0
  16. package/dist/llm/__tests__/anthropic-provider.test.js +121 -0
  17. package/dist/llm/__tests__/anthropic-provider.test.js.map +1 -0
  18. package/dist/llm/__tests__/llm-service.test.js +181 -40
  19. package/dist/llm/__tests__/llm-service.test.js.map +1 -1
  20. package/dist/llm/__tests__/ollama-embedding.test.d.ts +1 -0
  21. package/dist/llm/__tests__/ollama-embedding.test.js +128 -0
  22. package/dist/llm/__tests__/ollama-embedding.test.js.map +1 -0
  23. package/dist/llm/__tests__/ollama-provider.test.d.ts +1 -0
  24. package/dist/llm/__tests__/ollama-provider.test.js +213 -0
  25. package/dist/llm/__tests__/ollama-provider.test.js.map +1 -0
  26. package/dist/llm/__tests__/provider.test.d.ts +1 -0
  27. package/dist/llm/__tests__/provider.test.js +126 -0
  28. package/dist/llm/__tests__/provider.test.js.map +1 -0
  29. package/dist/llm/anthropic-provider.d.ts +41 -0
  30. package/dist/llm/anthropic-provider.js +86 -0
  31. package/dist/llm/anthropic-provider.js.map +1 -0
  32. package/dist/llm/index.d.ts +9 -1
  33. package/dist/llm/index.js +4 -0
  34. package/dist/llm/index.js.map +1 -1
  35. package/dist/llm/llm-service.d.ts +55 -7
  36. package/dist/llm/llm-service.js +184 -82
  37. package/dist/llm/llm-service.js.map +1 -1
  38. package/dist/llm/ollama-embedding.d.ts +46 -0
  39. package/dist/llm/ollama-embedding.js +93 -0
  40. package/dist/llm/ollama-embedding.js.map +1 -0
  41. package/dist/llm/ollama-provider.d.ts +80 -0
  42. package/dist/llm/ollama-provider.js +178 -0
  43. package/dist/llm/ollama-provider.js.map +1 -0
  44. package/dist/llm/provider.d.ts +120 -0
  45. package/dist/llm/provider.js +104 -0
  46. package/dist/llm/provider.js.map +1 -0
  47. package/dist/missions/mission-engine.d.ts +4 -0
  48. package/dist/missions/mission-engine.js +30 -8
  49. package/dist/missions/mission-engine.js.map +1 -1
  50. package/dist/notifications/__tests__/notification-service.test.d.ts +1 -0
  51. package/dist/notifications/__tests__/notification-service.test.js +176 -0
  52. package/dist/notifications/__tests__/notification-service.test.js.map +1 -0
  53. package/dist/notifications/discord-provider.d.ts +30 -0
  54. package/dist/notifications/discord-provider.js +89 -0
  55. package/dist/notifications/discord-provider.js.map +1 -0
  56. package/dist/notifications/email-provider.d.ts +41 -0
  57. package/dist/notifications/email-provider.js +101 -0
  58. package/dist/notifications/email-provider.js.map +1 -0
  59. package/dist/notifications/index.d.ts +8 -0
  60. package/dist/notifications/index.js +5 -0
  61. package/dist/notifications/index.js.map +1 -0
  62. package/dist/notifications/notification-provider.d.ts +75 -0
  63. package/dist/notifications/notification-provider.js +47 -0
  64. package/dist/notifications/notification-provider.js.map +1 -0
  65. package/dist/notifications/notification-service.d.ts +85 -0
  66. package/dist/notifications/notification-service.js +184 -0
  67. package/dist/notifications/notification-service.js.map +1 -0
  68. package/dist/notifications/telegram-provider.d.ts +30 -0
  69. package/dist/notifications/telegram-provider.js +78 -0
  70. package/dist/notifications/telegram-provider.js.map +1 -0
  71. package/dist/plugin/__tests__/plugin-registry.test.d.ts +1 -0
  72. package/dist/plugin/__tests__/plugin-registry.test.js +166 -0
  73. package/dist/plugin/__tests__/plugin-registry.test.js.map +1 -0
  74. package/dist/plugin/plugin-registry.d.ts +38 -0
  75. package/dist/plugin/plugin-registry.js +185 -0
  76. package/dist/plugin/plugin-registry.js.map +1 -0
  77. package/dist/plugin/types.d.ts +59 -0
  78. package/dist/plugin/types.js +2 -0
  79. package/dist/plugin/types.js.map +1 -0
  80. package/dist/research/adapters/__tests__/web-adapters.test.d.ts +1 -0
  81. package/dist/research/adapters/__tests__/web-adapters.test.js +106 -0
  82. package/dist/research/adapters/__tests__/web-adapters.test.js.map +1 -0
  83. package/dist/research/adapters/firecrawl-adapter.d.ts +57 -0
  84. package/dist/research/adapters/firecrawl-adapter.js +137 -0
  85. package/dist/research/adapters/firecrawl-adapter.js.map +1 -0
  86. package/dist/research/adapters/index.d.ts +3 -0
  87. package/dist/research/adapters/index.js +2 -0
  88. package/dist/research/adapters/index.js.map +1 -1
  89. package/dist/research/adapters/playwright-adapter.d.ts +54 -0
  90. package/dist/research/adapters/playwright-adapter.js +130 -0
  91. package/dist/research/adapters/playwright-adapter.js.map +1 -0
  92. package/dist/research/research-orchestrator.d.ts +3 -0
  93. package/dist/research/research-orchestrator.js +19 -1
  94. package/dist/research/research-orchestrator.js.map +1 -1
  95. package/dist/techradar/__tests__/techradar-engine.test.d.ts +1 -0
  96. package/dist/techradar/__tests__/techradar-engine.test.js +246 -0
  97. package/dist/techradar/__tests__/techradar-engine.test.js.map +1 -0
  98. package/dist/techradar/daily-digest.d.ts +18 -0
  99. package/dist/techradar/daily-digest.js +100 -0
  100. package/dist/techradar/daily-digest.js.map +1 -0
  101. package/dist/techradar/index.d.ts +5 -0
  102. package/dist/techradar/index.js +5 -0
  103. package/dist/techradar/index.js.map +1 -0
  104. package/dist/techradar/relevance-scorer.d.ts +29 -0
  105. package/dist/techradar/relevance-scorer.js +139 -0
  106. package/dist/techradar/relevance-scorer.js.map +1 -0
  107. package/dist/techradar/repo-watcher.d.ts +24 -0
  108. package/dist/techradar/repo-watcher.js +87 -0
  109. package/dist/techradar/repo-watcher.js.map +1 -0
  110. package/dist/techradar/techradar-engine.d.ts +69 -0
  111. package/dist/techradar/techradar-engine.js +382 -0
  112. package/dist/techradar/techradar-engine.js.map +1 -0
  113. package/dist/techradar/types.d.ts +87 -0
  114. package/dist/techradar/types.js +5 -0
  115. package/dist/techradar/types.js.map +1 -0
  116. package/dist/watchdog/__tests__/watchdog-service.test.d.ts +1 -0
  117. package/dist/watchdog/__tests__/watchdog-service.test.js +113 -0
  118. package/dist/watchdog/__tests__/watchdog-service.test.js.map +1 -0
  119. package/dist/watchdog/watchdog-service.d.ts +60 -0
  120. package/dist/watchdog/watchdog-service.js +275 -0
  121. package/dist/watchdog/watchdog-service.js.map +1 -0
  122. package/dist/watchdog/windows-service.d.ts +39 -0
  123. package/dist/watchdog/windows-service.js +179 -0
  124. package/dist/watchdog/windows-service.js.map +1 -0
  125. package/package.json +20 -2
@@ -0,0 +1,246 @@
1
+ import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
2
+ import Database from 'better-sqlite3';
3
+ vi.mock('../../utils/logger.js', () => ({
4
+ getLogger: () => ({
5
+ info: vi.fn(), warn: vi.fn(), error: vi.fn(), debug: vi.fn(),
6
+ }),
7
+ }));
8
+ import { TechRadarEngine } from '../techradar-engine.js';
9
+ import { RelevanceScorer } from '../relevance-scorer.js';
10
+ import { DigestGenerator } from '../daily-digest.js';
11
+ function createDb() {
12
+ return new Database(':memory:');
13
+ }
14
+ describe('TechRadarEngine', () => {
15
+ let db;
16
+ beforeEach(() => {
17
+ db = createDb();
18
+ });
19
+ afterEach(() => {
20
+ db.close();
21
+ });
22
+ describe('constructor', () => {
23
+ it('creates tables on init', () => {
24
+ const engine = new TechRadarEngine(db);
25
+ const tables = db.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name LIKE 'techradar_%'").all();
26
+ const names = tables.map(t => t.name);
27
+ expect(names).toContain('techradar_entries');
28
+ expect(names).toContain('techradar_watched_repos');
29
+ expect(names).toContain('techradar_digests');
30
+ });
31
+ it('seeds default watched repos', () => {
32
+ const engine = new TechRadarEngine(db);
33
+ const repos = engine.getWatchedRepos();
34
+ expect(repos.length).toBeGreaterThanOrEqual(3);
35
+ expect(repos.some(r => r.full_name === 'anthropics/claude-code')).toBe(true);
36
+ });
37
+ it('accepts custom config', () => {
38
+ const engine = new TechRadarEngine(db, {
39
+ watchedRepos: ['my/repo'],
40
+ relevanceThreshold: 50,
41
+ });
42
+ const repos = engine.getWatchedRepos();
43
+ expect(repos.some(r => r.full_name === 'my/repo')).toBe(true);
44
+ });
45
+ });
46
+ describe('watched repos', () => {
47
+ it('adds and removes repos', () => {
48
+ const engine = new TechRadarEngine(db, { watchedRepos: [] });
49
+ engine.addWatchedRepo('test/repo', 'testing');
50
+ expect(engine.getWatchedRepos()).toHaveLength(1);
51
+ engine.removeWatchedRepo('test/repo');
52
+ expect(engine.getWatchedRepos()).toHaveLength(0);
53
+ });
54
+ it('prevents duplicates', () => {
55
+ const engine = new TechRadarEngine(db, { watchedRepos: [] });
56
+ engine.addWatchedRepo('test/repo');
57
+ engine.addWatchedRepo('test/repo');
58
+ expect(engine.getWatchedRepos()).toHaveLength(1);
59
+ });
60
+ });
61
+ describe('entries', () => {
62
+ it('returns entries filtered by minScore', () => {
63
+ const engine = new TechRadarEngine(db, { watchedRepos: [] });
64
+ // Insert entries directly
65
+ db.prepare(`
66
+ INSERT INTO techradar_entries (name, source, source_url, category, ring, description, relevance_score, is_active)
67
+ VALUES (?, ?, ?, ?, ?, ?, ?, 1)
68
+ `).run('high-score', 'github_trending', 'https://example.com', 'library', 'adopt', 'A high-score lib', 80);
69
+ db.prepare(`
70
+ INSERT INTO techradar_entries (name, source, source_url, category, ring, description, relevance_score, is_active)
71
+ VALUES (?, ?, ?, ?, ?, ?, ?, 1)
72
+ `).run('low-score', 'github_trending', 'https://example.com', 'library', 'hold', 'A low-score lib', 10);
73
+ const highOnly = engine.getEntries({ minScore: 50 });
74
+ expect(highOnly).toHaveLength(1);
75
+ expect(highOnly[0].name).toBe('high-score');
76
+ const all = engine.getEntries();
77
+ expect(all).toHaveLength(2);
78
+ });
79
+ it('returns entries filtered by source', () => {
80
+ const engine = new TechRadarEngine(db, { watchedRepos: [] });
81
+ db.prepare(`
82
+ INSERT INTO techradar_entries (name, source, source_url, category, ring, description, relevance_score, is_active)
83
+ VALUES (?, ?, ?, ?, ?, ?, ?, 1)
84
+ `).run('release', 'github_release', 'url', 'library', 'trial', 'A release', 60);
85
+ db.prepare(`
86
+ INSERT INTO techradar_entries (name, source, source_url, category, ring, description, relevance_score, is_active)
87
+ VALUES (?, ?, ?, ?, ?, ?, ?, 1)
88
+ `).run('trending', 'github_trending', 'url', 'tool', 'assess', 'Trending', 50);
89
+ const releases = engine.getEntries({ source: 'github_release' });
90
+ expect(releases).toHaveLength(1);
91
+ expect(releases[0].name).toBe('release');
92
+ });
93
+ });
94
+ describe('digest', () => {
95
+ it('generates and retrieves digest', async () => {
96
+ const engine = new TechRadarEngine(db, { watchedRepos: [], relevanceThreshold: 0 });
97
+ // Insert some entries
98
+ db.prepare(`
99
+ INSERT INTO techradar_entries (name, source, source_url, category, ring, description, relevance_score, action_type, action_detail, is_active)
100
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, 1)
101
+ `).run('cool-lib', 'github_trending', 'url', 'library', 'trial', 'A cool library for AI', 75, 'investigate', 'Check it out');
102
+ const digest = await engine.generateDigest('2026-03-06');
103
+ expect(digest.date).toBe('2026-03-06');
104
+ expect(digest.entries.length).toBeGreaterThan(0);
105
+ expect(digest.summary).toBeTruthy();
106
+ // Retrieve
107
+ const stored = engine.getDigest('2026-03-06');
108
+ expect(stored).not.toBeNull();
109
+ expect(stored.date).toBe('2026-03-06');
110
+ });
111
+ it('returns null for missing digest', () => {
112
+ const engine = new TechRadarEngine(db, { watchedRepos: [] });
113
+ expect(engine.getDigest('2099-01-01')).toBeNull();
114
+ });
115
+ });
116
+ describe('stats', () => {
117
+ it('returns stats', () => {
118
+ const engine = new TechRadarEngine(db, { watchedRepos: ['a/b'] });
119
+ const stats = engine.getStats();
120
+ expect(stats.totalEntries).toBe(0);
121
+ expect(stats.watchedRepos).toBe(1);
122
+ expect(stats.bySource).toEqual({});
123
+ });
124
+ });
125
+ describe('start / stop', () => {
126
+ it('starts and stops without error', () => {
127
+ const engine = new TechRadarEngine(db, { watchedRepos: [], scanIntervalMs: 999999 });
128
+ engine.start();
129
+ engine.stop();
130
+ });
131
+ it('start is idempotent', () => {
132
+ const engine = new TechRadarEngine(db, { watchedRepos: [], scanIntervalMs: 999999 });
133
+ engine.start();
134
+ engine.start(); // Should not throw
135
+ engine.stop();
136
+ });
137
+ });
138
+ describe('importFromSignalScanner', () => {
139
+ it('imports from scanned_repos if table exists', async () => {
140
+ // Create a mock scanned_repos table
141
+ db.exec(`
142
+ CREATE TABLE scanned_repos (
143
+ id INTEGER PRIMARY KEY,
144
+ full_name TEXT NOT NULL,
145
+ url TEXT NOT NULL,
146
+ description TEXT,
147
+ language TEXT,
148
+ topics TEXT DEFAULT '[]',
149
+ current_stars INTEGER DEFAULT 0,
150
+ signal_score REAL DEFAULT 0,
151
+ signal_level TEXT DEFAULT 'noise',
152
+ star_velocity_24h INTEGER DEFAULT 0,
153
+ is_active INTEGER DEFAULT 1
154
+ )
155
+ `);
156
+ db.prepare(`
157
+ INSERT INTO scanned_repos (full_name, url, description, language, topics, current_stars, signal_score, signal_level, star_velocity_24h, is_active)
158
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, 1)
159
+ `).run('cool/mcp-server', 'https://github.com/cool/mcp-server', 'An MCP server for TypeScript', 'TypeScript', '["mcp","typescript"]', 500, 75, 'breakout', 50);
160
+ const engine = new TechRadarEngine(db, { watchedRepos: [], relevanceThreshold: 10 });
161
+ const result = await engine.scan();
162
+ // Should import the breakout repo (mcp + typescript keywords match)
163
+ expect(result.new_entries).toBeGreaterThanOrEqual(0); // May or may not match threshold
164
+ });
165
+ });
166
+ });
167
+ describe('RelevanceScorer', () => {
168
+ it('scores with keywords', () => {
169
+ const scorer = new RelevanceScorer();
170
+ const result = scorer.scoreKeywords('mcp-typescript-sdk', 'A TypeScript SDK for Model Context Protocol with SQLite support');
171
+ expect(result.score).toBeGreaterThan(20);
172
+ });
173
+ it('scores zero for irrelevant content', () => {
174
+ const scorer = new RelevanceScorer();
175
+ const result = scorer.scoreKeywords('recipe-app', 'A mobile app for sharing cooking recipes');
176
+ expect(result.score).toBe(0);
177
+ });
178
+ it('categorizes correctly', () => {
179
+ const scorer = new RelevanceScorer();
180
+ const result = scorer.scoreKeywords('gpt-4o', 'A new LLM model from OpenAI');
181
+ expect(result.category).toBe('ai_model');
182
+ });
183
+ it('assigns ring based on score', () => {
184
+ const scorer = new RelevanceScorer();
185
+ // This should score high with multiple keyword matches
186
+ const high = scorer.scoreKeywords('mcp-ollama-claude', 'MCP server with Ollama and Claude for TypeScript embeddings and SQLite');
187
+ expect(high.score).toBeGreaterThan(40);
188
+ expect(['adopt', 'trial']).toContain(high.ring);
189
+ });
190
+ });
191
+ describe('DigestGenerator', () => {
192
+ it('generates fallback digest without LLM', async () => {
193
+ const gen = new DigestGenerator();
194
+ const entries = [
195
+ {
196
+ name: 'test-lib',
197
+ source: 'github_trending',
198
+ source_url: 'url',
199
+ category: 'library',
200
+ ring: 'trial',
201
+ description: 'A test library',
202
+ relevance_score: 60,
203
+ relevance_reason: 'keyword match',
204
+ action_type: 'investigate',
205
+ action_detail: 'Check it out',
206
+ first_seen_at: new Date().toISOString(),
207
+ last_seen_at: new Date().toISOString(),
208
+ is_active: true,
209
+ },
210
+ ];
211
+ const digest = await gen.generate(entries, '2026-03-06');
212
+ expect(digest.date).toBe('2026-03-06');
213
+ expect(digest.summary).toContain('2026-03-06');
214
+ expect(digest.entries).toHaveLength(1);
215
+ });
216
+ it('handles empty entries', async () => {
217
+ const gen = new DigestGenerator();
218
+ const digest = await gen.generate([], '2026-03-06');
219
+ expect(digest.entries).toHaveLength(0);
220
+ expect(digest.summary).toContain('No new findings');
221
+ });
222
+ it('extracts action items from high-score entries', async () => {
223
+ const gen = new DigestGenerator();
224
+ const entries = [
225
+ {
226
+ name: 'important-update',
227
+ source: 'github_release',
228
+ source_url: 'url',
229
+ category: 'library',
230
+ ring: 'adopt',
231
+ description: 'Critical update',
232
+ relevance_score: 80,
233
+ relevance_reason: 'high relevance',
234
+ action_type: 'update',
235
+ action_detail: 'Update to v2.0',
236
+ first_seen_at: new Date().toISOString(),
237
+ last_seen_at: new Date().toISOString(),
238
+ is_active: true,
239
+ },
240
+ ];
241
+ const digest = await gen.generate(entries, '2026-03-06');
242
+ expect(digest.action_items.length).toBeGreaterThan(0);
243
+ expect(digest.opportunities.length).toBeGreaterThan(0);
244
+ });
245
+ });
246
+ //# sourceMappingURL=techradar-engine.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"techradar-engine.test.js","sourceRoot":"","sources":["../../../src/techradar/__tests__/techradar-engine.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Daily Digest — Generiert tägliche Zusammenfassung der TechRadar-Findings
3
+ */
4
+ import type { LLMService } from '../llm/llm-service.js';
5
+ import type { TechRadarEntry, DailyDigest } from './types.js';
6
+ export declare class DigestGenerator {
7
+ private llmService;
8
+ setLLMService(llmService: LLMService): void;
9
+ /**
10
+ * Generate a daily digest from today's radar entries.
11
+ * Uses LLM for summary when available, otherwise creates structured report.
12
+ */
13
+ generate(entries: TechRadarEntry[], date: string): Promise<DailyDigest>;
14
+ private generateLLMSummary;
15
+ private generateFallbackSummary;
16
+ private extractOpportunities;
17
+ private extractActionItems;
18
+ }
@@ -0,0 +1,100 @@
1
+ /**
2
+ * Daily Digest — Generiert tägliche Zusammenfassung der TechRadar-Findings
3
+ */
4
+ import { getLogger } from '../utils/logger.js';
5
+ const log = getLogger();
6
+ export class DigestGenerator {
7
+ llmService = null;
8
+ setLLMService(llmService) {
9
+ this.llmService = llmService;
10
+ }
11
+ /**
12
+ * Generate a daily digest from today's radar entries.
13
+ * Uses LLM for summary when available, otherwise creates structured report.
14
+ */
15
+ async generate(entries, date) {
16
+ const digestEntries = entries
17
+ .sort((a, b) => b.relevance_score - a.relevance_score)
18
+ .slice(0, 20)
19
+ .map(e => ({
20
+ name: e.name,
21
+ source: e.source,
22
+ category: e.category,
23
+ relevance_score: e.relevance_score,
24
+ summary: e.description.substring(0, 200),
25
+ }));
26
+ const opportunities = this.extractOpportunities(entries);
27
+ const actionItems = this.extractActionItems(entries);
28
+ let summary;
29
+ if (this.llmService && entries.length > 0) {
30
+ try {
31
+ summary = await this.generateLLMSummary(entries, date);
32
+ }
33
+ catch (err) {
34
+ log.warn(`[Digest] LLM summary failed: ${err.message}`);
35
+ summary = this.generateFallbackSummary(entries, date);
36
+ }
37
+ }
38
+ else {
39
+ summary = this.generateFallbackSummary(entries, date);
40
+ }
41
+ return {
42
+ date,
43
+ summary,
44
+ entries: digestEntries,
45
+ opportunities,
46
+ action_items: actionItems,
47
+ created_at: new Date().toISOString(),
48
+ };
49
+ }
50
+ async generateLLMSummary(entries, date) {
51
+ const topEntries = entries
52
+ .sort((a, b) => b.relevance_score - a.relevance_score)
53
+ .slice(0, 10)
54
+ .map(e => `- ${e.name} (${e.source}, relevance: ${e.relevance_score}): ${e.description.substring(0, 100)}`)
55
+ .join('\n');
56
+ const result = await this.llmService.call('summarize', `Write a concise daily tech digest for ${date}. Focus on what matters for a TypeScript AI project (Brain Ecosystem).
57
+
58
+ Top findings today:
59
+ ${topEntries}
60
+
61
+ Write 3-5 sentences highlighting the most important developments and their implications. Be direct, no fluff.`);
62
+ return result?.text ?? this.generateFallbackSummary(entries, date);
63
+ }
64
+ generateFallbackSummary(entries, date) {
65
+ if (entries.length === 0)
66
+ return `No new findings for ${date}.`;
67
+ const high = entries.filter(e => e.relevance_score >= 60);
68
+ const bySource = new Map();
69
+ for (const e of entries) {
70
+ bySource.set(e.source, (bySource.get(e.source) ?? 0) + 1);
71
+ }
72
+ const sourceSummary = [...bySource.entries()]
73
+ .map(([s, c]) => `${c} from ${s}`)
74
+ .join(', ');
75
+ return `TechRadar Digest for ${date}: ${entries.length} findings (${sourceSummary}). ${high.length} high-relevance items found.`;
76
+ }
77
+ extractOpportunities(entries) {
78
+ return entries
79
+ .filter(e => e.action_type === 'integrate' || e.action_type === 'update')
80
+ .slice(0, 5)
81
+ .map(e => ({
82
+ title: `${e.action_type === 'integrate' ? 'Integrate' : 'Update'}: ${e.name}`,
83
+ description: e.action_detail || e.description.substring(0, 200),
84
+ effort: e.relevance_score >= 70 ? 'low' : 'medium',
85
+ impact: e.relevance_score >= 70 ? 'high' : 'medium',
86
+ }));
87
+ }
88
+ extractActionItems(entries) {
89
+ return entries
90
+ .filter(e => e.action_type !== 'none' && e.relevance_score >= 40)
91
+ .sort((a, b) => b.relevance_score - a.relevance_score)
92
+ .slice(0, 10)
93
+ .map(e => ({
94
+ action: e.action_detail || `${e.action_type}: ${e.name}`,
95
+ priority: e.relevance_score >= 70 ? 'high' : e.relevance_score >= 50 ? 'medium' : 'low',
96
+ related_entry: e.name,
97
+ }));
98
+ }
99
+ }
100
+ //# sourceMappingURL=daily-digest.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"daily-digest.js","sourceRoot":"","sources":["../../src/techradar/daily-digest.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ export { TechRadarEngine, runTechRadarMigration } from './techradar-engine.js';
2
+ export { RepoWatcher } from './repo-watcher.js';
3
+ export { RelevanceScorer } from './relevance-scorer.js';
4
+ export { DigestGenerator } from './daily-digest.js';
5
+ export type { TechRadarConfig, TechRadarEntry, TechRadarScanResult, TechRadarSource, TechRadarCategory, TechRadarRing, TechRadarAction, WatchedRepo, RepoRelease, DailyDigest, DigestEntry, DigestOpportunity, DigestActionItem, } from './types.js';
@@ -0,0 +1,5 @@
1
+ export { TechRadarEngine, runTechRadarMigration } from './techradar-engine.js';
2
+ export { RepoWatcher } from './repo-watcher.js';
3
+ export { RelevanceScorer } from './relevance-scorer.js';
4
+ export { DigestGenerator } from './daily-digest.js';
5
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/techradar/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAC/E,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC"}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Relevance Scorer — LLM-basiertes Scoring für TechRadar Entries
3
+ *
4
+ * Bewertet: "Ist das relevant für das Brain Ecosystem?"
5
+ * Nutzt LLMService wenn verfügbar, sonst Keyword-basiertes Fallback.
6
+ */
7
+ import type { LLMService } from '../llm/llm-service.js';
8
+ import type { TechRadarCategory, TechRadarRing, TechRadarAction } from './types.js';
9
+ export interface RelevanceResult {
10
+ score: number;
11
+ reason: string;
12
+ category: TechRadarCategory;
13
+ ring: TechRadarRing;
14
+ action: TechRadarAction;
15
+ actionDetail: string;
16
+ }
17
+ export declare class RelevanceScorer {
18
+ private llmService;
19
+ setLLMService(llmService: LLMService): void;
20
+ /**
21
+ * Score how relevant a finding is for the Brain Ecosystem.
22
+ * Uses LLM when available, keyword fallback otherwise.
23
+ */
24
+ score(name: string, description: string, source: string): Promise<RelevanceResult>;
25
+ private scoreLLM;
26
+ /** Keyword-based fallback scoring */
27
+ scoreKeywords(name: string, description: string): RelevanceResult;
28
+ private inferCategory;
29
+ }
@@ -0,0 +1,139 @@
1
+ /**
2
+ * Relevance Scorer — LLM-basiertes Scoring für TechRadar Entries
3
+ *
4
+ * Bewertet: "Ist das relevant für das Brain Ecosystem?"
5
+ * Nutzt LLMService wenn verfügbar, sonst Keyword-basiertes Fallback.
6
+ */
7
+ import { getLogger } from '../utils/logger.js';
8
+ const log = getLogger();
9
+ // Keywords die auf Relevanz für Brain Ecosystem hindeuten
10
+ const RELEVANCE_KEYWORDS = {
11
+ // Direct relevance
12
+ 'mcp': 15, 'model context protocol': 15, 'claude': 12, 'anthropic': 12,
13
+ 'llm': 10, 'ai agent': 10, 'ai assistant': 8,
14
+ // Tech stack
15
+ 'typescript': 8, 'node': 5, 'sqlite': 8, 'better-sqlite3': 12,
16
+ 'vitest': 8, 'eslint': 5, 'monorepo': 6,
17
+ // Domains
18
+ 'trading bot': 10, 'paper trading': 12, 'crypto': 6, 'defi': 5,
19
+ 'marketing automation': 10, 'content strategy': 8, 'social media api': 8,
20
+ // Concepts
21
+ 'embeddings': 8, 'vector': 6, 'rag': 8, 'retrieval augmented': 8,
22
+ 'self-modifying': 10, 'metacognition': 10, 'knowledge graph': 8,
23
+ 'websocket': 6, 'real-time': 5, 'ipc': 6,
24
+ // Tools
25
+ 'ollama': 10, 'ccxt': 10, 'playwright': 8, 'discord.js': 6,
26
+ 'bluesky': 8, 'atproto': 8,
27
+ };
28
+ export class RelevanceScorer {
29
+ llmService = null;
30
+ setLLMService(llmService) {
31
+ this.llmService = llmService;
32
+ }
33
+ /**
34
+ * Score how relevant a finding is for the Brain Ecosystem.
35
+ * Uses LLM when available, keyword fallback otherwise.
36
+ */
37
+ async score(name, description, source) {
38
+ // Try LLM first
39
+ if (this.llmService) {
40
+ try {
41
+ return await this.scoreLLM(name, description, source);
42
+ }
43
+ catch (err) {
44
+ log.warn(`[RelevanceScorer] LLM scoring failed, using keyword fallback: ${err.message}`);
45
+ }
46
+ }
47
+ return this.scoreKeywords(name, description);
48
+ }
49
+ async scoreLLM(name, description, source) {
50
+ const prompt = `Analyze this technology finding for relevance to the "Brain Ecosystem" project.
51
+
52
+ The Brain Ecosystem is a TypeScript monorepo with:
53
+ - brain-core: shared infra (IPC, MCP server, SQLite, math, synapses, LLM integration)
54
+ - brain: error memory & code intelligence
55
+ - trading-brain: paper trading with signal learning (CCXT, CoinGecko)
56
+ - marketing-brain: content strategy & engagement learning (Bluesky, Reddit)
57
+
58
+ Tech stack: TypeScript, Node.js, better-sqlite3, Vitest, MCP protocol, Ollama, Anthropic Claude
59
+
60
+ Finding:
61
+ Name: ${name}
62
+ Source: ${source}
63
+ Description: ${description}
64
+
65
+ Respond in JSON format:
66
+ {
67
+ "score": <0-100 relevance score>,
68
+ "reason": "<one sentence why relevant or not>",
69
+ "category": "<framework|library|tool|language|platform|technique|ai_model|crypto|other>",
70
+ "ring": "<adopt|trial|assess|hold>",
71
+ "action": "<integrate|update|investigate|monitor|none>",
72
+ "actionDetail": "<specific recommendation>"
73
+ }`;
74
+ const result = await this.llmService.call('custom', prompt);
75
+ if (!result) {
76
+ throw new Error('LLM returned null');
77
+ }
78
+ try {
79
+ // Extract JSON from response
80
+ const jsonMatch = result.text.match(/\{[\s\S]*\}/);
81
+ if (!jsonMatch)
82
+ throw new Error('No JSON in response');
83
+ const parsed = JSON.parse(jsonMatch[0]);
84
+ return {
85
+ score: Math.max(0, Math.min(100, parsed.score ?? 0)),
86
+ reason: parsed.reason ?? 'No reason provided',
87
+ category: parsed.category ?? 'other',
88
+ ring: parsed.ring ?? 'assess',
89
+ action: parsed.action ?? 'monitor',
90
+ actionDetail: parsed.actionDetail ?? '',
91
+ };
92
+ }
93
+ catch {
94
+ throw new Error('Failed to parse LLM response as JSON');
95
+ }
96
+ }
97
+ /** Keyword-based fallback scoring */
98
+ scoreKeywords(name, description) {
99
+ const text = `${name} ${description}`.toLowerCase();
100
+ let score = 0;
101
+ for (const [keyword, weight] of Object.entries(RELEVANCE_KEYWORDS)) {
102
+ if (text.includes(keyword.toLowerCase())) {
103
+ score += weight;
104
+ }
105
+ }
106
+ // Cap at 100
107
+ score = Math.min(100, score);
108
+ // Determine category from keywords
109
+ const category = this.inferCategory(text);
110
+ const ring = score >= 70 ? 'adopt' : score >= 50 ? 'trial' : score >= 30 ? 'assess' : 'hold';
111
+ const action = score >= 60 ? 'investigate' : score >= 40 ? 'monitor' : 'none';
112
+ return {
113
+ score,
114
+ reason: score > 0 ? `Keyword matches: relevance ${score}/100` : 'No relevant keywords found',
115
+ category,
116
+ ring,
117
+ action,
118
+ actionDetail: action === 'investigate' ? `Look into ${name} for potential integration` : '',
119
+ };
120
+ }
121
+ inferCategory(text) {
122
+ if (text.includes('framework') || text.includes('react') || text.includes('next'))
123
+ return 'framework';
124
+ if (text.includes('model') || text.includes('llm') || text.includes('gpt') || text.includes('claude'))
125
+ return 'ai_model';
126
+ if (text.includes('tool') || text.includes('cli') || text.includes('editor'))
127
+ return 'tool';
128
+ if (text.includes('language') || text.includes('rust') || text.includes('zig'))
129
+ return 'language';
130
+ if (text.includes('platform') || text.includes('cloud') || text.includes('aws'))
131
+ return 'platform';
132
+ if (text.includes('crypto') || text.includes('defi') || text.includes('blockchain'))
133
+ return 'crypto';
134
+ if (text.includes('technique') || text.includes('pattern') || text.includes('algorithm'))
135
+ return 'technique';
136
+ return 'library';
137
+ }
138
+ }
139
+ //# sourceMappingURL=relevance-scorer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"relevance-scorer.js","sourceRoot":"","sources":["../../src/techradar/relevance-scorer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Repo Watcher — Überwacht GitHub Repos auf neue Releases/Changelogs
3
+ *
4
+ * Einrichten:
5
+ * Braucht GITHUB_TOKEN in .env für höheres Rate Limit (optional, 60 req/h ohne).
6
+ * Repos hinzufügen:
7
+ * brain techradar repos add anthropics/claude-code
8
+ * brain techradar repos add modelcontextprotocol/servers
9
+ */
10
+ import type { WatchedRepo, RepoRelease } from './types.js';
11
+ export declare class RepoWatcher {
12
+ private readonly githubToken;
13
+ constructor(githubToken?: string);
14
+ /**
15
+ * Check a repo for new releases since the last known tag.
16
+ * Returns new releases (newest first).
17
+ */
18
+ checkReleases(repo: WatchedRepo): Promise<RepoRelease[]>;
19
+ /**
20
+ * Fetch the CHANGELOG.md or CHANGES.md from a repo.
21
+ * Returns the content or null if not found.
22
+ */
23
+ fetchChangelog(repoFullName: string): Promise<string | null>;
24
+ }