@timmeck/brain-core 2.36.11 → 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.
- package/dist/cross-brain/__tests__/borg-sync-engine.test.d.ts +1 -0
- package/dist/cross-brain/__tests__/borg-sync-engine.test.js +240 -0
- package/dist/cross-brain/__tests__/borg-sync-engine.test.js.map +1 -0
- package/dist/cross-brain/borg-sync-engine.d.ts +62 -0
- package/dist/cross-brain/borg-sync-engine.js +215 -0
- package/dist/cross-brain/borg-sync-engine.js.map +1 -0
- package/dist/cross-brain/borg-types.d.ts +37 -0
- package/dist/cross-brain/borg-types.js +9 -0
- package/dist/cross-brain/borg-types.js.map +1 -0
- package/dist/embeddings/engine.js +2 -1
- package/dist/embeddings/engine.js.map +1 -1
- package/dist/index.d.ts +18 -1
- package/dist/index.js +14 -0
- package/dist/index.js.map +1 -1
- package/dist/llm/__tests__/anthropic-provider.test.d.ts +1 -0
- package/dist/llm/__tests__/anthropic-provider.test.js +121 -0
- package/dist/llm/__tests__/anthropic-provider.test.js.map +1 -0
- package/dist/llm/__tests__/llm-service.test.js +181 -40
- package/dist/llm/__tests__/llm-service.test.js.map +1 -1
- package/dist/llm/__tests__/ollama-embedding.test.d.ts +1 -0
- package/dist/llm/__tests__/ollama-embedding.test.js +128 -0
- package/dist/llm/__tests__/ollama-embedding.test.js.map +1 -0
- package/dist/llm/__tests__/ollama-provider.test.d.ts +1 -0
- package/dist/llm/__tests__/ollama-provider.test.js +213 -0
- package/dist/llm/__tests__/ollama-provider.test.js.map +1 -0
- package/dist/llm/__tests__/provider.test.d.ts +1 -0
- package/dist/llm/__tests__/provider.test.js +126 -0
- package/dist/llm/__tests__/provider.test.js.map +1 -0
- package/dist/llm/anthropic-provider.d.ts +41 -0
- package/dist/llm/anthropic-provider.js +86 -0
- package/dist/llm/anthropic-provider.js.map +1 -0
- package/dist/llm/index.d.ts +9 -1
- package/dist/llm/index.js +4 -0
- package/dist/llm/index.js.map +1 -1
- package/dist/llm/llm-service.d.ts +55 -7
- package/dist/llm/llm-service.js +184 -82
- package/dist/llm/llm-service.js.map +1 -1
- package/dist/llm/ollama-embedding.d.ts +46 -0
- package/dist/llm/ollama-embedding.js +93 -0
- package/dist/llm/ollama-embedding.js.map +1 -0
- package/dist/llm/ollama-provider.d.ts +80 -0
- package/dist/llm/ollama-provider.js +178 -0
- package/dist/llm/ollama-provider.js.map +1 -0
- package/dist/llm/provider.d.ts +120 -0
- package/dist/llm/provider.js +104 -0
- package/dist/llm/provider.js.map +1 -0
- package/dist/missions/mission-engine.d.ts +4 -0
- package/dist/missions/mission-engine.js +30 -8
- package/dist/missions/mission-engine.js.map +1 -1
- package/dist/notifications/__tests__/notification-service.test.d.ts +1 -0
- package/dist/notifications/__tests__/notification-service.test.js +176 -0
- package/dist/notifications/__tests__/notification-service.test.js.map +1 -0
- package/dist/notifications/discord-provider.d.ts +30 -0
- package/dist/notifications/discord-provider.js +89 -0
- package/dist/notifications/discord-provider.js.map +1 -0
- package/dist/notifications/email-provider.d.ts +41 -0
- package/dist/notifications/email-provider.js +101 -0
- package/dist/notifications/email-provider.js.map +1 -0
- package/dist/notifications/index.d.ts +8 -0
- package/dist/notifications/index.js +5 -0
- package/dist/notifications/index.js.map +1 -0
- package/dist/notifications/notification-provider.d.ts +75 -0
- package/dist/notifications/notification-provider.js +47 -0
- package/dist/notifications/notification-provider.js.map +1 -0
- package/dist/notifications/notification-service.d.ts +85 -0
- package/dist/notifications/notification-service.js +184 -0
- package/dist/notifications/notification-service.js.map +1 -0
- package/dist/notifications/telegram-provider.d.ts +30 -0
- package/dist/notifications/telegram-provider.js +78 -0
- package/dist/notifications/telegram-provider.js.map +1 -0
- package/dist/plugin/__tests__/plugin-registry.test.d.ts +1 -0
- package/dist/plugin/__tests__/plugin-registry.test.js +166 -0
- package/dist/plugin/__tests__/plugin-registry.test.js.map +1 -0
- package/dist/plugin/plugin-registry.d.ts +38 -0
- package/dist/plugin/plugin-registry.js +185 -0
- package/dist/plugin/plugin-registry.js.map +1 -0
- package/dist/plugin/types.d.ts +59 -0
- package/dist/plugin/types.js +2 -0
- package/dist/plugin/types.js.map +1 -0
- package/dist/research/adapters/__tests__/web-adapters.test.d.ts +1 -0
- package/dist/research/adapters/__tests__/web-adapters.test.js +106 -0
- package/dist/research/adapters/__tests__/web-adapters.test.js.map +1 -0
- package/dist/research/adapters/firecrawl-adapter.d.ts +57 -0
- package/dist/research/adapters/firecrawl-adapter.js +137 -0
- package/dist/research/adapters/firecrawl-adapter.js.map +1 -0
- package/dist/research/adapters/index.d.ts +3 -0
- package/dist/research/adapters/index.js +2 -0
- package/dist/research/adapters/index.js.map +1 -1
- package/dist/research/adapters/playwright-adapter.d.ts +54 -0
- package/dist/research/adapters/playwright-adapter.js +130 -0
- package/dist/research/adapters/playwright-adapter.js.map +1 -0
- package/dist/research/research-orchestrator.d.ts +3 -0
- package/dist/research/research-orchestrator.js +19 -1
- package/dist/research/research-orchestrator.js.map +1 -1
- package/dist/self-modification/self-modification-engine.js +28 -4
- package/dist/self-modification/self-modification-engine.js.map +1 -1
- package/dist/techradar/__tests__/techradar-engine.test.d.ts +1 -0
- package/dist/techradar/__tests__/techradar-engine.test.js +246 -0
- package/dist/techradar/__tests__/techradar-engine.test.js.map +1 -0
- package/dist/techradar/daily-digest.d.ts +18 -0
- package/dist/techradar/daily-digest.js +100 -0
- package/dist/techradar/daily-digest.js.map +1 -0
- package/dist/techradar/index.d.ts +5 -0
- package/dist/techradar/index.js +5 -0
- package/dist/techradar/index.js.map +1 -0
- package/dist/techradar/relevance-scorer.d.ts +29 -0
- package/dist/techradar/relevance-scorer.js +139 -0
- package/dist/techradar/relevance-scorer.js.map +1 -0
- package/dist/techradar/repo-watcher.d.ts +24 -0
- package/dist/techradar/repo-watcher.js +87 -0
- package/dist/techradar/repo-watcher.js.map +1 -0
- package/dist/techradar/techradar-engine.d.ts +69 -0
- package/dist/techradar/techradar-engine.js +382 -0
- package/dist/techradar/techradar-engine.js.map +1 -0
- package/dist/techradar/types.d.ts +87 -0
- package/dist/techradar/types.js +5 -0
- package/dist/techradar/types.js.map +1 -0
- package/dist/watchdog/__tests__/watchdog-service.test.d.ts +1 -0
- package/dist/watchdog/__tests__/watchdog-service.test.js +113 -0
- package/dist/watchdog/__tests__/watchdog-service.test.js.map +1 -0
- package/dist/watchdog/watchdog-service.d.ts +60 -0
- package/dist/watchdog/watchdog-service.js +275 -0
- package/dist/watchdog/watchdog-service.js.map +1 -0
- package/dist/watchdog/windows-service.d.ts +39 -0
- package/dist/watchdog/windows-service.js +179 -0
- package/dist/watchdog/windows-service.js.map +1 -0
- package/package.json +20 -2
|
@@ -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
|
+
}
|
|
@@ -0,0 +1,87 @@
|
|
|
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 { getLogger } from '../utils/logger.js';
|
|
11
|
+
const log = getLogger();
|
|
12
|
+
export class RepoWatcher {
|
|
13
|
+
githubToken;
|
|
14
|
+
constructor(githubToken) {
|
|
15
|
+
this.githubToken = githubToken ?? process.env.GITHUB_TOKEN ?? null;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Check a repo for new releases since the last known tag.
|
|
19
|
+
* Returns new releases (newest first).
|
|
20
|
+
*/
|
|
21
|
+
async checkReleases(repo) {
|
|
22
|
+
try {
|
|
23
|
+
const headers = {
|
|
24
|
+
'Accept': 'application/vnd.github+json',
|
|
25
|
+
'User-Agent': 'BrainEcosystem/1.0',
|
|
26
|
+
};
|
|
27
|
+
if (this.githubToken) {
|
|
28
|
+
headers['Authorization'] = `Bearer ${this.githubToken}`;
|
|
29
|
+
}
|
|
30
|
+
const response = await fetch(`https://api.github.com/repos/${repo.full_name}/releases?per_page=10`, { headers });
|
|
31
|
+
if (!response.ok) {
|
|
32
|
+
log.warn(`[RepoWatcher] GitHub API error for ${repo.full_name}: ${response.status}`);
|
|
33
|
+
return [];
|
|
34
|
+
}
|
|
35
|
+
const data = await response.json();
|
|
36
|
+
// Filter to only new releases (after last known tag)
|
|
37
|
+
const releases = [];
|
|
38
|
+
for (const release of data) {
|
|
39
|
+
if (repo.last_release_tag && release.tag_name === repo.last_release_tag) {
|
|
40
|
+
break; // We've seen this one, stop
|
|
41
|
+
}
|
|
42
|
+
releases.push({
|
|
43
|
+
tag: release.tag_name,
|
|
44
|
+
name: release.name || release.tag_name,
|
|
45
|
+
body: release.body || '',
|
|
46
|
+
published_at: release.published_at,
|
|
47
|
+
url: release.html_url,
|
|
48
|
+
is_prerelease: release.prerelease,
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
return releases;
|
|
52
|
+
}
|
|
53
|
+
catch (err) {
|
|
54
|
+
log.warn(`[RepoWatcher] Error checking ${repo.full_name}: ${err.message}`);
|
|
55
|
+
return [];
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Fetch the CHANGELOG.md or CHANGES.md from a repo.
|
|
60
|
+
* Returns the content or null if not found.
|
|
61
|
+
*/
|
|
62
|
+
async fetchChangelog(repoFullName) {
|
|
63
|
+
const candidates = ['CHANGELOG.md', 'CHANGES.md', 'HISTORY.md', 'changelog.md'];
|
|
64
|
+
for (const filename of candidates) {
|
|
65
|
+
try {
|
|
66
|
+
const headers = {
|
|
67
|
+
'Accept': 'application/vnd.github.raw+json',
|
|
68
|
+
'User-Agent': 'BrainEcosystem/1.0',
|
|
69
|
+
};
|
|
70
|
+
if (this.githubToken) {
|
|
71
|
+
headers['Authorization'] = `Bearer ${this.githubToken}`;
|
|
72
|
+
}
|
|
73
|
+
const response = await fetch(`https://api.github.com/repos/${repoFullName}/contents/${filename}`, { headers });
|
|
74
|
+
if (response.ok) {
|
|
75
|
+
const content = await response.text();
|
|
76
|
+
// Truncate to first ~5000 chars (recent entries)
|
|
77
|
+
return content.substring(0, 5000);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
catch {
|
|
81
|
+
// Try next candidate
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
return null;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
//# sourceMappingURL=repo-watcher.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"repo-watcher.js","sourceRoot":"","sources":["../../src/techradar/repo-watcher.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TechRadar Engine — Täglicher Internet-Scan + Relevanz-Analyse
|
|
3
|
+
*
|
|
4
|
+
* ═══════════════════════════════════════════════════════════════
|
|
5
|
+
* EINRICHTEN
|
|
6
|
+
* ═══════════════════════════════════════════════════════════════
|
|
7
|
+
*
|
|
8
|
+
* Funktioniert out of the box (nutzt SignalScanner-Daten).
|
|
9
|
+
*
|
|
10
|
+
* Für bessere Ergebnisse:
|
|
11
|
+
* 1. GITHUB_TOKEN in .env → höheres Rate Limit für Repo-Watching
|
|
12
|
+
* 2. LLMService angebunden → intelligentes Relevanz-Scoring
|
|
13
|
+
* 3. Repos watchlisten:
|
|
14
|
+
* brain techradar repos add anthropics/claude-code
|
|
15
|
+
* brain techradar repos add modelcontextprotocol/servers
|
|
16
|
+
*
|
|
17
|
+
* CLI:
|
|
18
|
+
* brain techradar → Heutigen Digest anzeigen
|
|
19
|
+
* brain techradar scan → Jetzt scannen
|
|
20
|
+
* brain techradar repos list → Überwachte Repos
|
|
21
|
+
* brain techradar repos add <repo>
|
|
22
|
+
* ═══════════════════════════════════════════════════════════════
|
|
23
|
+
*/
|
|
24
|
+
import Database from 'better-sqlite3';
|
|
25
|
+
import type { LLMService } from '../llm/llm-service.js';
|
|
26
|
+
import type { TechRadarConfig, TechRadarEntry, TechRadarScanResult, WatchedRepo, DailyDigest, TechRadarSource } from './types.js';
|
|
27
|
+
export declare function runTechRadarMigration(db: Database.Database): void;
|
|
28
|
+
export declare class TechRadarEngine {
|
|
29
|
+
private readonly db;
|
|
30
|
+
private readonly config;
|
|
31
|
+
private readonly repoWatcher;
|
|
32
|
+
private readonly relevanceScorer;
|
|
33
|
+
private readonly digestGenerator;
|
|
34
|
+
private scanTimer;
|
|
35
|
+
constructor(db: Database.Database, config?: Partial<TechRadarConfig>);
|
|
36
|
+
setLLMService(llmService: LLMService): void;
|
|
37
|
+
/** Start periodic scanning */
|
|
38
|
+
start(): void;
|
|
39
|
+
/** Stop periodic scanning */
|
|
40
|
+
stop(): void;
|
|
41
|
+
/** Run a full scan */
|
|
42
|
+
scan(): Promise<TechRadarScanResult>;
|
|
43
|
+
addWatchedRepo(fullName: string, reason?: string): void;
|
|
44
|
+
removeWatchedRepo(fullName: string): void;
|
|
45
|
+
getWatchedRepos(): WatchedRepo[];
|
|
46
|
+
private ensureDefaultWatchedRepos;
|
|
47
|
+
private checkWatchedRepos;
|
|
48
|
+
/**
|
|
49
|
+
* Import high-scoring repos from existing SignalScanner data.
|
|
50
|
+
* Only imports breakout and signal-level repos.
|
|
51
|
+
*/
|
|
52
|
+
private importFromSignalScanner;
|
|
53
|
+
private upsertEntry;
|
|
54
|
+
getEntries(options?: {
|
|
55
|
+
minScore?: number;
|
|
56
|
+
source?: TechRadarSource;
|
|
57
|
+
ring?: string;
|
|
58
|
+
limit?: number;
|
|
59
|
+
}): TechRadarEntry[];
|
|
60
|
+
generateDigest(date?: string): Promise<DailyDigest>;
|
|
61
|
+
getDigest(date?: string): DailyDigest | null;
|
|
62
|
+
getStats(): {
|
|
63
|
+
totalEntries: number;
|
|
64
|
+
bySource: Record<string, number>;
|
|
65
|
+
byRing: Record<string, number>;
|
|
66
|
+
watchedRepos: number;
|
|
67
|
+
lastDigest: string | null;
|
|
68
|
+
};
|
|
69
|
+
}
|