@timmeck/brain 1.1.0 → 1.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/commands/start.js +3 -1
- package/dist/cli/commands/start.js.map +1 -1
- package/dist/cli/commands/status.js +3 -1
- package/dist/cli/commands/status.js.map +1 -1
- package/dist/cli/update-check.d.ts +2 -0
- package/dist/cli/update-check.js +58 -0
- package/dist/cli/update-check.js.map +1 -0
- package/package.json +1 -1
- package/src/cli/commands/start.ts +3 -1
- package/src/cli/commands/status.ts +4 -1
- package/src/cli/update-check.ts +63 -0
|
@@ -4,6 +4,7 @@ import fs from 'node:fs';
|
|
|
4
4
|
import path from 'node:path';
|
|
5
5
|
import { getDataDir } from '../../utils/paths.js';
|
|
6
6
|
import { c, icons } from '../colors.js';
|
|
7
|
+
import { checkForUpdate } from '../update-check.js';
|
|
7
8
|
export function startCommand() {
|
|
8
9
|
return new Command('start')
|
|
9
10
|
.description('Start the Brain daemon')
|
|
@@ -44,13 +45,14 @@ export function startCommand() {
|
|
|
44
45
|
child.unref();
|
|
45
46
|
console.log(`${icons.brain} ${c.info('Brain daemon starting')} ${c.dim(`(PID: ${child.pid})`)}`);
|
|
46
47
|
// Wait briefly for PID file to appear
|
|
47
|
-
setTimeout(() => {
|
|
48
|
+
setTimeout(async () => {
|
|
48
49
|
if (fs.existsSync(pidPath)) {
|
|
49
50
|
console.log(`${icons.ok} ${c.success('Brain daemon started successfully.')}`);
|
|
50
51
|
}
|
|
51
52
|
else {
|
|
52
53
|
console.log(`${icons.clock} ${c.warn('Brain daemon may still be starting.')} Check: ${c.cyan('brain status')}`);
|
|
53
54
|
}
|
|
55
|
+
await checkForUpdate();
|
|
54
56
|
}, 1000);
|
|
55
57
|
});
|
|
56
58
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"start.js","sourceRoot":"","sources":["../../../src/cli/commands/start.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAC3C,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAClD,OAAO,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"start.js","sourceRoot":"","sources":["../../../src/cli/commands/start.ts"],"names":[],"mappings":"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"}
|
|
@@ -4,6 +4,7 @@ import path from 'node:path';
|
|
|
4
4
|
import { getDataDir } from '../../utils/paths.js';
|
|
5
5
|
import { withIpc } from '../ipc-helper.js';
|
|
6
6
|
import { c, icons, header, keyValue, divider } from '../colors.js';
|
|
7
|
+
import { checkForUpdate, getCurrentVersion } from '../update-check.js';
|
|
7
8
|
export function statusCommand() {
|
|
8
9
|
return new Command('status')
|
|
9
10
|
.description('Show Brain daemon status')
|
|
@@ -24,7 +25,7 @@ export function statusCommand() {
|
|
|
24
25
|
console.log(`${icons.brain} Brain Daemon: ${c.red.bold('NOT RUNNING')} ${c.dim('(stale PID file)')}`);
|
|
25
26
|
return;
|
|
26
27
|
}
|
|
27
|
-
console.log(header(
|
|
28
|
+
console.log(header(`Brain Status v${getCurrentVersion()}`, icons.brain));
|
|
28
29
|
console.log(` ${c.green(`${icons.dot} RUNNING`)} ${c.dim(`(PID ${pid})`)}`);
|
|
29
30
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
30
31
|
await withIpc(async (client) => {
|
|
@@ -56,6 +57,7 @@ export function statusCommand() {
|
|
|
56
57
|
console.log();
|
|
57
58
|
console.log(` ${icons.insight} ${c.orange.bold('Research Brain')}`);
|
|
58
59
|
console.log(` ${c.label('Insights:')} ${c.value(summary.insights?.active ?? 0)} active`);
|
|
60
|
+
await checkForUpdate();
|
|
59
61
|
console.log(`\n${divider()}`);
|
|
60
62
|
});
|
|
61
63
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"status.js","sourceRoot":"","sources":["../../../src/cli/commands/status.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAClD,OAAO,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAC3C,OAAO,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"status.js","sourceRoot":"","sources":["../../../src/cli/commands/status.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import https from 'node:https';
|
|
2
|
+
import { c, icons } from './colors.js';
|
|
3
|
+
// Read current version from package.json at build time
|
|
4
|
+
import { createRequire } from 'node:module';
|
|
5
|
+
const require = createRequire(import.meta.url);
|
|
6
|
+
const pkg = require('../../package.json');
|
|
7
|
+
const CURRENT_VERSION = pkg.version;
|
|
8
|
+
export function getCurrentVersion() {
|
|
9
|
+
return CURRENT_VERSION;
|
|
10
|
+
}
|
|
11
|
+
function fetchLatestVersion() {
|
|
12
|
+
return new Promise((resolve) => {
|
|
13
|
+
const timeout = setTimeout(() => resolve(null), 3000);
|
|
14
|
+
const req = https.get('https://registry.npmjs.org/@timmeck/brain/latest', { headers: { Accept: 'application/json' } }, (res) => {
|
|
15
|
+
let data = '';
|
|
16
|
+
res.on('data', (chunk) => { data += chunk; });
|
|
17
|
+
res.on('end', () => {
|
|
18
|
+
clearTimeout(timeout);
|
|
19
|
+
try {
|
|
20
|
+
const json = JSON.parse(data);
|
|
21
|
+
resolve(json.version ?? null);
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
resolve(null);
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
});
|
|
28
|
+
req.on('error', () => {
|
|
29
|
+
clearTimeout(timeout);
|
|
30
|
+
resolve(null);
|
|
31
|
+
});
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
function isNewer(latest, current) {
|
|
35
|
+
const l = latest.split('.').map(Number);
|
|
36
|
+
const c = current.split('.').map(Number);
|
|
37
|
+
for (let i = 0; i < 3; i++) {
|
|
38
|
+
if ((l[i] ?? 0) > (c[i] ?? 0))
|
|
39
|
+
return true;
|
|
40
|
+
if ((l[i] ?? 0) < (c[i] ?? 0))
|
|
41
|
+
return false;
|
|
42
|
+
}
|
|
43
|
+
return false;
|
|
44
|
+
}
|
|
45
|
+
export async function checkForUpdate() {
|
|
46
|
+
try {
|
|
47
|
+
const latest = await fetchLatestVersion();
|
|
48
|
+
if (latest && isNewer(latest, CURRENT_VERSION)) {
|
|
49
|
+
console.log();
|
|
50
|
+
console.log(` ${icons.star} ${c.orange.bold(`Update available: v${CURRENT_VERSION} → v${latest}`)}`);
|
|
51
|
+
console.log(` Run: ${c.cyan('npm update -g @timmeck/brain')}`);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
catch {
|
|
55
|
+
// silently ignore — update check is best-effort
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=update-check.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"update-check.js","sourceRoot":"","sources":["../../src/cli/update-check.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -4,6 +4,7 @@ import fs from 'node:fs';
|
|
|
4
4
|
import path from 'node:path';
|
|
5
5
|
import { getDataDir } from '../../utils/paths.js';
|
|
6
6
|
import { c, icons } from '../colors.js';
|
|
7
|
+
import { checkForUpdate } from '../update-check.js';
|
|
7
8
|
|
|
8
9
|
export function startCommand(): Command {
|
|
9
10
|
return new Command('start')
|
|
@@ -49,12 +50,13 @@ export function startCommand(): Command {
|
|
|
49
50
|
console.log(`${icons.brain} ${c.info('Brain daemon starting')} ${c.dim(`(PID: ${child.pid})`)}`);
|
|
50
51
|
|
|
51
52
|
// Wait briefly for PID file to appear
|
|
52
|
-
setTimeout(() => {
|
|
53
|
+
setTimeout(async () => {
|
|
53
54
|
if (fs.existsSync(pidPath)) {
|
|
54
55
|
console.log(`${icons.ok} ${c.success('Brain daemon started successfully.')}`);
|
|
55
56
|
} else {
|
|
56
57
|
console.log(`${icons.clock} ${c.warn('Brain daemon may still be starting.')} Check: ${c.cyan('brain status')}`);
|
|
57
58
|
}
|
|
59
|
+
await checkForUpdate();
|
|
58
60
|
}, 1000);
|
|
59
61
|
});
|
|
60
62
|
}
|
|
@@ -4,6 +4,7 @@ import path from 'node:path';
|
|
|
4
4
|
import { getDataDir } from '../../utils/paths.js';
|
|
5
5
|
import { withIpc } from '../ipc-helper.js';
|
|
6
6
|
import { c, icons, header, keyValue, divider } from '../colors.js';
|
|
7
|
+
import { checkForUpdate, getCurrentVersion } from '../update-check.js';
|
|
7
8
|
|
|
8
9
|
export function statusCommand(): Command {
|
|
9
10
|
return new Command('status')
|
|
@@ -28,7 +29,7 @@ export function statusCommand(): Command {
|
|
|
28
29
|
return;
|
|
29
30
|
}
|
|
30
31
|
|
|
31
|
-
console.log(header(
|
|
32
|
+
console.log(header(`Brain Status v${getCurrentVersion()}`, icons.brain));
|
|
32
33
|
console.log(` ${c.green(`${icons.dot} RUNNING`)} ${c.dim(`(PID ${pid})`)}`);
|
|
33
34
|
|
|
34
35
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
@@ -66,6 +67,8 @@ export function statusCommand(): Command {
|
|
|
66
67
|
|
|
67
68
|
console.log(` ${icons.insight} ${c.orange.bold('Research Brain')}`);
|
|
68
69
|
console.log(` ${c.label('Insights:')} ${c.value(summary.insights?.active ?? 0)} active`);
|
|
70
|
+
|
|
71
|
+
await checkForUpdate();
|
|
69
72
|
console.log(`\n${divider()}`);
|
|
70
73
|
});
|
|
71
74
|
});
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import https from 'node:https';
|
|
2
|
+
import { c, icons } from './colors.js';
|
|
3
|
+
|
|
4
|
+
// Read current version from package.json at build time
|
|
5
|
+
import { createRequire } from 'node:module';
|
|
6
|
+
const require = createRequire(import.meta.url);
|
|
7
|
+
const pkg = require('../../package.json');
|
|
8
|
+
const CURRENT_VERSION: string = pkg.version;
|
|
9
|
+
|
|
10
|
+
export function getCurrentVersion(): string {
|
|
11
|
+
return CURRENT_VERSION;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function fetchLatestVersion(): Promise<string | null> {
|
|
15
|
+
return new Promise((resolve) => {
|
|
16
|
+
const timeout = setTimeout(() => resolve(null), 3000);
|
|
17
|
+
|
|
18
|
+
const req = https.get(
|
|
19
|
+
'https://registry.npmjs.org/@timmeck/brain/latest',
|
|
20
|
+
{ headers: { Accept: 'application/json' } },
|
|
21
|
+
(res) => {
|
|
22
|
+
let data = '';
|
|
23
|
+
res.on('data', (chunk) => { data += chunk; });
|
|
24
|
+
res.on('end', () => {
|
|
25
|
+
clearTimeout(timeout);
|
|
26
|
+
try {
|
|
27
|
+
const json = JSON.parse(data);
|
|
28
|
+
resolve(json.version ?? null);
|
|
29
|
+
} catch {
|
|
30
|
+
resolve(null);
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
},
|
|
34
|
+
);
|
|
35
|
+
req.on('error', () => {
|
|
36
|
+
clearTimeout(timeout);
|
|
37
|
+
resolve(null);
|
|
38
|
+
});
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function isNewer(latest: string, current: string): boolean {
|
|
43
|
+
const l = latest.split('.').map(Number);
|
|
44
|
+
const c = current.split('.').map(Number);
|
|
45
|
+
for (let i = 0; i < 3; i++) {
|
|
46
|
+
if ((l[i] ?? 0) > (c[i] ?? 0)) return true;
|
|
47
|
+
if ((l[i] ?? 0) < (c[i] ?? 0)) return false;
|
|
48
|
+
}
|
|
49
|
+
return false;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export async function checkForUpdate(): Promise<void> {
|
|
53
|
+
try {
|
|
54
|
+
const latest = await fetchLatestVersion();
|
|
55
|
+
if (latest && isNewer(latest, CURRENT_VERSION)) {
|
|
56
|
+
console.log();
|
|
57
|
+
console.log(` ${icons.star} ${c.orange.bold(`Update available: v${CURRENT_VERSION} → v${latest}`)}`);
|
|
58
|
+
console.log(` Run: ${c.cyan('npm update -g @timmeck/brain')}`);
|
|
59
|
+
}
|
|
60
|
+
} catch {
|
|
61
|
+
// silently ignore — update check is best-effort
|
|
62
|
+
}
|
|
63
|
+
}
|