@timmeck/brain 3.15.0 → 3.17.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.
- package/dist/brain.js +12 -1
- package/dist/brain.js.map +1 -1
- package/dist/cli/commands/import.js +52 -1
- package/dist/cli/commands/import.js.map +1 -1
- package/dist/config.js +16 -0
- package/dist/config.js.map +1 -1
- package/dist/ipc/router.d.ts +4 -0
- package/dist/ipc/router.js +36 -1
- package/dist/ipc/router.js.map +1 -1
- package/dist/mcp/http-server.js +5 -1
- package/dist/mcp/http-server.js.map +1 -1
- package/dist/mcp/reposignal-tools.d.ts +7 -0
- package/dist/mcp/reposignal-tools.js +65 -0
- package/dist/mcp/reposignal-tools.js.map +1 -0
- package/dist/mcp/scanner-tools.d.ts +7 -0
- package/dist/mcp/scanner-tools.js +189 -0
- package/dist/mcp/scanner-tools.js.map +1 -0
- package/dist/mcp/server.js +5 -1
- package/dist/mcp/server.js.map +1 -1
- package/dist/services/reposignal-importer.d.ts +68 -0
- package/dist/services/reposignal-importer.js +242 -0
- package/dist/services/reposignal-importer.js.map +1 -0
- package/dist/types/config.types.d.ts +11 -0
- package/package.json +2 -2
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import Database from 'better-sqlite3';
|
|
2
|
+
export interface ReposignalRepo {
|
|
3
|
+
id: number;
|
|
4
|
+
full_name: string;
|
|
5
|
+
name: string;
|
|
6
|
+
owner: string;
|
|
7
|
+
description: string | null;
|
|
8
|
+
language: string | null;
|
|
9
|
+
topics: string | null;
|
|
10
|
+
current_stars: number;
|
|
11
|
+
current_forks: number;
|
|
12
|
+
signal_score: number;
|
|
13
|
+
signal_level: string;
|
|
14
|
+
phase: string;
|
|
15
|
+
first_seen_at: string;
|
|
16
|
+
last_scanned_at: string | null;
|
|
17
|
+
}
|
|
18
|
+
export interface ReposignalHnMention {
|
|
19
|
+
title: string;
|
|
20
|
+
url: string;
|
|
21
|
+
score: number;
|
|
22
|
+
comment_count: number;
|
|
23
|
+
repo_id: number | null;
|
|
24
|
+
}
|
|
25
|
+
export interface ReposignalImportOptions {
|
|
26
|
+
/** Minimum signal level: 'noise' | 'watch' | 'signal' | 'breakout'. Default: 'watch' */
|
|
27
|
+
minSignalLevel?: string;
|
|
28
|
+
/** Maximum repos to import per run. Default: 5000 */
|
|
29
|
+
batchSize?: number;
|
|
30
|
+
/** Import HN mentions too. Default: true */
|
|
31
|
+
includeHnMentions?: boolean;
|
|
32
|
+
/** Record metrics for PredictionEngine. Default: true */
|
|
33
|
+
recordMetrics?: boolean;
|
|
34
|
+
}
|
|
35
|
+
export interface ReposignalImportResult {
|
|
36
|
+
dbPath: string;
|
|
37
|
+
totalReposInDb: number;
|
|
38
|
+
reposImported: number;
|
|
39
|
+
discoveriesCreated: number;
|
|
40
|
+
journalEntriesCreated: number;
|
|
41
|
+
hnMentionsImported: number;
|
|
42
|
+
metricsRecorded: number;
|
|
43
|
+
skippedDuplicates: number;
|
|
44
|
+
languageBreakdown: Record<string, number>;
|
|
45
|
+
signalBreakdown: Record<string, number>;
|
|
46
|
+
duration_ms: number;
|
|
47
|
+
}
|
|
48
|
+
export declare class ReposignalImporter {
|
|
49
|
+
private brainDb;
|
|
50
|
+
private log;
|
|
51
|
+
private lastResult;
|
|
52
|
+
constructor(brainDb: Database.Database);
|
|
53
|
+
private ensureStateTable;
|
|
54
|
+
/** Import repos from a reposignal/aisurvival SQLite database. */
|
|
55
|
+
import(dbPath: string, options?: ReposignalImportOptions): ReposignalImportResult;
|
|
56
|
+
/** Import top HN mentions as journal entries. */
|
|
57
|
+
private importHnMentions;
|
|
58
|
+
/** Record aggregated metrics into prediction_metrics table. */
|
|
59
|
+
private recordImportMetrics;
|
|
60
|
+
private parseTopics;
|
|
61
|
+
getLastResult(): ReposignalImportResult | null;
|
|
62
|
+
/** Get import stats from state table. */
|
|
63
|
+
getStats(): {
|
|
64
|
+
totalImported: number;
|
|
65
|
+
byLevel: Record<string, number>;
|
|
66
|
+
lastImport: string | null;
|
|
67
|
+
};
|
|
68
|
+
}
|
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
import Database from 'better-sqlite3';
|
|
2
|
+
import fs from 'node:fs';
|
|
3
|
+
import { getLogger } from '@timmeck/brain-core/utils/logger';
|
|
4
|
+
// ── Constants ───────────────────────────────────────
|
|
5
|
+
const SIGNAL_LEVELS = ['noise', 'watch', 'signal', 'breakout'];
|
|
6
|
+
function signalLevelIndex(level) {
|
|
7
|
+
return SIGNAL_LEVELS.indexOf(level);
|
|
8
|
+
}
|
|
9
|
+
// ── Importer ────────────────────────────────────────
|
|
10
|
+
export class ReposignalImporter {
|
|
11
|
+
brainDb;
|
|
12
|
+
log = getLogger();
|
|
13
|
+
lastResult = null;
|
|
14
|
+
constructor(brainDb) {
|
|
15
|
+
this.brainDb = brainDb;
|
|
16
|
+
this.ensureStateTable();
|
|
17
|
+
}
|
|
18
|
+
ensureStateTable() {
|
|
19
|
+
this.brainDb.exec(`
|
|
20
|
+
CREATE TABLE IF NOT EXISTS reposignal_import_state (
|
|
21
|
+
repo_full_name TEXT PRIMARY KEY,
|
|
22
|
+
signal_score REAL NOT NULL,
|
|
23
|
+
signal_level TEXT NOT NULL,
|
|
24
|
+
imported_at TEXT DEFAULT (datetime('now'))
|
|
25
|
+
)
|
|
26
|
+
`);
|
|
27
|
+
}
|
|
28
|
+
/** Import repos from a reposignal/aisurvival SQLite database. */
|
|
29
|
+
import(dbPath, options = {}) {
|
|
30
|
+
const start = Date.now();
|
|
31
|
+
const minLevel = options.minSignalLevel ?? 'watch';
|
|
32
|
+
const batchSize = options.batchSize ?? 5000;
|
|
33
|
+
const includeHn = options.includeHnMentions !== false;
|
|
34
|
+
const recordMetrics = options.recordMetrics !== false;
|
|
35
|
+
if (!fs.existsSync(dbPath)) {
|
|
36
|
+
throw new Error(`Reposignal DB not found: ${dbPath}`);
|
|
37
|
+
}
|
|
38
|
+
const extDb = new Database(dbPath, { readonly: true });
|
|
39
|
+
const result = {
|
|
40
|
+
dbPath,
|
|
41
|
+
totalReposInDb: 0,
|
|
42
|
+
reposImported: 0,
|
|
43
|
+
discoveriesCreated: 0,
|
|
44
|
+
journalEntriesCreated: 0,
|
|
45
|
+
hnMentionsImported: 0,
|
|
46
|
+
metricsRecorded: 0,
|
|
47
|
+
skippedDuplicates: 0,
|
|
48
|
+
languageBreakdown: {},
|
|
49
|
+
signalBreakdown: {},
|
|
50
|
+
duration_ms: 0,
|
|
51
|
+
};
|
|
52
|
+
try {
|
|
53
|
+
// Count total repos
|
|
54
|
+
result.totalReposInDb = extDb.prepare('SELECT COUNT(*) as c FROM repositories').get().c;
|
|
55
|
+
// Fetch repos at or above minimum signal level
|
|
56
|
+
const minLevelIdx = signalLevelIndex(minLevel);
|
|
57
|
+
const allowedLevels = SIGNAL_LEVELS.filter((_, i) => i >= minLevelIdx);
|
|
58
|
+
const placeholders = allowedLevels.map(() => '?').join(',');
|
|
59
|
+
const repos = extDb.prepare(`
|
|
60
|
+
SELECT id, full_name, name, owner, description, language, topics,
|
|
61
|
+
current_stars, current_forks, signal_score, signal_level, phase,
|
|
62
|
+
first_seen_at, last_scanned_at
|
|
63
|
+
FROM repositories
|
|
64
|
+
WHERE signal_level IN (${placeholders}) AND is_active = 1
|
|
65
|
+
ORDER BY signal_score DESC
|
|
66
|
+
LIMIT ?
|
|
67
|
+
`).all(...allowedLevels, batchSize);
|
|
68
|
+
this.log.info(`[reposignal] Found ${repos.length} repos at ${minLevel}+ level (${result.totalReposInDb} total in DB)`);
|
|
69
|
+
// Check which repos we already imported
|
|
70
|
+
const alreadyImported = new Set();
|
|
71
|
+
const existing = this.brainDb.prepare('SELECT repo_full_name FROM reposignal_import_state').all();
|
|
72
|
+
for (const e of existing)
|
|
73
|
+
alreadyImported.add(e.repo_full_name);
|
|
74
|
+
// Prepare statements
|
|
75
|
+
const insertDiscovery = this.brainDb.prepare(`
|
|
76
|
+
INSERT INTO research_discoveries (type, title, description, confidence, impact, source, data)
|
|
77
|
+
VALUES (?, ?, ?, ?, ?, ?, ?)
|
|
78
|
+
`);
|
|
79
|
+
const insertJournal = this.brainDb.prepare(`
|
|
80
|
+
INSERT INTO research_journal (timestamp, type, title, content, tags, ref_ids, significance, data)
|
|
81
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
|
82
|
+
`);
|
|
83
|
+
const insertState = this.brainDb.prepare(`
|
|
84
|
+
INSERT OR REPLACE INTO reposignal_import_state (repo_full_name, signal_score, signal_level)
|
|
85
|
+
VALUES (?, ?, ?)
|
|
86
|
+
`);
|
|
87
|
+
// Batch import repos
|
|
88
|
+
const importBatch = this.brainDb.transaction(() => {
|
|
89
|
+
for (const repo of repos) {
|
|
90
|
+
// Track breakdown
|
|
91
|
+
const lang = repo.language || 'unknown';
|
|
92
|
+
result.languageBreakdown[lang] = (result.languageBreakdown[lang] || 0) + 1;
|
|
93
|
+
result.signalBreakdown[repo.signal_level] = (result.signalBreakdown[repo.signal_level] || 0) + 1;
|
|
94
|
+
// Skip duplicates
|
|
95
|
+
if (alreadyImported.has(repo.full_name)) {
|
|
96
|
+
result.skippedDuplicates++;
|
|
97
|
+
continue;
|
|
98
|
+
}
|
|
99
|
+
// Create research discovery for signal+ repos
|
|
100
|
+
const confidence = Math.min(repo.signal_score / 100, 1.0);
|
|
101
|
+
const impact = repo.signal_level === 'breakout' ? 0.9 : repo.signal_level === 'signal' ? 0.7 : 0.4;
|
|
102
|
+
const topics = this.parseTopics(repo.topics);
|
|
103
|
+
const description = [
|
|
104
|
+
repo.description || 'No description',
|
|
105
|
+
`Language: ${lang}`,
|
|
106
|
+
`Stars: ${repo.current_stars}, Forks: ${repo.current_forks}`,
|
|
107
|
+
`Phase: ${repo.phase}`,
|
|
108
|
+
topics.length > 0 ? `Topics: ${topics.join(', ')}` : '',
|
|
109
|
+
].filter(Boolean).join('\n');
|
|
110
|
+
insertDiscovery.run('reposignal_import', `[${repo.signal_level.toUpperCase()}] ${repo.full_name} — ${(repo.description || 'GitHub project').slice(0, 120)}`, description, confidence, impact, 'reposignal', JSON.stringify({
|
|
111
|
+
repo: repo.full_name,
|
|
112
|
+
language: lang,
|
|
113
|
+
stars: repo.current_stars,
|
|
114
|
+
forks: repo.current_forks,
|
|
115
|
+
signal_score: repo.signal_score,
|
|
116
|
+
signal_level: repo.signal_level,
|
|
117
|
+
phase: repo.phase,
|
|
118
|
+
topics,
|
|
119
|
+
}));
|
|
120
|
+
result.discoveriesCreated++;
|
|
121
|
+
// Mark as imported
|
|
122
|
+
insertState.run(repo.full_name, repo.signal_score, repo.signal_level);
|
|
123
|
+
result.reposImported++;
|
|
124
|
+
}
|
|
125
|
+
// Create journal entries summarizing the import by language
|
|
126
|
+
const langGroups = Object.entries(result.languageBreakdown)
|
|
127
|
+
.sort(([, a], [, b]) => b - a)
|
|
128
|
+
.slice(0, 10);
|
|
129
|
+
if (result.reposImported > 0) {
|
|
130
|
+
const langSummary = langGroups.map(([lang, count]) => `${lang}: ${count}`).join(', ');
|
|
131
|
+
insertJournal.run(Date.now(), 'discovery', `Reposignal Import: ${result.reposImported} repos imported`, `Imported ${result.reposImported} trending repos from reposignal DB (${result.totalReposInDb} total tracked).\n` +
|
|
132
|
+
`Signal breakdown: ${Object.entries(result.signalBreakdown).map(([k, v]) => `${k}: ${v}`).join(', ')}\n` +
|
|
133
|
+
`Top languages: ${langSummary}`, JSON.stringify(['reposignal', 'import', 'tech-trends']), '[]', 'notable', JSON.stringify({ reposImported: result.reposImported, languageBreakdown: result.languageBreakdown }));
|
|
134
|
+
result.journalEntriesCreated++;
|
|
135
|
+
}
|
|
136
|
+
// Create journal entries for top signal repos (breakout/signal)
|
|
137
|
+
const topRepos = repos
|
|
138
|
+
.filter(r => !alreadyImported.has(r.full_name) && (r.signal_level === 'breakout' || r.signal_level === 'signal'))
|
|
139
|
+
.slice(0, 20);
|
|
140
|
+
for (const repo of topRepos) {
|
|
141
|
+
const topics = this.parseTopics(repo.topics);
|
|
142
|
+
insertJournal.run(Date.now(), 'discovery', `Trending: ${repo.full_name} (${repo.signal_level}, ${repo.signal_score.toFixed(1)} score)`, `${repo.description || 'No description'}\n` +
|
|
143
|
+
`Language: ${repo.language || 'unknown'}, Stars: ${repo.current_stars}, Phase: ${repo.phase}`, JSON.stringify(['reposignal', repo.signal_level, repo.language || 'unknown', ...topics.slice(0, 3)]), '[]', repo.signal_level === 'breakout' ? 'breakthrough' : 'notable', JSON.stringify({ repo: repo.full_name, signal_score: repo.signal_score }));
|
|
144
|
+
result.journalEntriesCreated++;
|
|
145
|
+
}
|
|
146
|
+
});
|
|
147
|
+
importBatch();
|
|
148
|
+
// Import HN mentions
|
|
149
|
+
if (includeHn) {
|
|
150
|
+
result.hnMentionsImported = this.importHnMentions(extDb, insertJournal);
|
|
151
|
+
result.journalEntriesCreated += result.hnMentionsImported;
|
|
152
|
+
}
|
|
153
|
+
// Record metrics for PredictionEngine
|
|
154
|
+
if (recordMetrics) {
|
|
155
|
+
result.metricsRecorded = this.recordImportMetrics(result);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
finally {
|
|
159
|
+
extDb.close();
|
|
160
|
+
}
|
|
161
|
+
result.duration_ms = Date.now() - start;
|
|
162
|
+
this.lastResult = result;
|
|
163
|
+
this.log.info(`[reposignal] Import complete: ${result.reposImported} repos, ${result.discoveriesCreated} discoveries, ${result.journalEntriesCreated} journal entries in ${result.duration_ms}ms`);
|
|
164
|
+
return result;
|
|
165
|
+
}
|
|
166
|
+
/** Import top HN mentions as journal entries. */
|
|
167
|
+
importHnMentions(extDb, insertJournal) {
|
|
168
|
+
let count = 0;
|
|
169
|
+
try {
|
|
170
|
+
const mentions = extDb.prepare(`
|
|
171
|
+
SELECT DISTINCT title, url, score, comment_count
|
|
172
|
+
FROM hn_mentions
|
|
173
|
+
WHERE score > 50
|
|
174
|
+
ORDER BY score DESC
|
|
175
|
+
LIMIT 100
|
|
176
|
+
`).all();
|
|
177
|
+
for (const m of mentions) {
|
|
178
|
+
insertJournal.run(Date.now(), 'discovery', `HN: ${m.title} (${m.score} pts, ${m.comment_count} comments)`, `High-engagement HN/Reddit post: ${m.title}\nScore: ${m.score}, Comments: ${m.comment_count}`, JSON.stringify(['reposignal', 'hn', 'social-signal']), '[]', m.score > 500 ? 'notable' : 'routine', JSON.stringify({ source: 'hn', score: m.score, comments: m.comment_count }));
|
|
179
|
+
count++;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
catch {
|
|
183
|
+
this.log.debug('[reposignal] No HN mentions table or error reading it');
|
|
184
|
+
}
|
|
185
|
+
return count;
|
|
186
|
+
}
|
|
187
|
+
/** Record aggregated metrics into prediction_metrics table. */
|
|
188
|
+
recordImportMetrics(result) {
|
|
189
|
+
let count = 0;
|
|
190
|
+
try {
|
|
191
|
+
const insertMetric = this.brainDb.prepare(`
|
|
192
|
+
INSERT INTO prediction_metrics (metric, value, timestamp, domain)
|
|
193
|
+
VALUES (?, ?, ?, ?)
|
|
194
|
+
`);
|
|
195
|
+
const now = Date.now();
|
|
196
|
+
insertMetric.run('reposignal_total_repos', result.totalReposInDb, now, 'metric');
|
|
197
|
+
count++;
|
|
198
|
+
insertMetric.run('reposignal_repos_imported', result.reposImported, now, 'metric');
|
|
199
|
+
count++;
|
|
200
|
+
// Record per-language counts
|
|
201
|
+
for (const [lang, langCount] of Object.entries(result.languageBreakdown)) {
|
|
202
|
+
if (langCount >= 10) {
|
|
203
|
+
insertMetric.run(`reposignal_lang_${lang.toLowerCase()}`, langCount, now, 'metric');
|
|
204
|
+
count++;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
// Record signal level counts
|
|
208
|
+
for (const [level, levelCount] of Object.entries(result.signalBreakdown)) {
|
|
209
|
+
insertMetric.run(`reposignal_${level}_count`, levelCount, now, 'metric');
|
|
210
|
+
count++;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
catch (err) {
|
|
214
|
+
this.log.debug('[reposignal] Error recording metrics:', err);
|
|
215
|
+
}
|
|
216
|
+
return count;
|
|
217
|
+
}
|
|
218
|
+
parseTopics(topics) {
|
|
219
|
+
if (!topics)
|
|
220
|
+
return [];
|
|
221
|
+
try {
|
|
222
|
+
return JSON.parse(topics);
|
|
223
|
+
}
|
|
224
|
+
catch {
|
|
225
|
+
return [];
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
getLastResult() {
|
|
229
|
+
return this.lastResult;
|
|
230
|
+
}
|
|
231
|
+
/** Get import stats from state table. */
|
|
232
|
+
getStats() {
|
|
233
|
+
const total = this.brainDb.prepare('SELECT COUNT(*) as c FROM reposignal_import_state').get().c;
|
|
234
|
+
const levels = this.brainDb.prepare('SELECT signal_level, COUNT(*) as c FROM reposignal_import_state GROUP BY signal_level').all();
|
|
235
|
+
const last = this.brainDb.prepare('SELECT MAX(imported_at) as t FROM reposignal_import_state').get();
|
|
236
|
+
const byLevel = {};
|
|
237
|
+
for (const l of levels)
|
|
238
|
+
byLevel[l.signal_level] = l.c;
|
|
239
|
+
return { totalImported: total, byLevel, lastImport: last.t };
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
//# sourceMappingURL=reposignal-importer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reposignal-importer.js","sourceRoot":"","sources":["../../src/services/reposignal-importer.ts"],"names":[],"mappings":"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"}
|
|
@@ -73,6 +73,16 @@ export interface EmbeddingsConfig {
|
|
|
73
73
|
sweepIntervalMs: number;
|
|
74
74
|
batchSize: number;
|
|
75
75
|
}
|
|
76
|
+
export interface ScannerBrainConfig {
|
|
77
|
+
enabled: boolean;
|
|
78
|
+
githubToken: string;
|
|
79
|
+
scanIntervalMs: number;
|
|
80
|
+
minStarsEmerging: number;
|
|
81
|
+
minStarsTrending: number;
|
|
82
|
+
maxReposPerScan: number;
|
|
83
|
+
cryptoEnabled: boolean;
|
|
84
|
+
hnEnabled: boolean;
|
|
85
|
+
}
|
|
76
86
|
export interface BrainConfig {
|
|
77
87
|
dataDir: string;
|
|
78
88
|
dbPath: string;
|
|
@@ -88,4 +98,5 @@ export interface BrainConfig {
|
|
|
88
98
|
research: ResearchConfig;
|
|
89
99
|
log: LogConfig;
|
|
90
100
|
retention: RetentionConfig;
|
|
101
|
+
scanner: ScannerBrainConfig;
|
|
91
102
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@timmeck/brain",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.17.0",
|
|
4
4
|
"description": "Adaptive error memory and code intelligence system with Hebbian synapse network, hybrid search, and REST API",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
"dependencies": {
|
|
44
44
|
"@huggingface/transformers": "^3.8.1",
|
|
45
45
|
"@modelcontextprotocol/sdk": "^1.0.0",
|
|
46
|
-
"@timmeck/brain-core": "2.
|
|
46
|
+
"@timmeck/brain-core": "^2.16.0",
|
|
47
47
|
"better-sqlite3": "^11.7.0",
|
|
48
48
|
"chalk": "^5.6.2",
|
|
49
49
|
"commander": "^13.0.0",
|