@timmeck/brain-core 1.1.0 → 1.5.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/README.md +66 -14
- package/brain.log +6 -0
- package/dist/config/__tests__/loader.test.d.ts +1 -0
- package/dist/config/__tests__/loader.test.js +85 -0
- package/dist/config/__tests__/loader.test.js.map +1 -0
- package/dist/config/loader.d.ts +15 -0
- package/dist/config/loader.js +39 -0
- package/dist/config/loader.js.map +1 -0
- package/dist/cross-brain/__tests__/client.test.d.ts +1 -0
- package/dist/cross-brain/__tests__/client.test.js +31 -0
- package/dist/cross-brain/__tests__/client.test.js.map +1 -0
- package/dist/cross-brain/__tests__/notifications.test.d.ts +1 -0
- package/dist/cross-brain/__tests__/notifications.test.js +52 -0
- package/dist/cross-brain/__tests__/notifications.test.js.map +1 -0
- package/dist/cross-brain/notifications.d.ts +25 -0
- package/dist/cross-brain/notifications.js +51 -0
- package/dist/cross-brain/notifications.js.map +1 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.js +14 -0
- package/dist/index.js.map +1 -1
- package/dist/ipc/__tests__/protocol.test.d.ts +1 -0
- package/dist/ipc/__tests__/protocol.test.js +69 -0
- package/dist/ipc/__tests__/protocol.test.js.map +1 -0
- package/dist/learning/__tests__/base-engine.test.d.ts +1 -0
- package/dist/learning/__tests__/base-engine.test.js +49 -0
- package/dist/learning/__tests__/base-engine.test.js.map +1 -0
- package/dist/learning/base-engine.d.ts +16 -0
- package/dist/learning/base-engine.js +30 -0
- package/dist/learning/base-engine.js.map +1 -0
- package/dist/math/__tests__/time-decay.test.d.ts +1 -0
- package/dist/math/__tests__/time-decay.test.js +37 -0
- package/dist/math/__tests__/time-decay.test.js.map +1 -0
- package/dist/math/__tests__/wilson-score.test.d.ts +1 -0
- package/dist/math/__tests__/wilson-score.test.js +43 -0
- package/dist/math/__tests__/wilson-score.test.js.map +1 -0
- package/dist/math/time-decay.d.ts +10 -0
- package/dist/math/time-decay.js +16 -0
- package/dist/math/time-decay.js.map +1 -0
- package/dist/math/wilson-score.d.ts +10 -0
- package/dist/math/wilson-score.js +21 -0
- package/dist/math/wilson-score.js.map +1 -0
- package/dist/research/__tests__/base-engine.test.d.ts +1 -0
- package/dist/research/__tests__/base-engine.test.js +56 -0
- package/dist/research/__tests__/base-engine.test.js.map +1 -0
- package/dist/research/base-engine.d.ts +20 -0
- package/dist/research/base-engine.js +46 -0
- package/dist/research/base-engine.js.map +1 -0
- package/dist/synapses/__tests__/activation.test.d.ts +1 -0
- package/dist/synapses/__tests__/activation.test.js +87 -0
- package/dist/synapses/__tests__/activation.test.js.map +1 -0
- package/dist/synapses/__tests__/decay.test.d.ts +1 -0
- package/dist/synapses/__tests__/decay.test.js +73 -0
- package/dist/synapses/__tests__/decay.test.js.map +1 -0
- package/dist/synapses/__tests__/hebbian.test.d.ts +1 -0
- package/dist/synapses/__tests__/hebbian.test.js +95 -0
- package/dist/synapses/__tests__/hebbian.test.js.map +1 -0
- package/dist/synapses/__tests__/pathfinder.test.d.ts +1 -0
- package/dist/synapses/__tests__/pathfinder.test.js +74 -0
- package/dist/synapses/__tests__/pathfinder.test.js.map +1 -0
- package/dist/synapses/__tests__/synapse-manager.test.d.ts +1 -0
- package/dist/synapses/__tests__/synapse-manager.test.js +94 -0
- package/dist/synapses/__tests__/synapse-manager.test.js.map +1 -0
- package/dist/synapses/activation.d.ts +6 -0
- package/dist/synapses/activation.js +54 -0
- package/dist/synapses/activation.js.map +1 -0
- package/dist/synapses/decay.d.ts +9 -0
- package/dist/synapses/decay.js +26 -0
- package/dist/synapses/decay.js.map +1 -0
- package/dist/synapses/hebbian.d.ts +12 -0
- package/dist/synapses/hebbian.js +45 -0
- package/dist/synapses/hebbian.js.map +1 -0
- package/dist/synapses/pathfinder.d.ts +6 -0
- package/dist/synapses/pathfinder.js +54 -0
- package/dist/synapses/pathfinder.js.map +1 -0
- package/dist/synapses/synapse-manager.d.ts +35 -0
- package/dist/synapses/synapse-manager.js +72 -0
- package/dist/synapses/synapse-manager.js.map +1 -0
- package/dist/synapses/types.d.ts +85 -0
- package/dist/synapses/types.js +7 -0
- package/dist/synapses/types.js.map +1 -0
- package/dist/utils/__tests__/events.test.d.ts +1 -0
- package/dist/utils/__tests__/events.test.js +38 -0
- package/dist/utils/__tests__/events.test.js.map +1 -0
- package/dist/utils/__tests__/hash.test.d.ts +1 -0
- package/dist/utils/__tests__/hash.test.js +25 -0
- package/dist/utils/__tests__/hash.test.js.map +1 -0
- package/dist/utils/__tests__/logger.test.d.ts +1 -0
- package/dist/utils/__tests__/logger.test.js +29 -0
- package/dist/utils/__tests__/logger.test.js.map +1 -0
- package/dist/utils/__tests__/paths.test.d.ts +1 -0
- package/dist/utils/__tests__/paths.test.js +50 -0
- package/dist/utils/__tests__/paths.test.js.map +1 -0
- package/eslint.config.js +14 -0
- package/package.json +17 -2
- package/.github/FUNDING.yml +0 -1
- package/.github/workflows/ci.yml +0 -21
- package/src/api/server.ts +0 -210
- package/src/cli/colors.ts +0 -105
- package/src/cross-brain/client.ts +0 -94
- package/src/db/connection.ts +0 -22
- package/src/index.ts +0 -35
- package/src/ipc/client.ts +0 -117
- package/src/ipc/protocol.ts +0 -35
- package/src/ipc/server.ts +0 -170
- package/src/mcp/http-server.ts +0 -148
- package/src/mcp/server.ts +0 -84
- package/src/types/ipc.types.ts +0 -8
- package/src/utils/events.ts +0 -30
- package/src/utils/hash.ts +0 -5
- package/src/utils/logger.ts +0 -67
- package/src/utils/paths.ts +0 -24
- package/tsconfig.json +0 -18
package/README.md
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
[](LICENSE)
|
|
6
6
|
[](https://github.com/timmeck/brain-core)
|
|
7
7
|
|
|
8
|
-
**Shared infrastructure for the Brain ecosystem — IPC, MCP, CLI, DB, and utilities.**
|
|
8
|
+
**Shared infrastructure for the Brain ecosystem — IPC, MCP, CLI, DB, math, synapses, and utilities.**
|
|
9
9
|
|
|
10
10
|
Brain Core extracts the common infrastructure used across all Brain MCP servers ([Brain](https://github.com/timmeck/brain), [Trading Brain](https://github.com/timmeck/trading-brain), [Marketing Brain](https://github.com/timmeck/marketing-brain)) into a single, reusable package.
|
|
11
11
|
|
|
@@ -23,6 +23,15 @@ Brain Core extracts the common infrastructure used across all Brain MCP servers
|
|
|
23
23
|
| **CLI Colors** | Shared color palette, formatting helpers (header, table, badges) |
|
|
24
24
|
| **Logger** | Winston-based structured logging with file rotation |
|
|
25
25
|
| **Event Bus** | Generic typed event emitter |
|
|
26
|
+
| **Cross-Brain Client** | Discover and query peer brains over IPC named pipes |
|
|
27
|
+
| **Cross-Brain Notifier** | Push event notifications to peer brains (new in v1.5) |
|
|
28
|
+
| **Math — Wilson Score** | Statistical confidence intervals for win rates / rule confidence |
|
|
29
|
+
| **Math — Time Decay** | Exponential half-life decay for synapse and rule freshness |
|
|
30
|
+
| **Config Loader** | `deepMerge()` + `loadConfigFile()` for layered config |
|
|
31
|
+
| **Synapse Algorithms** | Hebbian learning, decay, spreading activation, A* pathfinding |
|
|
32
|
+
| **BaseSynapseManager** | Abstract synapse manager with strengthen/weaken/activate/findPath/decay |
|
|
33
|
+
| **BaseLearningEngine** | Abstract timer-managed learning engine with error handling |
|
|
34
|
+
| **BaseResearchEngine** | Abstract timer-managed research engine with optional initial delay |
|
|
26
35
|
| **Utils** | Path normalization, data dir resolution, SHA-256 hashing |
|
|
27
36
|
|
|
28
37
|
## Installation
|
|
@@ -120,24 +129,67 @@ class MyRouter implements IpcRouter {
|
|
|
120
129
|
|
|
121
130
|
```
|
|
122
131
|
@timmeck/brain-core
|
|
123
|
-
├── Types
|
|
124
|
-
├── Utils
|
|
125
|
-
├── DB
|
|
126
|
-
├── IPC
|
|
127
|
-
├── MCP
|
|
128
|
-
├── CLI
|
|
129
|
-
|
|
132
|
+
├── Types ──────── IpcMessage, SynapseRecord, NodeRef, NetworkStats
|
|
133
|
+
├── Utils ──────── hash, logger, paths, events
|
|
134
|
+
├── DB ─────────── SQLite connection (WAL mode)
|
|
135
|
+
├── IPC ────────── protocol, server, client
|
|
136
|
+
├── MCP ────────── stdio server, HTTP/SSE server
|
|
137
|
+
├── CLI ────────── colors, formatting helpers
|
|
138
|
+
├── API ────────── BaseApiServer (CORS, auth, RPC, SSE)
|
|
139
|
+
├── Math ───────── Wilson Score, Time Decay
|
|
140
|
+
├── Config ─────── deepMerge, loadConfigFile
|
|
141
|
+
├── Synapses ───── Hebbian, Decay, Activation, Pathfinder, BaseSynapseManager
|
|
142
|
+
├── Learning ───── BaseLearningEngine (abstract, timer-managed)
|
|
143
|
+
├── Research ───── BaseResearchEngine (abstract, timer-managed)
|
|
144
|
+
└── Cross-Brain ── CrossBrainClient, CrossBrainNotifier
|
|
130
145
|
```
|
|
131
146
|
|
|
132
147
|
## Brain Ecosystem
|
|
133
148
|
|
|
134
|
-
| Brain | Purpose | Ports |
|
|
135
|
-
|
|
136
|
-
| [Brain](https://github.com/timmeck/brain) | Error memory & code intelligence | 7777/7778 |
|
|
137
|
-
| [Trading Brain](https://github.com/timmeck/trading-brain) | Adaptive trading intelligence | 7779/7780 |
|
|
138
|
-
| [Marketing Brain](https://github.com/timmeck/marketing-brain) | Content strategy & social media | 7781/7782 |
|
|
149
|
+
| Brain | Version | Purpose | Ports |
|
|
150
|
+
|-------|---------|---------|-------|
|
|
151
|
+
| [Brain](https://github.com/timmeck/brain) | v2.1.0 | Error memory & code intelligence | 7777/7778 |
|
|
152
|
+
| [Trading Brain](https://github.com/timmeck/trading-brain) | v1.2.0 | Adaptive trading intelligence | 7779/7780 |
|
|
153
|
+
| [Marketing Brain](https://github.com/timmeck/marketing-brain) | v0.4.0 | Content strategy & social media | 7781/7782/7783 |
|
|
154
|
+
| [Brain Core](https://github.com/timmeck/brain-core) | v1.6.0 | Shared infrastructure (this package) | — |
|
|
139
155
|
|
|
140
|
-
All three brains are standalone — brain-core is an **optional** shared dependency that eliminates code
|
|
156
|
+
All three brains are standalone — brain-core is an **optional** shared dependency that eliminates ~600 lines of duplicated code across the ecosystem.
|
|
157
|
+
|
|
158
|
+
## Cross-Brain Communication
|
|
159
|
+
|
|
160
|
+
`CrossBrainClient` lets brains discover and query each other over IPC named pipes. Each brain exposes a `status` IPC method returning its name, version, uptime, pid, and method count — enabling automatic peer discovery without central coordination.
|
|
161
|
+
|
|
162
|
+
```typescript
|
|
163
|
+
import { CrossBrainClient, CrossBrainNotifier } from '@timmeck/brain-core';
|
|
164
|
+
|
|
165
|
+
// Query peers
|
|
166
|
+
const cross = new CrossBrainClient('brain');
|
|
167
|
+
const peers = await cross.getAvailablePeers();
|
|
168
|
+
// → [{ name: 'trading-brain', version: '1.2.0', uptime: 3600, pid: 12345, methods: 18 }, ...]
|
|
169
|
+
|
|
170
|
+
// Push event notifications to peers (v1.5+)
|
|
171
|
+
const notifier = new CrossBrainNotifier(cross, 'brain');
|
|
172
|
+
notifier.notify('error:reported', { errorId: 42, fingerprint: 'ENOENT' });
|
|
173
|
+
notifier.notifyPeer('trading-brain', 'insight:created', { insightId: 7 });
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
### Base Engines
|
|
177
|
+
|
|
178
|
+
Abstract base classes eliminate timer boilerplate from learning and research engines:
|
|
179
|
+
|
|
180
|
+
```typescript
|
|
181
|
+
import { BaseLearningEngine, BaseResearchEngine } from '@timmeck/brain-core';
|
|
182
|
+
|
|
183
|
+
class MyLearningEngine extends BaseLearningEngine {
|
|
184
|
+
runCycle() { /* your learning logic */ }
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
class MyResearchEngine extends BaseResearchEngine {
|
|
188
|
+
runCycle() { /* your research logic */ }
|
|
189
|
+
}
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
Visit the [Brain Hub](https://timmeck.github.io/brain-hub/) for the full ecosystem overview.
|
|
141
193
|
|
|
142
194
|
## License
|
|
143
195
|
|
package/brain.log
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
2026-02-27T15:33:52.574Z [error] {"error":"Error: boom"} Learning cycle error
|
|
2
|
+
2026-02-27T15:33:52.575Z [error] {"error":"Error: boom"} Research cycle error
|
|
3
|
+
2026-02-27T15:36:06.467Z [error] {"error":"Error: boom"} Learning cycle error
|
|
4
|
+
2026-02-27T15:36:06.471Z [error] {"error":"Error: boom"} Research cycle error
|
|
5
|
+
2026-02-27T15:40:43.982Z [error] {"error":"Error: boom"} Research cycle error
|
|
6
|
+
2026-02-27T15:40:43.982Z [error] {"error":"Error: boom"} Learning cycle error
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
|
|
2
|
+
import fs from 'node:fs';
|
|
3
|
+
import { deepMerge, loadConfigFile } from '../loader.js';
|
|
4
|
+
describe('deepMerge', () => {
|
|
5
|
+
it('merges flat properties', () => {
|
|
6
|
+
const target = { a: 1, b: 2 };
|
|
7
|
+
deepMerge(target, { b: 3, c: 4 });
|
|
8
|
+
expect(target).toEqual({ a: 1, b: 3, c: 4 });
|
|
9
|
+
});
|
|
10
|
+
it('merges nested objects recursively', () => {
|
|
11
|
+
const target = { api: { port: 7777, enabled: true } };
|
|
12
|
+
deepMerge(target, { api: { port: 8080 } });
|
|
13
|
+
expect(target).toEqual({ api: { port: 8080, enabled: true } });
|
|
14
|
+
});
|
|
15
|
+
it('overwrites arrays (no merge)', () => {
|
|
16
|
+
const target = { tags: ['a', 'b'] };
|
|
17
|
+
deepMerge(target, { tags: ['c'] });
|
|
18
|
+
expect(target).toEqual({ tags: ['c'] });
|
|
19
|
+
});
|
|
20
|
+
it('ignores undefined values', () => {
|
|
21
|
+
const target = { a: 1 };
|
|
22
|
+
deepMerge(target, { a: undefined, b: 2 });
|
|
23
|
+
expect(target).toEqual({ a: 1, b: 2 });
|
|
24
|
+
});
|
|
25
|
+
it('handles deeply nested merge', () => {
|
|
26
|
+
const target = {
|
|
27
|
+
level1: {
|
|
28
|
+
level2: {
|
|
29
|
+
level3: { keep: true, replace: 'old' },
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
};
|
|
33
|
+
deepMerge(target, {
|
|
34
|
+
level1: { level2: { level3: { replace: 'new' } } },
|
|
35
|
+
});
|
|
36
|
+
expect(target.level1.level2.level3).toEqual({ keep: true, replace: 'new' });
|
|
37
|
+
});
|
|
38
|
+
});
|
|
39
|
+
describe('loadConfigFile', () => {
|
|
40
|
+
beforeEach(() => {
|
|
41
|
+
vi.spyOn(fs, 'existsSync');
|
|
42
|
+
vi.spyOn(fs, 'readFileSync');
|
|
43
|
+
});
|
|
44
|
+
afterEach(() => {
|
|
45
|
+
vi.restoreAllMocks();
|
|
46
|
+
});
|
|
47
|
+
it('returns defaults when no file exists', () => {
|
|
48
|
+
vi.mocked(fs.existsSync).mockReturnValue(false);
|
|
49
|
+
const defaults = { port: 8080, name: 'test' };
|
|
50
|
+
const result = loadConfigFile(defaults);
|
|
51
|
+
expect(result).toEqual(defaults);
|
|
52
|
+
});
|
|
53
|
+
it('merges config file into defaults', () => {
|
|
54
|
+
vi.mocked(fs.existsSync).mockReturnValue(true);
|
|
55
|
+
vi.mocked(fs.readFileSync).mockReturnValue(JSON.stringify({ port: 9090 }));
|
|
56
|
+
const defaults = { port: 8080, name: 'test' };
|
|
57
|
+
const result = loadConfigFile(defaults, '/some/config.json');
|
|
58
|
+
expect(result).toEqual({ port: 9090, name: 'test' });
|
|
59
|
+
});
|
|
60
|
+
it('uses defaultConfigPath as fallback', () => {
|
|
61
|
+
vi.mocked(fs.existsSync).mockReturnValue(true);
|
|
62
|
+
vi.mocked(fs.readFileSync).mockReturnValue(JSON.stringify({ name: 'custom' }));
|
|
63
|
+
const defaults = { port: 8080, name: 'test' };
|
|
64
|
+
const result = loadConfigFile(defaults, undefined, '/default/config.json');
|
|
65
|
+
expect(result).toEqual({ port: 8080, name: 'custom' });
|
|
66
|
+
expect(fs.existsSync).toHaveBeenCalledWith('/default/config.json');
|
|
67
|
+
});
|
|
68
|
+
it('does not mutate original defaults', () => {
|
|
69
|
+
vi.mocked(fs.existsSync).mockReturnValue(true);
|
|
70
|
+
vi.mocked(fs.readFileSync).mockReturnValue(JSON.stringify({ port: 9090 }));
|
|
71
|
+
const defaults = { port: 8080, name: 'test' };
|
|
72
|
+
loadConfigFile(defaults, '/some/config.json');
|
|
73
|
+
expect(defaults.port).toBe(8080);
|
|
74
|
+
});
|
|
75
|
+
it('handles nested config merge', () => {
|
|
76
|
+
vi.mocked(fs.existsSync).mockReturnValue(true);
|
|
77
|
+
vi.mocked(fs.readFileSync).mockReturnValue(JSON.stringify({
|
|
78
|
+
api: { port: 9999 },
|
|
79
|
+
}));
|
|
80
|
+
const defaults = { api: { port: 8080, enabled: true } };
|
|
81
|
+
const result = loadConfigFile(defaults, '/some/config.json');
|
|
82
|
+
expect(result).toEqual({ api: { port: 9999, enabled: true } });
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
//# sourceMappingURL=loader.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loader.test.js","sourceRoot":"","sources":["../../../src/config/__tests__/loader.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Deep-merge source into target. Recursively merges nested objects,
|
|
3
|
+
* overwrites primitives and arrays.
|
|
4
|
+
*/
|
|
5
|
+
export declare function deepMerge(target: Record<string, unknown>, source: Record<string, unknown>): void;
|
|
6
|
+
/**
|
|
7
|
+
* Load and parse a JSON config file, merging it into defaults.
|
|
8
|
+
* If the file doesn't exist, returns the defaults unchanged.
|
|
9
|
+
*
|
|
10
|
+
* @param defaults The default config object (will be cloned)
|
|
11
|
+
* @param configPath Explicit config file path, or undefined for auto-detect
|
|
12
|
+
* @param defaultConfigPath Fallback path when configPath is not provided
|
|
13
|
+
* @returns Merged config object
|
|
14
|
+
*/
|
|
15
|
+
export declare function loadConfigFile<T>(defaults: T, configPath?: string, defaultConfigPath?: string): T;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
/**
|
|
4
|
+
* Deep-merge source into target. Recursively merges nested objects,
|
|
5
|
+
* overwrites primitives and arrays.
|
|
6
|
+
*/
|
|
7
|
+
export function deepMerge(target, source) {
|
|
8
|
+
for (const key of Object.keys(source)) {
|
|
9
|
+
const val = source[key];
|
|
10
|
+
if (val && typeof val === 'object' && !Array.isArray(val) && target[key] && typeof target[key] === 'object') {
|
|
11
|
+
deepMerge(target[key], val);
|
|
12
|
+
}
|
|
13
|
+
else if (val !== undefined) {
|
|
14
|
+
target[key] = val;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Load and parse a JSON config file, merging it into defaults.
|
|
20
|
+
* If the file doesn't exist, returns the defaults unchanged.
|
|
21
|
+
*
|
|
22
|
+
* @param defaults The default config object (will be cloned)
|
|
23
|
+
* @param configPath Explicit config file path, or undefined for auto-detect
|
|
24
|
+
* @param defaultConfigPath Fallback path when configPath is not provided
|
|
25
|
+
* @returns Merged config object
|
|
26
|
+
*/
|
|
27
|
+
export function loadConfigFile(defaults, configPath, defaultConfigPath) {
|
|
28
|
+
const config = structuredClone(defaults);
|
|
29
|
+
const filePath = configPath
|
|
30
|
+
? path.resolve(configPath)
|
|
31
|
+
: defaultConfigPath;
|
|
32
|
+
if (filePath && fs.existsSync(filePath)) {
|
|
33
|
+
const raw = fs.readFileSync(filePath, 'utf-8');
|
|
34
|
+
const fileConfig = JSON.parse(raw);
|
|
35
|
+
deepMerge(config, fileConfig);
|
|
36
|
+
}
|
|
37
|
+
return config;
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=loader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loader.js","sourceRoot":"","sources":["../../src/config/loader.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B;;;GAGG;AACH,MAAM,UAAU,SAAS,CAAC,MAA+B,EAAE,MAA+B;IACxF,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;QACtC,MAAM,GAAG,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;QACxB,IAAI,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,IAAI,OAAO,MAAM,CAAC,GAAG,CAAC,KAAK,QAAQ,EAAE,CAAC;YAC5G,SAAS,CAAC,MAAM,CAAC,GAAG,CAA4B,EAAE,GAA8B,CAAC,CAAC;QACpF,CAAC;aAAM,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;YAC7B,MAAM,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC;QACpB,CAAC;IACH,CAAC;AACH,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,cAAc,CAC5B,QAAW,EACX,UAAmB,EACnB,iBAA0B;IAE1B,MAAM,MAAM,GAAG,eAAe,CAAC,QAAQ,CAAC,CAAC;IAEzC,MAAM,QAAQ,GAAG,UAAU;QACzB,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC;QAC1B,CAAC,CAAC,iBAAiB,CAAC;IAEtB,IAAI,QAAQ,IAAI,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QACxC,MAAM,GAAG,GAAG,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QAC/C,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAe,CAAC;QACjD,SAAS,CAAC,MAA4C,EAAE,UAAgD,CAAC,CAAC;IAC5G,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import { CrossBrainClient } from '../client.js';
|
|
3
|
+
describe('CrossBrainClient', () => {
|
|
4
|
+
it('filters self from peers', () => {
|
|
5
|
+
const client = new CrossBrainClient('brain');
|
|
6
|
+
const names = client.getPeerNames();
|
|
7
|
+
expect(names).not.toContain('brain');
|
|
8
|
+
expect(names).toContain('trading-brain');
|
|
9
|
+
expect(names).toContain('marketing-brain');
|
|
10
|
+
});
|
|
11
|
+
it('returns empty for unavailable peers', async () => {
|
|
12
|
+
const client = new CrossBrainClient('brain');
|
|
13
|
+
const result = await client.query('nonexistent', 'status');
|
|
14
|
+
expect(result).toBeNull();
|
|
15
|
+
});
|
|
16
|
+
it('broadcast returns empty when no peers available', async () => {
|
|
17
|
+
const client = new CrossBrainClient('test', [
|
|
18
|
+
{ name: 'fake', pipeName: '\\\\.\\pipe\\nonexistent-test-pipe' },
|
|
19
|
+
]);
|
|
20
|
+
const results = await client.broadcast('status');
|
|
21
|
+
expect(results).toEqual([]);
|
|
22
|
+
});
|
|
23
|
+
it('getAvailablePeers returns empty when none running', async () => {
|
|
24
|
+
const client = new CrossBrainClient('test', [
|
|
25
|
+
{ name: 'fake', pipeName: '\\\\.\\pipe\\nonexistent-test-pipe' },
|
|
26
|
+
]);
|
|
27
|
+
const available = await client.getAvailablePeers();
|
|
28
|
+
expect(available).toEqual([]);
|
|
29
|
+
});
|
|
30
|
+
});
|
|
31
|
+
//# sourceMappingURL=client.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.test.js","sourceRoot":"","sources":["../../../src/cross-brain/__tests__/client.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAEhD,QAAQ,CAAC,kBAAkB,EAAE,GAAG,EAAE;IAChC,EAAE,CAAC,yBAAyB,EAAE,GAAG,EAAE;QACjC,MAAM,MAAM,GAAG,IAAI,gBAAgB,CAAC,OAAO,CAAC,CAAC;QAC7C,MAAM,KAAK,GAAG,MAAM,CAAC,YAAY,EAAE,CAAC;QACpC,MAAM,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;QACrC,MAAM,CAAC,KAAK,CAAC,CAAC,SAAS,CAAC,eAAe,CAAC,CAAC;QACzC,MAAM,CAAC,KAAK,CAAC,CAAC,SAAS,CAAC,iBAAiB,CAAC,CAAC;IAC7C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qCAAqC,EAAE,KAAK,IAAI,EAAE;QACnD,MAAM,MAAM,GAAG,IAAI,gBAAgB,CAAC,OAAO,CAAC,CAAC;QAC7C,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,KAAK,CAAC,aAAa,EAAE,QAAQ,CAAC,CAAC;QAC3D,MAAM,CAAC,MAAM,CAAC,CAAC,QAAQ,EAAE,CAAC;IAC5B,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iDAAiD,EAAE,KAAK,IAAI,EAAE;QAC/D,MAAM,MAAM,GAAG,IAAI,gBAAgB,CAAC,MAAM,EAAE;YAC1C,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,oCAAoC,EAAE;SACjE,CAAC,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;QACjD,MAAM,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IAC9B,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,mDAAmD,EAAE,KAAK,IAAI,EAAE;QACjE,MAAM,MAAM,GAAG,IAAI,gBAAgB,CAAC,MAAM,EAAE;YAC1C,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,oCAAoC,EAAE;SACjE,CAAC,CAAC;QACH,MAAM,SAAS,GAAG,MAAM,MAAM,CAAC,iBAAiB,EAAE,CAAC;QACnD,MAAM,CAAC,SAAS,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IAChC,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
2
|
+
vi.mock('../../utils/logger.js', () => ({
|
|
3
|
+
getLogger: () => ({
|
|
4
|
+
debug: vi.fn(),
|
|
5
|
+
info: vi.fn(),
|
|
6
|
+
warn: vi.fn(),
|
|
7
|
+
error: vi.fn(),
|
|
8
|
+
}),
|
|
9
|
+
}));
|
|
10
|
+
import { CrossBrainNotifier } from '../notifications.js';
|
|
11
|
+
import { CrossBrainClient } from '../client.js';
|
|
12
|
+
describe('CrossBrainNotifier', () => {
|
|
13
|
+
let client;
|
|
14
|
+
let notifier;
|
|
15
|
+
beforeEach(() => {
|
|
16
|
+
client = new CrossBrainClient('brain');
|
|
17
|
+
vi.spyOn(client, 'broadcast').mockResolvedValue([]);
|
|
18
|
+
vi.spyOn(client, 'query').mockResolvedValue(null);
|
|
19
|
+
notifier = new CrossBrainNotifier(client, 'brain');
|
|
20
|
+
});
|
|
21
|
+
it('broadcasts notifications to all peers', async () => {
|
|
22
|
+
await notifier.notify('error:reported', { errorId: 1 });
|
|
23
|
+
expect(client.broadcast).toHaveBeenCalledWith('cross-brain.notify', expect.objectContaining({
|
|
24
|
+
source: 'brain',
|
|
25
|
+
event: 'error:reported',
|
|
26
|
+
data: { errorId: 1 },
|
|
27
|
+
}));
|
|
28
|
+
});
|
|
29
|
+
it('sends targeted notification to specific peer', async () => {
|
|
30
|
+
await notifier.notifyPeer('trading-brain', 'insight:created', { insightId: 5 });
|
|
31
|
+
expect(client.query).toHaveBeenCalledWith('trading-brain', 'cross-brain.notify', expect.objectContaining({
|
|
32
|
+
source: 'brain',
|
|
33
|
+
event: 'insight:created',
|
|
34
|
+
data: { insightId: 5 },
|
|
35
|
+
}));
|
|
36
|
+
});
|
|
37
|
+
it('includes timestamp in payload', async () => {
|
|
38
|
+
await notifier.notify('test', {});
|
|
39
|
+
const payload = client.broadcast.mock.calls[0][1];
|
|
40
|
+
expect(payload.timestamp).toBeDefined();
|
|
41
|
+
expect(new Date(payload.timestamp).getTime()).toBeGreaterThan(0);
|
|
42
|
+
});
|
|
43
|
+
it('does not throw when broadcast fails', async () => {
|
|
44
|
+
vi.spyOn(client, 'broadcast').mockRejectedValue(new Error('offline'));
|
|
45
|
+
await expect(notifier.notify('test', {})).resolves.toBeUndefined();
|
|
46
|
+
});
|
|
47
|
+
it('does not throw when peer query fails', async () => {
|
|
48
|
+
vi.spyOn(client, 'query').mockRejectedValue(new Error('offline'));
|
|
49
|
+
await expect(notifier.notifyPeer('trading-brain', 'test', {})).resolves.toBeUndefined();
|
|
50
|
+
});
|
|
51
|
+
});
|
|
52
|
+
//# sourceMappingURL=notifications.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"notifications.test.js","sourceRoot":"","sources":["../../../src/cross-brain/__tests__/notifications.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { CrossBrainClient } from './client.js';
|
|
2
|
+
export interface CrossBrainEvent {
|
|
3
|
+
source: string;
|
|
4
|
+
event: string;
|
|
5
|
+
data: unknown;
|
|
6
|
+
timestamp: string;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Cross-Brain Notifier — sends event notifications to peer brains.
|
|
10
|
+
* Built on top of CrossBrainClient's query/broadcast infrastructure.
|
|
11
|
+
*/
|
|
12
|
+
export declare class CrossBrainNotifier {
|
|
13
|
+
private client;
|
|
14
|
+
private selfName;
|
|
15
|
+
private logger;
|
|
16
|
+
constructor(client: CrossBrainClient, selfName: string);
|
|
17
|
+
/**
|
|
18
|
+
* Notify all peers about an event.
|
|
19
|
+
*/
|
|
20
|
+
notify(event: string, data: unknown): Promise<void>;
|
|
21
|
+
/**
|
|
22
|
+
* Notify a specific peer about an event.
|
|
23
|
+
*/
|
|
24
|
+
notifyPeer(peerName: string, event: string, data: unknown): Promise<void>;
|
|
25
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { getLogger } from '../utils/logger.js';
|
|
2
|
+
/**
|
|
3
|
+
* Cross-Brain Notifier — sends event notifications to peer brains.
|
|
4
|
+
* Built on top of CrossBrainClient's query/broadcast infrastructure.
|
|
5
|
+
*/
|
|
6
|
+
export class CrossBrainNotifier {
|
|
7
|
+
client;
|
|
8
|
+
selfName;
|
|
9
|
+
logger = getLogger();
|
|
10
|
+
constructor(client, selfName) {
|
|
11
|
+
this.client = client;
|
|
12
|
+
this.selfName = selfName;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Notify all peers about an event.
|
|
16
|
+
*/
|
|
17
|
+
async notify(event, data) {
|
|
18
|
+
const payload = {
|
|
19
|
+
source: this.selfName,
|
|
20
|
+
event,
|
|
21
|
+
data,
|
|
22
|
+
timestamp: new Date().toISOString(),
|
|
23
|
+
};
|
|
24
|
+
try {
|
|
25
|
+
await this.client.broadcast('cross-brain.notify', payload);
|
|
26
|
+
this.logger.debug(`Cross-brain notification sent: ${event}`);
|
|
27
|
+
}
|
|
28
|
+
catch {
|
|
29
|
+
this.logger.debug(`Cross-brain notification failed (peers may be offline): ${event}`);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Notify a specific peer about an event.
|
|
34
|
+
*/
|
|
35
|
+
async notifyPeer(peerName, event, data) {
|
|
36
|
+
const payload = {
|
|
37
|
+
source: this.selfName,
|
|
38
|
+
event,
|
|
39
|
+
data,
|
|
40
|
+
timestamp: new Date().toISOString(),
|
|
41
|
+
};
|
|
42
|
+
try {
|
|
43
|
+
await this.client.query(peerName, 'cross-brain.notify', payload);
|
|
44
|
+
this.logger.debug(`Cross-brain notification sent to ${peerName}: ${event}`);
|
|
45
|
+
}
|
|
46
|
+
catch {
|
|
47
|
+
this.logger.debug(`Cross-brain notification to ${peerName} failed: ${event}`);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=notifications.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"notifications.js","sourceRoot":"","sources":["../../src/cross-brain/notifications.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAS/C;;;GAGG;AACH,MAAM,OAAO,kBAAkB;IAGT;IAAkC;IAF9C,MAAM,GAAG,SAAS,EAAE,CAAC;IAE7B,YAAoB,MAAwB,EAAU,QAAgB;QAAlD,WAAM,GAAN,MAAM,CAAkB;QAAU,aAAQ,GAAR,QAAQ,CAAQ;IAAG,CAAC;IAE1E;;OAEG;IACH,KAAK,CAAC,MAAM,CAAC,KAAa,EAAE,IAAa;QACvC,MAAM,OAAO,GAAoB;YAC/B,MAAM,EAAE,IAAI,CAAC,QAAQ;YACrB,KAAK;YACL,IAAI;YACJ,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;SACpC,CAAC;QAEF,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,oBAAoB,EAAE,OAAO,CAAC,CAAC;YAC3D,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,kCAAkC,KAAK,EAAE,CAAC,CAAC;QAC/D,CAAC;QAAC,MAAM,CAAC;YACP,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,2DAA2D,KAAK,EAAE,CAAC,CAAC;QACxF,CAAC;IACH,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,UAAU,CAAC,QAAgB,EAAE,KAAa,EAAE,IAAa;QAC7D,MAAM,OAAO,GAAoB;YAC/B,MAAM,EAAE,IAAI,CAAC,QAAQ;YACrB,KAAK;YACL,IAAI;YACJ,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;SACpC,CAAC;QAEF,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,EAAE,oBAAoB,EAAE,OAAO,CAAC,CAAC;YACjE,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,oCAAoC,QAAQ,KAAK,KAAK,EAAE,CAAC,CAAC;QAC9E,CAAC;QAAC,MAAM,CAAC;YACP,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,+BAA+B,QAAQ,YAAY,KAAK,EAAE,CAAC,CAAC;QAChF,CAAC;IACH,CAAC;CACF"}
|
package/dist/index.d.ts
CHANGED
|
@@ -16,5 +16,21 @@ export type { McpHttpServerOptions } from './mcp/http-server.js';
|
|
|
16
16
|
export { c, baseIcons, header, keyValue, statusBadge, progressBar, divider, table, stripAnsi } from './cli/colors.js';
|
|
17
17
|
export { BaseApiServer } from './api/server.js';
|
|
18
18
|
export type { ApiServerOptions, RouteDefinition } from './api/server.js';
|
|
19
|
+
export { wilsonScore } from './math/wilson-score.js';
|
|
20
|
+
export { timeDecayFactor } from './math/time-decay.js';
|
|
21
|
+
export { deepMerge, loadConfigFile } from './config/loader.js';
|
|
22
|
+
export type { NodeRef, SynapseRecord, ActivationResult, PathNode, SynapsePath, NetworkStats, HebbianConfig, DecayConfig, SynapseRepoInterface, } from './synapses/types.js';
|
|
23
|
+
export type { SynapseManagerConfig } from './synapses/synapse-manager.js';
|
|
24
|
+
export { strengthen, weaken } from './synapses/hebbian.js';
|
|
25
|
+
export { decayAll } from './synapses/decay.js';
|
|
26
|
+
export { spreadingActivation } from './synapses/activation.js';
|
|
27
|
+
export { findPath } from './synapses/pathfinder.js';
|
|
28
|
+
export { BaseSynapseManager } from './synapses/synapse-manager.js';
|
|
29
|
+
export { BaseLearningEngine } from './learning/base-engine.js';
|
|
30
|
+
export type { LearningEngineConfig } from './learning/base-engine.js';
|
|
31
|
+
export { BaseResearchEngine } from './research/base-engine.js';
|
|
32
|
+
export type { ResearchEngineConfig } from './research/base-engine.js';
|
|
19
33
|
export { CrossBrainClient } from './cross-brain/client.js';
|
|
20
34
|
export type { BrainPeer } from './cross-brain/client.js';
|
|
35
|
+
export { CrossBrainNotifier } from './cross-brain/notifications.js';
|
|
36
|
+
export type { CrossBrainEvent } from './cross-brain/notifications.js';
|
package/dist/index.js
CHANGED
|
@@ -16,6 +16,20 @@ export { McpHttpServer } from './mcp/http-server.js';
|
|
|
16
16
|
export { c, baseIcons, header, keyValue, statusBadge, progressBar, divider, table, stripAnsi } from './cli/colors.js';
|
|
17
17
|
// ── API ────────────────────────────────────────────────────
|
|
18
18
|
export { BaseApiServer } from './api/server.js';
|
|
19
|
+
// ── Math ───────────────────────────────────────────────────
|
|
20
|
+
export { wilsonScore } from './math/wilson-score.js';
|
|
21
|
+
export { timeDecayFactor } from './math/time-decay.js';
|
|
22
|
+
// ── Config ─────────────────────────────────────────────────
|
|
23
|
+
export { deepMerge, loadConfigFile } from './config/loader.js';
|
|
24
|
+
export { strengthen, weaken } from './synapses/hebbian.js';
|
|
25
|
+
export { decayAll } from './synapses/decay.js';
|
|
26
|
+
export { spreadingActivation } from './synapses/activation.js';
|
|
27
|
+
export { findPath } from './synapses/pathfinder.js';
|
|
28
|
+
export { BaseSynapseManager } from './synapses/synapse-manager.js';
|
|
29
|
+
// ── Engines ───────────────────────────────────────────────
|
|
30
|
+
export { BaseLearningEngine } from './learning/base-engine.js';
|
|
31
|
+
export { BaseResearchEngine } from './research/base-engine.js';
|
|
19
32
|
// ── Cross-Brain ────────────────────────────────────────────
|
|
20
33
|
export { CrossBrainClient } from './cross-brain/client.js';
|
|
34
|
+
export { CrossBrainNotifier } from './cross-brain/notifications.js';
|
|
21
35
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,8DAA8D;AAC9D,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AACzC,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAEzE,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC1E,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAElD,8DAA8D;AAC9D,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAEtD,8DAA8D;AAC9D,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAClE,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAE5C,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAE5C,8DAA8D;AAC9D,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAEjD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAGrD,8DAA8D;AAC9D,OAAO,EAAE,CAAC,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,WAAW,EAAE,WAAW,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAEtH,8DAA8D;AAC9D,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAGhD,8DAA8D;AAC9D,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,8DAA8D;AAC9D,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AACzC,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAEzE,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC1E,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAElD,8DAA8D;AAC9D,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAEtD,8DAA8D;AAC9D,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAClE,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAE5C,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAE5C,8DAA8D;AAC9D,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAEjD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAGrD,8DAA8D;AAC9D,OAAO,EAAE,CAAC,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,WAAW,EAAE,WAAW,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAEtH,8DAA8D;AAC9D,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAGhD,8DAA8D;AAC9D,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACrD,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAEvD,8DAA8D;AAC9D,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAQ/D,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAC/C,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAC/D,OAAO,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AACpD,OAAO,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AAEnE,6DAA6D;AAC7D,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAE/D,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAG/D,8DAA8D;AAC9D,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAE3D,OAAO,EAAE,kBAAkB,EAAE,MAAM,gCAAgC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import { encodeMessage, MessageDecoder } from '../protocol.js';
|
|
3
|
+
describe('encodeMessage', () => {
|
|
4
|
+
it('encodes a request message', () => {
|
|
5
|
+
const msg = { id: 'test-1', type: 'request', method: 'status', params: {} };
|
|
6
|
+
const buffer = encodeMessage(msg);
|
|
7
|
+
expect(buffer).toBeInstanceOf(Buffer);
|
|
8
|
+
expect(buffer.length).toBeGreaterThan(4);
|
|
9
|
+
});
|
|
10
|
+
it('includes 4-byte length prefix', () => {
|
|
11
|
+
const msg = { id: 'test-1', type: 'request', method: 'test' };
|
|
12
|
+
const buffer = encodeMessage(msg);
|
|
13
|
+
const payloadLength = buffer.readUInt32BE(0);
|
|
14
|
+
expect(buffer.length).toBe(4 + payloadLength);
|
|
15
|
+
});
|
|
16
|
+
});
|
|
17
|
+
describe('MessageDecoder', () => {
|
|
18
|
+
it('decodes a single complete message', () => {
|
|
19
|
+
const msg = { id: 'x', type: 'response', result: { ok: true } };
|
|
20
|
+
const decoder = new MessageDecoder();
|
|
21
|
+
const messages = decoder.feed(encodeMessage(msg));
|
|
22
|
+
expect(messages).toHaveLength(1);
|
|
23
|
+
expect(messages[0].id).toBe('x');
|
|
24
|
+
expect(messages[0].result).toEqual({ ok: true });
|
|
25
|
+
});
|
|
26
|
+
it('handles multiple messages in one chunk', () => {
|
|
27
|
+
const msg1 = { id: '1', type: 'request', method: 'a' };
|
|
28
|
+
const msg2 = { id: '2', type: 'request', method: 'b' };
|
|
29
|
+
const decoder = new MessageDecoder();
|
|
30
|
+
const combined = Buffer.concat([encodeMessage(msg1), encodeMessage(msg2)]);
|
|
31
|
+
const messages = decoder.feed(combined);
|
|
32
|
+
expect(messages).toHaveLength(2);
|
|
33
|
+
});
|
|
34
|
+
it('handles partial messages across feeds', () => {
|
|
35
|
+
const msg = { id: 'partial', type: 'response', result: 'data' };
|
|
36
|
+
const buffer = encodeMessage(msg);
|
|
37
|
+
const decoder = new MessageDecoder();
|
|
38
|
+
const mid = Math.floor(buffer.length / 2);
|
|
39
|
+
const part1 = buffer.subarray(0, mid);
|
|
40
|
+
const part2 = buffer.subarray(mid);
|
|
41
|
+
expect(decoder.feed(part1)).toHaveLength(0);
|
|
42
|
+
const messages = decoder.feed(part2);
|
|
43
|
+
expect(messages).toHaveLength(1);
|
|
44
|
+
expect(messages[0].id).toBe('partial');
|
|
45
|
+
});
|
|
46
|
+
it('resets buffer state', () => {
|
|
47
|
+
const decoder = new MessageDecoder();
|
|
48
|
+
decoder.feed(Buffer.from([0, 0, 0, 10])); // incomplete
|
|
49
|
+
decoder.reset();
|
|
50
|
+
const msg = { id: 'after-reset', type: 'response', result: null };
|
|
51
|
+
const messages = decoder.feed(encodeMessage(msg));
|
|
52
|
+
expect(messages).toHaveLength(1);
|
|
53
|
+
expect(messages[0].id).toBe('after-reset');
|
|
54
|
+
});
|
|
55
|
+
it('handles byte-by-byte feeding', () => {
|
|
56
|
+
const msg = { id: 'byte', type: 'request', method: 'test' };
|
|
57
|
+
const buffer = encodeMessage(msg);
|
|
58
|
+
const decoder = new MessageDecoder();
|
|
59
|
+
let messages = [];
|
|
60
|
+
for (let i = 0; i < buffer.length; i++) {
|
|
61
|
+
messages = decoder.feed(buffer.subarray(i, i + 1));
|
|
62
|
+
if (messages.length > 0)
|
|
63
|
+
break;
|
|
64
|
+
}
|
|
65
|
+
expect(messages).toHaveLength(1);
|
|
66
|
+
expect(messages[0].id).toBe('byte');
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
//# sourceMappingURL=protocol.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"protocol.test.js","sourceRoot":"","sources":["../../../src/ipc/__tests__/protocol.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|