@timmeck/brain 3.36.15 → 3.36.17

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 (33) hide show
  1. package/README.md +178 -188
  2. package/dist/brain.d.ts +4 -0
  3. package/dist/brain.js +185 -7
  4. package/dist/brain.js.map +1 -1
  5. package/dist/cli/commands/__tests__/borg.test.d.ts +1 -0
  6. package/dist/cli/commands/__tests__/borg.test.js +84 -0
  7. package/dist/cli/commands/__tests__/borg.test.js.map +1 -0
  8. package/dist/cli/commands/__tests__/plugins.test.d.ts +1 -0
  9. package/dist/cli/commands/__tests__/plugins.test.js +69 -0
  10. package/dist/cli/commands/__tests__/plugins.test.js.map +1 -0
  11. package/dist/cli/commands/__tests__/watchdog.test.d.ts +1 -0
  12. package/dist/cli/commands/__tests__/watchdog.test.js +63 -0
  13. package/dist/cli/commands/__tests__/watchdog.test.js.map +1 -0
  14. package/dist/cli/commands/borg.d.ts +2 -0
  15. package/dist/cli/commands/borg.js +77 -0
  16. package/dist/cli/commands/borg.js.map +1 -0
  17. package/dist/cli/commands/plugins.d.ts +2 -0
  18. package/dist/cli/commands/plugins.js +75 -0
  19. package/dist/cli/commands/plugins.js.map +1 -0
  20. package/dist/cli/commands/service.d.ts +2 -0
  21. package/dist/cli/commands/service.js +101 -0
  22. package/dist/cli/commands/service.js.map +1 -0
  23. package/dist/cli/commands/watchdog.d.ts +2 -0
  24. package/dist/cli/commands/watchdog.js +69 -0
  25. package/dist/cli/commands/watchdog.js.map +1 -0
  26. package/dist/index.js +8 -0
  27. package/dist/index.js.map +1 -1
  28. package/dist/ipc/router.d.ts +7 -0
  29. package/dist/ipc/router.js +39 -5
  30. package/dist/ipc/router.js.map +1 -1
  31. package/dist/mcp/debate-tools.js +48 -0
  32. package/dist/mcp/debate-tools.js.map +1 -1
  33. package/package.json +1 -1
@@ -0,0 +1,84 @@
1
+ import { describe, it, expect, vi, beforeEach } from 'vitest';
2
+ import { borgCommand } from '../borg.js';
3
+ // Mock ipc-helper
4
+ vi.mock('../../ipc-helper.js', () => ({
5
+ withIpc: vi.fn(async (fn) => {
6
+ const mockClient = {
7
+ request: vi.fn().mockImplementation((method) => {
8
+ if (method === 'borg.status') {
9
+ return {
10
+ enabled: true,
11
+ mode: 'selective',
12
+ syncIntervalMs: 60000,
13
+ totalSyncs: 5,
14
+ totalSent: 12,
15
+ totalReceived: 8,
16
+ lastSync: '2026-03-06T12:00:00Z',
17
+ };
18
+ }
19
+ if (method === 'borg.enable')
20
+ return { enabled: true };
21
+ if (method === 'borg.disable')
22
+ return { enabled: false };
23
+ if (method === 'borg.sync')
24
+ return { synced: true };
25
+ if (method === 'borg.history') {
26
+ return [
27
+ { timestamp: '2026-03-06T12:00:00Z', direction: 'sent', peer: 'trading-brain', itemCount: 5, accepted: 3, rejected: 2 },
28
+ { timestamp: '2026-03-06T12:01:00Z', direction: 'received', peer: 'marketing-brain', itemCount: 4, accepted: 4, rejected: 0 },
29
+ ];
30
+ }
31
+ return null;
32
+ }),
33
+ };
34
+ return fn(mockClient);
35
+ }),
36
+ }));
37
+ describe('borgCommand', () => {
38
+ beforeEach(() => {
39
+ vi.clearAllMocks();
40
+ vi.spyOn(console, 'log').mockImplementation(() => { });
41
+ });
42
+ it('creates a valid commander command', () => {
43
+ const cmd = borgCommand();
44
+ expect(cmd.name()).toBe('borg');
45
+ expect(cmd.commands.length).toBeGreaterThanOrEqual(5);
46
+ });
47
+ it('has status, enable, disable, sync, history subcommands', () => {
48
+ const cmd = borgCommand();
49
+ expect(cmd.commands.find(c => c.name() === 'status')).toBeDefined();
50
+ expect(cmd.commands.find(c => c.name() === 'enable')).toBeDefined();
51
+ expect(cmd.commands.find(c => c.name() === 'disable')).toBeDefined();
52
+ expect(cmd.commands.find(c => c.name() === 'sync')).toBeDefined();
53
+ expect(cmd.commands.find(c => c.name() === 'history')).toBeDefined();
54
+ });
55
+ it('status command shows borg information', async () => {
56
+ const cmd = borgCommand();
57
+ const statusCmd = cmd.commands.find(c => c.name() === 'status');
58
+ await statusCmd.parseAsync([], { from: 'user' });
59
+ const { withIpc } = await import('../../ipc-helper.js');
60
+ expect(withIpc).toHaveBeenCalledTimes(1);
61
+ });
62
+ it('enable command enables borg mode', async () => {
63
+ const cmd = borgCommand();
64
+ const enableCmd = cmd.commands.find(c => c.name() === 'enable');
65
+ await enableCmd.parseAsync([], { from: 'user' });
66
+ const { withIpc } = await import('../../ipc-helper.js');
67
+ expect(withIpc).toHaveBeenCalledTimes(1);
68
+ });
69
+ it('sync command triggers manual sync', async () => {
70
+ const cmd = borgCommand();
71
+ const syncCmd = cmd.commands.find(c => c.name() === 'sync');
72
+ await syncCmd.parseAsync([], { from: 'user' });
73
+ const { withIpc } = await import('../../ipc-helper.js');
74
+ expect(withIpc).toHaveBeenCalledTimes(1);
75
+ });
76
+ it('history command shows sync history', async () => {
77
+ const cmd = borgCommand();
78
+ const historyCmd = cmd.commands.find(c => c.name() === 'history');
79
+ await historyCmd.parseAsync([], { from: 'user' });
80
+ const { withIpc } = await import('../../ipc-helper.js');
81
+ expect(withIpc).toHaveBeenCalledTimes(1);
82
+ });
83
+ });
84
+ //# sourceMappingURL=borg.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"borg.test.js","sourceRoot":"","sources":["../../../../src/cli/commands/__tests__/borg.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,69 @@
1
+ import { describe, it, expect, vi, beforeEach } from 'vitest';
2
+ import { pluginsCommand } from '../plugins.js';
3
+ // Mock ipc-helper
4
+ vi.mock('../../ipc-helper.js', () => ({
5
+ withIpc: vi.fn(async (fn) => {
6
+ const mockClient = {
7
+ request: vi.fn().mockImplementation((method) => {
8
+ if (method === 'plugin.list') {
9
+ return [
10
+ { name: 'hello-brain', version: '1.0.0', description: 'Example plugin', enabled: true, loadedAt: '2026-03-06T12:00:00Z', error: null },
11
+ { name: 'weather-brain', version: '0.2.0', description: 'Weather data', enabled: true, loadedAt: '2026-03-06T12:00:00Z', error: null },
12
+ ];
13
+ }
14
+ if (method === 'plugin.routes') {
15
+ return [
16
+ { plugin: 'hello-brain', method: 'stats' },
17
+ { plugin: 'weather-brain', method: 'forecast' },
18
+ ];
19
+ }
20
+ if (method === 'plugin.tools') {
21
+ return [
22
+ { plugin: 'hello-brain', name: 'greet', description: 'Say hello' },
23
+ ];
24
+ }
25
+ return null;
26
+ }),
27
+ };
28
+ return fn(mockClient);
29
+ }),
30
+ }));
31
+ describe('pluginsCommand', () => {
32
+ beforeEach(() => {
33
+ vi.clearAllMocks();
34
+ vi.spyOn(console, 'log').mockImplementation(() => { });
35
+ });
36
+ it('creates a valid commander command', () => {
37
+ const cmd = pluginsCommand();
38
+ expect(cmd.name()).toBe('plugins');
39
+ expect(cmd.commands.length).toBeGreaterThanOrEqual(3);
40
+ });
41
+ it('has list, routes, tools subcommands', () => {
42
+ const cmd = pluginsCommand();
43
+ expect(cmd.commands.find(c => c.name() === 'list')).toBeDefined();
44
+ expect(cmd.commands.find(c => c.name() === 'routes')).toBeDefined();
45
+ expect(cmd.commands.find(c => c.name() === 'tools')).toBeDefined();
46
+ });
47
+ it('list command shows plugin information', async () => {
48
+ const cmd = pluginsCommand();
49
+ const listCmd = cmd.commands.find(c => c.name() === 'list');
50
+ await listCmd.parseAsync([], { from: 'user' });
51
+ const { withIpc } = await import('../../ipc-helper.js');
52
+ expect(withIpc).toHaveBeenCalledTimes(1);
53
+ });
54
+ it('routes command shows plugin routes', async () => {
55
+ const cmd = pluginsCommand();
56
+ const routesCmd = cmd.commands.find(c => c.name() === 'routes');
57
+ await routesCmd.parseAsync([], { from: 'user' });
58
+ const { withIpc } = await import('../../ipc-helper.js');
59
+ expect(withIpc).toHaveBeenCalledTimes(1);
60
+ });
61
+ it('tools command shows plugin tools', async () => {
62
+ const cmd = pluginsCommand();
63
+ const toolsCmd = cmd.commands.find(c => c.name() === 'tools');
64
+ await toolsCmd.parseAsync([], { from: 'user' });
65
+ const { withIpc } = await import('../../ipc-helper.js');
66
+ expect(withIpc).toHaveBeenCalledTimes(1);
67
+ });
68
+ });
69
+ //# sourceMappingURL=plugins.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugins.test.js","sourceRoot":"","sources":["../../../../src/cli/commands/__tests__/plugins.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,63 @@
1
+ import { describe, it, expect, vi, beforeEach } from 'vitest';
2
+ import { watchdogCommand } from '../watchdog.js';
3
+ // Mock ipc-helper
4
+ vi.mock('../../ipc-helper.js', () => ({
5
+ withIpc: vi.fn(async (fn) => {
6
+ const mockClient = {
7
+ request: vi.fn().mockImplementation((method, params) => {
8
+ if (method === 'watchdog.status') {
9
+ return [
10
+ { name: 'brain', pid: 1234, running: true, healthy: true, uptime: 60000, restarts: 0, lastCrash: null },
11
+ { name: 'trading-brain', pid: 5678, running: true, healthy: false, uptime: 30000, restarts: 1, lastCrash: '2026-03-06T12:00:00Z' },
12
+ { name: 'marketing-brain', pid: null, running: false, healthy: false, uptime: null, restarts: 3, lastCrash: '2026-03-06T11:00:00Z' },
13
+ ];
14
+ }
15
+ if (method === 'watchdog.restart') {
16
+ const { name } = params;
17
+ return name === 'brain' || name === 'trading-brain' || name === 'marketing-brain';
18
+ }
19
+ return null;
20
+ }),
21
+ };
22
+ return fn(mockClient);
23
+ }),
24
+ }));
25
+ describe('watchdogCommand', () => {
26
+ beforeEach(() => {
27
+ vi.clearAllMocks();
28
+ vi.spyOn(console, 'log').mockImplementation(() => { });
29
+ });
30
+ it('creates a valid commander command', () => {
31
+ const cmd = watchdogCommand();
32
+ expect(cmd.name()).toBe('watchdog');
33
+ expect(cmd.commands.length).toBeGreaterThanOrEqual(2);
34
+ });
35
+ it('has status subcommand', () => {
36
+ const cmd = watchdogCommand();
37
+ const status = cmd.commands.find(c => c.name() === 'status');
38
+ expect(status).toBeDefined();
39
+ });
40
+ it('has restart subcommand', () => {
41
+ const cmd = watchdogCommand();
42
+ const restart = cmd.commands.find(c => c.name() === 'restart');
43
+ expect(restart).toBeDefined();
44
+ });
45
+ it('status command shows daemon information', async () => {
46
+ const cmd = watchdogCommand();
47
+ const statusCmd = cmd.commands.find(c => c.name() === 'status');
48
+ await statusCmd.parseAsync([], { from: 'user' });
49
+ const { withIpc } = await import('../../ipc-helper.js');
50
+ expect(withIpc).toHaveBeenCalledTimes(1);
51
+ // Check that console.log was called with output containing daemon names
52
+ const logs = console.log.mock.calls.map(c => c[0]).join('\n');
53
+ expect(logs).toContain('brain');
54
+ });
55
+ it('restart command sends restart request', async () => {
56
+ const cmd = watchdogCommand();
57
+ const restartCmd = cmd.commands.find(c => c.name() === 'restart');
58
+ await restartCmd.parseAsync(['brain'], { from: 'user' });
59
+ const { withIpc } = await import('../../ipc-helper.js');
60
+ expect(withIpc).toHaveBeenCalledTimes(1);
61
+ });
62
+ });
63
+ //# sourceMappingURL=watchdog.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"watchdog.test.js","sourceRoot":"","sources":["../../../../src/cli/commands/__tests__/watchdog.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import { Command } from 'commander';
2
+ export declare function borgCommand(): Command;
@@ -0,0 +1,77 @@
1
+ import { Command } from 'commander';
2
+ import { withIpc } from '../ipc-helper.js';
3
+ import { c, header, keyValue, divider } from '../colors.js';
4
+ export function borgCommand() {
5
+ const cmd = new Command('borg')
6
+ .description('Borg Mode — collective knowledge sync between brains');
7
+ cmd.command('status')
8
+ .description('Show Borg sync status')
9
+ .action(async () => {
10
+ await withIpc(async (client) => {
11
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
12
+ const status = await client.request('borg.status');
13
+ console.log(header('Borg Sync Status', '\u{1F916}'));
14
+ console.log(keyValue('Enabled', status.enabled ? c.green('yes') : c.dim('no')));
15
+ console.log(keyValue('Mode', c.value(status.mode ?? '-')));
16
+ console.log(keyValue('Sync Interval', `${(status.syncIntervalMs ?? 60000) / 1000}s`));
17
+ console.log(keyValue('Total Syncs', String(status.totalSyncs ?? 0)));
18
+ console.log(keyValue('Items Sent', String(status.totalSent ?? 0)));
19
+ console.log(keyValue('Items Received', String(status.totalReceived ?? 0)));
20
+ console.log(keyValue('Last Sync', status.lastSync ? new Date(status.lastSync).toLocaleString() : c.dim('never')));
21
+ console.log(divider());
22
+ if (!status.enabled) {
23
+ console.log(` ${c.dim('Borg mode is disabled. Enable with: brain borg enable')}`);
24
+ }
25
+ });
26
+ });
27
+ cmd.command('enable')
28
+ .description('Enable Borg sync')
29
+ .action(async () => {
30
+ await withIpc(async (client) => {
31
+ await client.request('borg.enable');
32
+ console.log(` ${c.green('Borg mode enabled')} — collective sync started`);
33
+ });
34
+ });
35
+ cmd.command('disable')
36
+ .description('Disable Borg sync')
37
+ .action(async () => {
38
+ await withIpc(async (client) => {
39
+ await client.request('borg.disable');
40
+ console.log(` ${c.dim('Borg mode disabled')}`);
41
+ });
42
+ });
43
+ cmd.command('sync')
44
+ .description('Trigger manual sync cycle')
45
+ .action(async () => {
46
+ await withIpc(async (client) => {
47
+ await client.request('borg.sync');
48
+ console.log(` ${c.green('Sync cycle completed')}`);
49
+ });
50
+ });
51
+ cmd.command('history')
52
+ .description('Show recent sync history')
53
+ .option('-n, --limit <n>', 'Number of entries', '20')
54
+ .action(async (opts) => {
55
+ await withIpc(async (client) => {
56
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
57
+ const history = await client.request('borg.history', { limit: parseInt(opts.limit, 10) });
58
+ if (!history?.length) {
59
+ console.log(` ${c.dim('No sync history yet.')}`);
60
+ return;
61
+ }
62
+ console.log(header(`${history.length} Sync Entries`, '\u{1F504}'));
63
+ for (const h of history) {
64
+ const dir = h.direction === 'sent' ? c.cyan('\u{2191} sent') : c.green('\u{2193} recv');
65
+ const time = new Date(h.timestamp).toLocaleTimeString();
66
+ console.log(` ${c.dim(time)} ${dir} ${c.value(h.peer.padEnd(20))} ${h.accepted}/${h.itemCount} accepted`);
67
+ }
68
+ console.log(divider());
69
+ });
70
+ });
71
+ // Default action: status
72
+ cmd.action(async () => {
73
+ await cmd.commands.find(c => c.name() === 'status').parseAsync([], { from: 'user' });
74
+ });
75
+ return cmd;
76
+ }
77
+ //# sourceMappingURL=borg.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"borg.js","sourceRoot":"","sources":["../../../src/cli/commands/borg.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import { Command } from 'commander';
2
+ export declare function pluginsCommand(): Command;
@@ -0,0 +1,75 @@
1
+ import { Command } from 'commander';
2
+ import { withIpc } from '../ipc-helper.js';
3
+ import { c, header, divider } from '../colors.js';
4
+ export function pluginsCommand() {
5
+ const cmd = new Command('plugins')
6
+ .description('Plugin management — list, inspect community plugins');
7
+ cmd.command('list')
8
+ .description('List loaded plugins')
9
+ .action(async () => {
10
+ await withIpc(async (client) => {
11
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
12
+ const plugins = await client.request('plugin.list');
13
+ if (!plugins?.length) {
14
+ console.log(` ${c.dim('No plugins loaded.')}`);
15
+ console.log(` ${c.dim('Place plugins in ~/.brain/plugins/ and restart.')}`);
16
+ return;
17
+ }
18
+ console.log(header(`${plugins.length} Plugins`, '\u{1F9E9}'));
19
+ for (const p of plugins) {
20
+ const status = p.enabled ? c.green('loaded') : c.red('disabled');
21
+ console.log(` ${c.cyan(p.name.padEnd(25))} v${c.value(p.version)} ${status}`);
22
+ if (p.description) {
23
+ console.log(` ${''.padEnd(25)} ${c.dim(p.description)}`);
24
+ }
25
+ if (p.error) {
26
+ console.log(` ${''.padEnd(25)} ${c.red(`Error: ${p.error}`)}`);
27
+ }
28
+ }
29
+ console.log(divider());
30
+ });
31
+ });
32
+ cmd.command('routes')
33
+ .description('List plugin IPC routes')
34
+ .action(async () => {
35
+ await withIpc(async (client) => {
36
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
37
+ const routes = await client.request('plugin.routes');
38
+ if (!routes?.length) {
39
+ console.log(` ${c.dim('No plugin routes registered.')}`);
40
+ return;
41
+ }
42
+ console.log(header(`${routes.length} Plugin Routes`, '\u{1F517}'));
43
+ for (const r of routes) {
44
+ console.log(` ${c.cyan(r.plugin.padEnd(20))} ${c.value(r.method)}`);
45
+ }
46
+ console.log(divider());
47
+ });
48
+ });
49
+ cmd.command('tools')
50
+ .description('List plugin MCP tools')
51
+ .action(async () => {
52
+ await withIpc(async (client) => {
53
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
54
+ const tools = await client.request('plugin.tools');
55
+ if (!tools?.length) {
56
+ console.log(` ${c.dim('No plugin tools registered.')}`);
57
+ return;
58
+ }
59
+ console.log(header(`${tools.length} Plugin Tools`, '\u{1F527}'));
60
+ for (const t of tools) {
61
+ console.log(` ${c.cyan(t.plugin.padEnd(20))} ${c.value(t.name)}`);
62
+ if (t.description) {
63
+ console.log(` ${''.padEnd(20)} ${c.dim(t.description)}`);
64
+ }
65
+ }
66
+ console.log(divider());
67
+ });
68
+ });
69
+ // Default action: list
70
+ cmd.action(async () => {
71
+ await cmd.commands.find(c => c.name() === 'list').parseAsync([], { from: 'user' });
72
+ });
73
+ return cmd;
74
+ }
75
+ //# sourceMappingURL=plugins.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugins.js","sourceRoot":"","sources":["../../../src/cli/commands/plugins.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import { Command } from 'commander';
2
+ export declare function serviceCommand(): Command;
@@ -0,0 +1,101 @@
1
+ import { Command } from 'commander';
2
+ import path from 'node:path';
3
+ import { c, header, divider } from '../colors.js';
4
+ import { WindowsServiceManager } from '@timmeck/brain-core';
5
+ const BRAINS = [
6
+ {
7
+ name: 'brain',
8
+ displayName: 'Brain Ecosystem — Brain',
9
+ description: 'Error memory, code intelligence & autonomous research daemon',
10
+ },
11
+ {
12
+ name: 'trading-brain',
13
+ displayName: 'Brain Ecosystem — Trading Brain',
14
+ description: 'Adaptive trading intelligence with signal learning daemon',
15
+ },
16
+ {
17
+ name: 'marketing-brain',
18
+ displayName: 'Brain Ecosystem — Marketing Brain',
19
+ description: 'Content strategy & social engagement daemon',
20
+ },
21
+ ];
22
+ function getEntryPoint(name) {
23
+ // Resolve from brain-core package location up to packages dir
24
+ const packagesDir = path.resolve(import.meta.dirname, '..', '..', '..', '..');
25
+ return path.join(packagesDir, name, 'dist', 'index.js');
26
+ }
27
+ export function serviceCommand() {
28
+ const cmd = new Command('service')
29
+ .description('Windows service management (install/uninstall/status)');
30
+ cmd.command('install')
31
+ .description('Install all brains as Windows services')
32
+ .action(() => {
33
+ const manager = new WindowsServiceManager();
34
+ if (!manager.isAvailable()) {
35
+ console.log(` ${c.red('\u2717')} Windows service management is only available on Windows.`);
36
+ return;
37
+ }
38
+ console.log(header('Installing Windows Services', '\u{1F3ED}'));
39
+ for (const brain of BRAINS) {
40
+ const entryPoint = getEntryPoint(brain.name);
41
+ const ok = manager.install({
42
+ name: brain.name,
43
+ displayName: brain.displayName,
44
+ description: brain.description,
45
+ entryPoint,
46
+ args: ['daemon'],
47
+ });
48
+ if (ok) {
49
+ console.log(` ${c.green('\u2713')} ${c.cyan(brain.name)} installed`);
50
+ }
51
+ else {
52
+ console.log(` ${c.red('\u2717')} ${c.cyan(brain.name)} failed to install`);
53
+ }
54
+ }
55
+ console.log(`\n ${c.dim('Start services with:')} ${c.cyan('sc start BrainEcosystem_brain')}`);
56
+ console.log(divider());
57
+ });
58
+ cmd.command('uninstall')
59
+ .description('Uninstall all brain Windows services')
60
+ .action(() => {
61
+ const manager = new WindowsServiceManager();
62
+ if (!manager.isAvailable()) {
63
+ console.log(` ${c.red('\u2717')} Windows service management is only available on Windows.`);
64
+ return;
65
+ }
66
+ console.log(header('Uninstalling Windows Services', '\u{1F3ED}'));
67
+ for (const brain of BRAINS) {
68
+ const ok = manager.uninstall(brain.name);
69
+ if (ok) {
70
+ console.log(` ${c.green('\u2713')} ${c.cyan(brain.name)} uninstalled`);
71
+ }
72
+ else {
73
+ console.log(` ${c.red('\u2717')} ${c.cyan(brain.name)} failed to uninstall`);
74
+ }
75
+ }
76
+ console.log(divider());
77
+ });
78
+ cmd.command('status')
79
+ .description('Show Windows service status for all brains')
80
+ .action(() => {
81
+ const manager = new WindowsServiceManager();
82
+ if (!manager.isAvailable()) {
83
+ console.log(` ${c.red('\u2717')} Windows service management is only available on Windows.`);
84
+ return;
85
+ }
86
+ console.log(header('Windows Service Status', '\u{1F3ED}'));
87
+ const statuses = manager.queryAll();
88
+ for (const s of statuses) {
89
+ const stateColor = s.state === 'running' ? c.green : s.state === 'stopped' ? c.red : c.orange;
90
+ const installed = s.installed ? c.green('installed') : c.dim('not installed');
91
+ console.log(` ${c.cyan(s.name.padEnd(20))} ${stateColor(s.state.padEnd(12))} ${installed}`);
92
+ }
93
+ console.log(divider());
94
+ });
95
+ // Default action: show status
96
+ cmd.action(() => {
97
+ cmd.commands.find(c => c.name() === 'status').parse([], { from: 'user' });
98
+ });
99
+ return cmd;
100
+ }
101
+ //# sourceMappingURL=service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"service.js","sourceRoot":"","sources":["../../../src/cli/commands/service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import { Command } from 'commander';
2
+ export declare function watchdogCommand(): Command;
@@ -0,0 +1,69 @@
1
+ import { Command } from 'commander';
2
+ import { withIpc } from '../ipc-helper.js';
3
+ import { c, header, divider } from '../colors.js';
4
+ function fmtUptime(ms) {
5
+ const s = Math.floor(ms / 1000);
6
+ if (s < 60)
7
+ return `${s}s`;
8
+ if (s < 3600)
9
+ return `${Math.floor(s / 60)}m ${s % 60}s`;
10
+ const h = Math.floor(s / 3600);
11
+ const m = Math.floor((s % 3600) / 60);
12
+ return `${h}h ${m}m`;
13
+ }
14
+ function statusIcon(running, healthy) {
15
+ if (!running)
16
+ return c.red('STOPPED');
17
+ if (healthy)
18
+ return c.green('HEALTHY');
19
+ return c.orange('UNHEALTHY');
20
+ }
21
+ export function watchdogCommand() {
22
+ const cmd = new Command('watchdog')
23
+ .description('Watchdog — daemon monitoring and control');
24
+ cmd.command('status')
25
+ .description('Show status of all monitored daemons')
26
+ .action(async () => {
27
+ await withIpc(async (client) => {
28
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
29
+ const daemons = await client.request('watchdog.status');
30
+ if (!daemons?.length) {
31
+ console.log(` ${c.dim('No daemons configured.')}`);
32
+ return;
33
+ }
34
+ console.log(header('Watchdog Status', '\u{1F6E1}'));
35
+ for (const d of daemons) {
36
+ const status = statusIcon(d.running, d.healthy);
37
+ const uptime = d.uptime ? fmtUptime(d.uptime) : '-';
38
+ console.log(` ${c.cyan(d.name.padEnd(20))} ${status.padEnd(20)} PID: ${c.value(d.pid || '-')} Uptime: ${c.value(uptime)} Restarts: ${c.value(d.restarts || 0)}`);
39
+ if (d.lastCrash) {
40
+ console.log(` ${''.padEnd(20)} ${c.dim(`Last crash: ${d.lastCrash}`)}`);
41
+ }
42
+ }
43
+ const running = daemons.filter(d => d.running).length;
44
+ const healthy = daemons.filter(d => d.running && d.healthy).length;
45
+ console.log(`\n ${c.dim(`${running}/${daemons.length} running, ${healthy}/${daemons.length} healthy`)}`);
46
+ console.log(divider());
47
+ });
48
+ });
49
+ cmd.command('restart')
50
+ .description('Restart a specific daemon')
51
+ .argument('<name>', 'Daemon name (brain, trading-brain, marketing-brain)')
52
+ .action(async (name) => {
53
+ await withIpc(async (client) => {
54
+ const result = await client.request('watchdog.restart', { name });
55
+ if (result) {
56
+ console.log(` ${c.green('\u2713')} Restart signal sent to ${c.cyan(name)}`);
57
+ }
58
+ else {
59
+ console.log(` ${c.red('\u2717')} Unknown daemon: ${c.cyan(name)}`);
60
+ }
61
+ });
62
+ });
63
+ // Default action: show status
64
+ cmd.action(async () => {
65
+ await cmd.commands.find(c => c.name() === 'status').parseAsync([], { from: 'user' });
66
+ });
67
+ return cmd;
68
+ }
69
+ //# sourceMappingURL=watchdog.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"watchdog.js","sourceRoot":"","sources":["../../../src/cli/commands/watchdog.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAC3C,OAAO,EAAE,CAAC,EAAE,MAAM,EAAY,OAAO,EAAS,MAAM,cAAc,CAAC;AAEnE,SAAS,SAAS,CAAC,EAAU;IAC3B,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,GAAG,IAAI,CAAC,CAAC;IAChC,IAAI,CAAC,GAAG,EAAE;QAAE,OAAO,GAAG,CAAC,GAAG,CAAC;IAC3B,IAAI,CAAC,GAAG,IAAI;QAAE,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,GAAG,CAAC;IACzD,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;IAC/B,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;IACtC,OAAO,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC;AACvB,CAAC;AAED,SAAS,UAAU,CAAC,OAAgB,EAAE,OAAgB;IACpD,IAAI,CAAC,OAAO;QAAE,OAAO,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;IACtC,IAAI,OAAO;QAAE,OAAO,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;IACvC,OAAO,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;AAC/B,CAAC;AAED,MAAM,UAAU,eAAe;IAC7B,MAAM,GAAG,GAAG,IAAI,OAAO,CAAC,UAAU,CAAC;SAChC,WAAW,CAAC,0CAA0C,CAAC,CAAC;IAE3D,GAAG,CAAC,OAAO,CAAC,QAAQ,CAAC;SAClB,WAAW,CAAC,sCAAsC,CAAC;SACnD,MAAM,CAAC,KAAK,IAAI,EAAE;QACjB,MAAM,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE;YAC7B,8DAA8D;YAC9D,MAAM,OAAO,GAAU,MAAM,MAAM,CAAC,OAAO,CAAC,iBAAiB,CAAU,CAAC;YAExE,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,CAAC;gBACrB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,wBAAwB,CAAC,EAAE,CAAC,CAAC;gBACpD,OAAO;YACT,CAAC;YAED,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,iBAAiB,EAAE,WAAW,CAAC,CAAC,CAAC;YACpD,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;gBACxB,MAAM,MAAM,GAAG,UAAU,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC;gBAChD,MAAM,MAAM,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;gBACpD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,SAAS,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,IAAI,GAAG,CAAC,aAAa,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,QAAQ,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC;gBACpK,IAAI,CAAC,CAAC,SAAS,EAAE,CAAC;oBAChB,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC,SAAS,EAAE,CAAC,EAAE,CAAC,CAAC;gBAC3E,CAAC;YACH,CAAC;YAED,MAAM,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC;YACtD,MAAM,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC;YACnE,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,GAAG,OAAO,IAAI,OAAO,CAAC,MAAM,aAAa,OAAO,IAAI,OAAO,CAAC,MAAM,UAAU,CAAC,EAAE,CAAC,CAAC;YAC1G,OAAO,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;QACzB,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEL,GAAG,CAAC,OAAO,CAAC,SAAS,CAAC;SACnB,WAAW,CAAC,2BAA2B,CAAC;SACxC,QAAQ,CAAC,QAAQ,EAAE,qDAAqD,CAAC;SACzE,MAAM,CAAC,KAAK,EAAE,IAAY,EAAE,EAAE;QAC7B,MAAM,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE;YAC7B,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,kBAAkB,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;YAClE,IAAI,MAAM,EAAE,CAAC;gBACX,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,2BAA2B,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YAC/E,CAAC;iBAAM,CAAC;gBACN,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,oBAAoB,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACtE,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEL,8BAA8B;IAC9B,GAAG,CAAC,MAAM,CAAC,KAAK,IAAI,EAAE;QACpB,MAAM,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,KAAK,QAAQ,CAAE,CAAC,UAAU,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;IACxF,CAAC,CAAC,CAAC;IAEH,OAAO,GAAG,CAAC;AACb,CAAC"}