@timmeck/brain-core 1.0.0 → 1.2.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 +3 -1
- package/brain.log +0 -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/client.d.ts +27 -0
- package/dist/cross-brain/client.js +84 -0
- package/dist/cross-brain/client.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -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/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/package.json +3 -2
- package/src/api/server.ts +0 -210
- package/src/cli/colors.ts +0 -105
- package/src/db/connection.ts +0 -22
- package/src/index.ts +0 -31
- 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
|
@@ -135,10 +135,12 @@ class MyRouter implements IpcRouter {
|
|
|
135
135
|
|-------|---------|-------|
|
|
136
136
|
| [Brain](https://github.com/timmeck/brain) | Error memory & code intelligence | 7777/7778 |
|
|
137
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 |
|
|
138
|
+
| [Marketing Brain](https://github.com/timmeck/marketing-brain) | Content strategy & social media | 7781/7782/7783 |
|
|
139
139
|
|
|
140
140
|
All three brains are standalone — brain-core is an **optional** shared dependency that eliminates code duplication.
|
|
141
141
|
|
|
142
|
+
Visit the [Brain Hub](https://timmeck.github.io/brain-hub/) for the full ecosystem overview.
|
|
143
|
+
|
|
142
144
|
## License
|
|
143
145
|
|
|
144
146
|
[MIT](LICENSE)
|
package/brain.log
ADDED
|
File without changes
|
|
@@ -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,27 @@
|
|
|
1
|
+
export interface BrainPeer {
|
|
2
|
+
name: string;
|
|
3
|
+
pipeName: string;
|
|
4
|
+
}
|
|
5
|
+
export declare class CrossBrainClient {
|
|
6
|
+
private selfName;
|
|
7
|
+
private peers;
|
|
8
|
+
constructor(selfName: string, peers?: BrainPeer[]);
|
|
9
|
+
/**
|
|
10
|
+
* Query a specific peer brain by name.
|
|
11
|
+
* Returns null if the peer is not available.
|
|
12
|
+
*/
|
|
13
|
+
query(peerName: string, method: string, params?: unknown): Promise<unknown | null>;
|
|
14
|
+
/**
|
|
15
|
+
* Broadcast a query to all available peer brains.
|
|
16
|
+
* Returns results from all peers that responded.
|
|
17
|
+
*/
|
|
18
|
+
broadcast(method: string, params?: unknown): Promise<{
|
|
19
|
+
name: string;
|
|
20
|
+
result: unknown;
|
|
21
|
+
}[]>;
|
|
22
|
+
/**
|
|
23
|
+
* Check which peer brains are currently running.
|
|
24
|
+
*/
|
|
25
|
+
getAvailablePeers(): Promise<string[]>;
|
|
26
|
+
getPeerNames(): string[];
|
|
27
|
+
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { IpcClient } from '../ipc/client.js';
|
|
2
|
+
import { getPipeName } from '../utils/paths.js';
|
|
3
|
+
const DEFAULT_PEERS = [
|
|
4
|
+
{ name: 'brain', pipeName: getPipeName('brain') },
|
|
5
|
+
{ name: 'trading-brain', pipeName: getPipeName('trading-brain') },
|
|
6
|
+
{ name: 'marketing-brain', pipeName: getPipeName('marketing-brain') },
|
|
7
|
+
];
|
|
8
|
+
export class CrossBrainClient {
|
|
9
|
+
selfName;
|
|
10
|
+
peers;
|
|
11
|
+
constructor(selfName, peers) {
|
|
12
|
+
this.selfName = selfName;
|
|
13
|
+
this.peers = (peers ?? DEFAULT_PEERS).filter(p => p.name !== selfName);
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Query a specific peer brain by name.
|
|
17
|
+
* Returns null if the peer is not available.
|
|
18
|
+
*/
|
|
19
|
+
async query(peerName, method, params) {
|
|
20
|
+
const peer = this.peers.find(p => p.name === peerName);
|
|
21
|
+
if (!peer)
|
|
22
|
+
return null;
|
|
23
|
+
const client = new IpcClient(peer.pipeName, 3000);
|
|
24
|
+
try {
|
|
25
|
+
await client.connect();
|
|
26
|
+
const result = await client.request(method, params);
|
|
27
|
+
return result;
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
finally {
|
|
33
|
+
client.disconnect();
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Broadcast a query to all available peer brains.
|
|
38
|
+
* Returns results from all peers that responded.
|
|
39
|
+
*/
|
|
40
|
+
async broadcast(method, params) {
|
|
41
|
+
const results = [];
|
|
42
|
+
const promises = this.peers.map(async (peer) => {
|
|
43
|
+
const client = new IpcClient(peer.pipeName, 3000);
|
|
44
|
+
try {
|
|
45
|
+
await client.connect();
|
|
46
|
+
const result = await client.request(method, params);
|
|
47
|
+
results.push({ name: peer.name, result });
|
|
48
|
+
}
|
|
49
|
+
catch {
|
|
50
|
+
// Peer not available — skip
|
|
51
|
+
}
|
|
52
|
+
finally {
|
|
53
|
+
client.disconnect();
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
await Promise.all(promises);
|
|
57
|
+
return results;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Check which peer brains are currently running.
|
|
61
|
+
*/
|
|
62
|
+
async getAvailablePeers() {
|
|
63
|
+
const available = [];
|
|
64
|
+
const checks = this.peers.map(async (peer) => {
|
|
65
|
+
const client = new IpcClient(peer.pipeName, 1000);
|
|
66
|
+
try {
|
|
67
|
+
await client.connect();
|
|
68
|
+
available.push(peer.name);
|
|
69
|
+
}
|
|
70
|
+
catch {
|
|
71
|
+
// Not available
|
|
72
|
+
}
|
|
73
|
+
finally {
|
|
74
|
+
client.disconnect();
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
await Promise.all(checks);
|
|
78
|
+
return available;
|
|
79
|
+
}
|
|
80
|
+
getPeerNames() {
|
|
81
|
+
return this.peers.map(p => p.name);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/cross-brain/client.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -16,3 +16,5 @@ 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 { CrossBrainClient } from './cross-brain/client.js';
|
|
20
|
+
export type { BrainPeer } from './cross-brain/client.js';
|
package/dist/index.js
CHANGED
|
@@ -16,4 +16,6 @@ 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
|
+
// ── Cross-Brain ────────────────────────────────────────────
|
|
20
|
+
export { CrossBrainClient } from './cross-brain/client.js';
|
|
19
21
|
//# 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"}
|
|
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"}
|
|
@@ -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 {};
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { describe, it, expect, vi } from 'vitest';
|
|
2
|
+
import { TypedEventBus } from '../events.js';
|
|
3
|
+
describe('TypedEventBus', () => {
|
|
4
|
+
it('emits and receives events', () => {
|
|
5
|
+
const bus = new TypedEventBus();
|
|
6
|
+
const handler = vi.fn();
|
|
7
|
+
bus.on('test:fired', handler);
|
|
8
|
+
bus.emit('test:fired', { value: 42 });
|
|
9
|
+
expect(handler).toHaveBeenCalledWith({ value: 42 });
|
|
10
|
+
});
|
|
11
|
+
it('supports once listener', () => {
|
|
12
|
+
const bus = new TypedEventBus();
|
|
13
|
+
const handler = vi.fn();
|
|
14
|
+
bus.once('test:fired', handler);
|
|
15
|
+
bus.emit('test:fired', { value: 1 });
|
|
16
|
+
bus.emit('test:fired', { value: 2 });
|
|
17
|
+
expect(handler).toHaveBeenCalledTimes(1);
|
|
18
|
+
});
|
|
19
|
+
it('supports off to remove listener', () => {
|
|
20
|
+
const bus = new TypedEventBus();
|
|
21
|
+
const handler = vi.fn();
|
|
22
|
+
bus.on('test:fired', handler);
|
|
23
|
+
bus.off('test:fired', handler);
|
|
24
|
+
bus.emit('test:fired', { value: 1 });
|
|
25
|
+
expect(handler).not.toHaveBeenCalled();
|
|
26
|
+
});
|
|
27
|
+
it('handles multiple event types independently', () => {
|
|
28
|
+
const bus = new TypedEventBus();
|
|
29
|
+
const handler1 = vi.fn();
|
|
30
|
+
const handler2 = vi.fn();
|
|
31
|
+
bus.on('test:fired', handler1);
|
|
32
|
+
bus.on('test:other', handler2);
|
|
33
|
+
bus.emit('test:fired', { value: 10 });
|
|
34
|
+
expect(handler1).toHaveBeenCalledTimes(1);
|
|
35
|
+
expect(handler2).not.toHaveBeenCalled();
|
|
36
|
+
});
|
|
37
|
+
});
|
|
38
|
+
//# sourceMappingURL=events.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"events.test.js","sourceRoot":"","sources":["../../../src/utils/__tests__/events.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAClD,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAO7C,QAAQ,CAAC,eAAe,EAAE,GAAG,EAAE;IAC7B,EAAE,CAAC,2BAA2B,EAAE,GAAG,EAAE;QACnC,MAAM,GAAG,GAAG,IAAI,aAAa,EAAc,CAAC;QAC5C,MAAM,OAAO,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC;QACxB,GAAG,CAAC,EAAE,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC;QAC9B,GAAG,CAAC,IAAI,CAAC,YAAY,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,CAAC;QACtC,MAAM,CAAC,OAAO,CAAC,CAAC,oBAAoB,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,CAAC;IACtD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wBAAwB,EAAE,GAAG,EAAE;QAChC,MAAM,GAAG,GAAG,IAAI,aAAa,EAAc,CAAC;QAC5C,MAAM,OAAO,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC;QACxB,GAAG,CAAC,IAAI,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC;QAChC,GAAG,CAAC,IAAI,CAAC,YAAY,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC;QACrC,GAAG,CAAC,IAAI,CAAC,YAAY,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC;QACrC,MAAM,CAAC,OAAO,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;IAC3C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iCAAiC,EAAE,GAAG,EAAE;QACzC,MAAM,GAAG,GAAG,IAAI,aAAa,EAAc,CAAC;QAC5C,MAAM,OAAO,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC;QACxB,GAAG,CAAC,EAAE,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC;QAC9B,GAAG,CAAC,GAAG,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC;QAC/B,GAAG,CAAC,IAAI,CAAC,YAAY,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC;QACrC,MAAM,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,gBAAgB,EAAE,CAAC;IACzC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4CAA4C,EAAE,GAAG,EAAE;QACpD,MAAM,GAAG,GAAG,IAAI,aAAa,EAAc,CAAC;QAC5C,MAAM,QAAQ,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC;QACzB,MAAM,QAAQ,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC;QACzB,GAAG,CAAC,EAAE,CAAC,YAAY,EAAE,QAAQ,CAAC,CAAC;QAC/B,GAAG,CAAC,EAAE,CAAC,YAAY,EAAE,QAAQ,CAAC,CAAC;QAC/B,GAAG,CAAC,IAAI,CAAC,YAAY,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,CAAC;QACtC,MAAM,CAAC,QAAQ,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;QAC1C,MAAM,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,gBAAgB,EAAE,CAAC;IAC1C,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import { sha256 } from '../hash.js';
|
|
3
|
+
describe('sha256', () => {
|
|
4
|
+
it('returns consistent hash for same input', () => {
|
|
5
|
+
expect(sha256('hello')).toBe(sha256('hello'));
|
|
6
|
+
});
|
|
7
|
+
it('returns different hashes for different inputs', () => {
|
|
8
|
+
expect(sha256('hello')).not.toBe(sha256('world'));
|
|
9
|
+
});
|
|
10
|
+
it('returns 64-char hex string', () => {
|
|
11
|
+
expect(sha256('test')).toMatch(/^[a-f0-9]{64}$/);
|
|
12
|
+
});
|
|
13
|
+
it('matches known SHA-256 value', () => {
|
|
14
|
+
expect(sha256('hello')).toBe('2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824');
|
|
15
|
+
});
|
|
16
|
+
it('handles empty string', () => {
|
|
17
|
+
expect(sha256('')).toBe('e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855');
|
|
18
|
+
});
|
|
19
|
+
it('handles unicode', () => {
|
|
20
|
+
const hash = sha256('こんにちは');
|
|
21
|
+
expect(hash).toMatch(/^[a-f0-9]{64}$/);
|
|
22
|
+
expect(hash).toBe(sha256('こんにちは'));
|
|
23
|
+
});
|
|
24
|
+
});
|
|
25
|
+
//# sourceMappingURL=hash.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hash.test.js","sourceRoot":"","sources":["../../../src/utils/__tests__/hash.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAEpC,QAAQ,CAAC,QAAQ,EAAE,GAAG,EAAE;IACtB,EAAE,CAAC,wCAAwC,EAAE,GAAG,EAAE;QAChD,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC;IAChD,CAAC,CAAC,CAAC;IACH,EAAE,CAAC,+CAA+C,EAAE,GAAG,EAAE;QACvD,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC;IACpD,CAAC,CAAC,CAAC;IACH,EAAE,CAAC,4BAA4B,EAAE,GAAG,EAAE;QACpC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC;IACnD,CAAC,CAAC,CAAC;IACH,EAAE,CAAC,6BAA6B,EAAE,GAAG,EAAE;QACrC,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,kEAAkE,CAAC,CAAC;IACnG,CAAC,CAAC,CAAC;IACH,EAAE,CAAC,sBAAsB,EAAE,GAAG,EAAE;QAC9B,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,kEAAkE,CAAC,CAAC;IAC9F,CAAC,CAAC,CAAC;IACH,EAAE,CAAC,iBAAiB,EAAE,GAAG,EAAE;QACzB,MAAM,IAAI,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC;QAC7B,MAAM,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC;QACvC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC;IACrC,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { describe, it, expect, afterEach } from 'vitest';
|
|
2
|
+
import { createLogger, getLogger, resetLogger } from '../logger.js';
|
|
3
|
+
describe('logger', () => {
|
|
4
|
+
afterEach(() => {
|
|
5
|
+
resetLogger();
|
|
6
|
+
});
|
|
7
|
+
it('createLogger returns a logger instance', () => {
|
|
8
|
+
const logger = createLogger({ level: 'error' });
|
|
9
|
+
expect(logger).toBeDefined();
|
|
10
|
+
expect(typeof logger.info).toBe('function');
|
|
11
|
+
expect(typeof logger.error).toBe('function');
|
|
12
|
+
});
|
|
13
|
+
it('getLogger returns the same singleton', () => {
|
|
14
|
+
const a = createLogger({ level: 'error' });
|
|
15
|
+
const b = getLogger();
|
|
16
|
+
expect(a).toBe(b);
|
|
17
|
+
});
|
|
18
|
+
it('resetLogger allows creating a new logger', () => {
|
|
19
|
+
const a = createLogger({ level: 'error' });
|
|
20
|
+
resetLogger();
|
|
21
|
+
const b = createLogger({ level: 'warn' });
|
|
22
|
+
expect(a).not.toBe(b);
|
|
23
|
+
});
|
|
24
|
+
it('getLogger auto-creates if none exists', () => {
|
|
25
|
+
const logger = getLogger();
|
|
26
|
+
expect(logger).toBeDefined();
|
|
27
|
+
});
|
|
28
|
+
});
|
|
29
|
+
//# sourceMappingURL=logger.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.test.js","sourceRoot":"","sources":["../../../src/utils/__tests__/logger.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AACzD,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAEpE,QAAQ,CAAC,QAAQ,EAAE,GAAG,EAAE;IACtB,SAAS,CAAC,GAAG,EAAE;QACb,WAAW,EAAE,CAAC;IAChB,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wCAAwC,EAAE,GAAG,EAAE;QAChD,MAAM,MAAM,GAAG,YAAY,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,CAAC;QAChD,MAAM,CAAC,MAAM,CAAC,CAAC,WAAW,EAAE,CAAC;QAC7B,MAAM,CAAC,OAAO,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAC5C,MAAM,CAAC,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IAC/C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,sCAAsC,EAAE,GAAG,EAAE;QAC9C,MAAM,CAAC,GAAG,YAAY,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,CAAC;QAC3C,MAAM,CAAC,GAAG,SAAS,EAAE,CAAC;QACtB,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACpB,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,0CAA0C,EAAE,GAAG,EAAE;QAClD,MAAM,CAAC,GAAG,YAAY,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,CAAC;QAC3C,WAAW,EAAE,CAAC;QACd,MAAM,CAAC,GAAG,YAAY,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;QAC1C,MAAM,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACxB,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,uCAAuC,EAAE,GAAG,EAAE;QAC/C,MAAM,MAAM,GAAG,SAAS,EAAE,CAAC;QAC3B,MAAM,CAAC,MAAM,CAAC,CAAC,WAAW,EAAE,CAAC;IAC/B,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { describe, it, expect, afterEach } from 'vitest';
|
|
2
|
+
import { normalizePath, getDataDir, getPipeName } from '../paths.js';
|
|
3
|
+
describe('normalizePath', () => {
|
|
4
|
+
it('converts backslashes to forward slashes', () => {
|
|
5
|
+
expect(normalizePath('C:\\Users\\test\\file.ts')).toBe('C:/Users/test/file.ts');
|
|
6
|
+
});
|
|
7
|
+
it('leaves forward slashes unchanged', () => {
|
|
8
|
+
expect(normalizePath('/home/user/file.ts')).toBe('/home/user/file.ts');
|
|
9
|
+
});
|
|
10
|
+
it('handles mixed slashes', () => {
|
|
11
|
+
expect(normalizePath('C:\\Users/test\\file.ts')).toBe('C:/Users/test/file.ts');
|
|
12
|
+
});
|
|
13
|
+
});
|
|
14
|
+
describe('getDataDir', () => {
|
|
15
|
+
afterEach(() => {
|
|
16
|
+
delete process.env['TEST_DATA_DIR'];
|
|
17
|
+
});
|
|
18
|
+
it('uses env var when set', () => {
|
|
19
|
+
process.env['TEST_DATA_DIR'] = '/custom/dir';
|
|
20
|
+
const result = getDataDir('TEST_DATA_DIR', '.brain');
|
|
21
|
+
// path.resolve normalises to platform-native form
|
|
22
|
+
expect(result).toContain('custom');
|
|
23
|
+
expect(result).not.toContain('.brain');
|
|
24
|
+
});
|
|
25
|
+
it('falls back to home dir', () => {
|
|
26
|
+
const result = getDataDir('NONEXISTENT_VAR_XYZ', '.test-brain');
|
|
27
|
+
expect(result).toContain('.test-brain');
|
|
28
|
+
});
|
|
29
|
+
});
|
|
30
|
+
describe('getPipeName', () => {
|
|
31
|
+
it('returns platform-specific path', () => {
|
|
32
|
+
const name = getPipeName('test-brain');
|
|
33
|
+
if (process.platform === 'win32') {
|
|
34
|
+
expect(name).toBe('\\\\.\\pipe\\test-brain');
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
expect(name).toContain('test-brain.sock');
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
it('defaults to brain', () => {
|
|
41
|
+
const name = getPipeName();
|
|
42
|
+
if (process.platform === 'win32') {
|
|
43
|
+
expect(name).toBe('\\\\.\\pipe\\brain');
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
expect(name).toContain('brain.sock');
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
});
|
|
50
|
+
//# sourceMappingURL=paths.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"paths.test.js","sourceRoot":"","sources":["../../../src/utils/__tests__/paths.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAM,SAAS,EAAE,MAAM,QAAQ,CAAC;AAC7D,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAErE,QAAQ,CAAC,eAAe,EAAE,GAAG,EAAE;IAC7B,EAAE,CAAC,yCAAyC,EAAE,GAAG,EAAE;QACjD,MAAM,CAAC,aAAa,CAAC,0BAA0B,CAAC,CAAC,CAAC,IAAI,CAAC,uBAAuB,CAAC,CAAC;IAClF,CAAC,CAAC,CAAC;IACH,EAAE,CAAC,kCAAkC,EAAE,GAAG,EAAE;QAC1C,MAAM,CAAC,aAAa,CAAC,oBAAoB,CAAC,CAAC,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;IACzE,CAAC,CAAC,CAAC;IACH,EAAE,CAAC,uBAAuB,EAAE,GAAG,EAAE;QAC/B,MAAM,CAAC,aAAa,CAAC,yBAAyB,CAAC,CAAC,CAAC,IAAI,CAAC,uBAAuB,CAAC,CAAC;IACjF,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,YAAY,EAAE,GAAG,EAAE;IAC1B,SAAS,CAAC,GAAG,EAAE;QACb,OAAO,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;IACtC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,uBAAuB,EAAE,GAAG,EAAE;QAC/B,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,GAAG,aAAa,CAAC;QAC7C,MAAM,MAAM,GAAG,UAAU,CAAC,eAAe,EAAE,QAAQ,CAAC,CAAC;QACrD,kDAAkD;QAClD,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;QACnC,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;IACzC,CAAC,CAAC,CAAC;IACH,EAAE,CAAC,wBAAwB,EAAE,GAAG,EAAE;QAChC,MAAM,MAAM,GAAG,UAAU,CAAC,qBAAqB,EAAE,aAAa,CAAC,CAAC;QAChE,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,aAAa,CAAC,CAAC;IAC1C,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,aAAa,EAAE,GAAG,EAAE;IAC3B,EAAE,CAAC,gCAAgC,EAAE,GAAG,EAAE;QACxC,MAAM,IAAI,GAAG,WAAW,CAAC,YAAY,CAAC,CAAC;QACvC,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC;YACjC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,yBAAyB,CAAC,CAAC;QAC/C,CAAC;aAAM,CAAC;YACN,MAAM,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,iBAAiB,CAAC,CAAC;QAC5C,CAAC;IACH,CAAC,CAAC,CAAC;IACH,EAAE,CAAC,mBAAmB,EAAE,GAAG,EAAE;QAC3B,MAAM,IAAI,GAAG,WAAW,EAAE,CAAC;QAC3B,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC;YACjC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;QAC1C,CAAC;aAAM,CAAC;YACN,MAAM,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC;QACvC,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@timmeck/brain-core",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"description": "Shared core infrastructure for the Brain ecosystem — IPC, MCP, CLI, DB connection, and utilities",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -19,7 +19,8 @@
|
|
|
19
19
|
"./mcp/server": "./dist/mcp/server.js",
|
|
20
20
|
"./mcp/http-server": "./dist/mcp/http-server.js",
|
|
21
21
|
"./cli/colors": "./dist/cli/colors.js",
|
|
22
|
-
"./api/server": "./dist/api/server.js"
|
|
22
|
+
"./api/server": "./dist/api/server.js",
|
|
23
|
+
"./cross-brain": "./dist/cross-brain/client.js"
|
|
23
24
|
},
|
|
24
25
|
"scripts": {
|
|
25
26
|
"build": "tsc",
|