@timmeck/brain 1.8.5 → 2.0.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.
Files changed (221) hide show
  1. package/.dockerignore +11 -0
  2. package/Dockerfile +21 -0
  3. package/README.md +19 -0
  4. package/assets/brain-avatar-256.png +0 -0
  5. package/assets/brain-avatar-512.png +0 -0
  6. package/assets/brain-avatar.png +0 -0
  7. package/brain.log +1164 -0
  8. package/{src/cli/commands/dashboard.ts → dashboard.html} +688 -807
  9. package/dist/api/server.d.ts +4 -18
  10. package/dist/api/server.js +4 -173
  11. package/dist/api/server.js.map +1 -1
  12. package/dist/brain.d.ts +6 -0
  13. package/dist/brain.js +56 -4
  14. package/dist/brain.js.map +1 -1
  15. package/dist/cli/colors.d.ts +4 -25
  16. package/dist/cli/colors.js +3 -89
  17. package/dist/cli/colors.js.map +1 -1
  18. package/dist/cli/commands/peers.d.ts +2 -0
  19. package/dist/cli/commands/peers.js +38 -0
  20. package/dist/cli/commands/peers.js.map +1 -0
  21. package/dist/cli/commands/start.js +54 -17
  22. package/dist/cli/commands/start.js.map +1 -1
  23. package/dist/db/connection.d.ts +1 -2
  24. package/dist/db/connection.js +1 -18
  25. package/dist/db/connection.js.map +1 -1
  26. package/dist/index.js +3 -1
  27. package/dist/index.js.map +1 -1
  28. package/dist/ipc/__tests__/protocol.test.d.ts +1 -0
  29. package/dist/ipc/__tests__/protocol.test.js +117 -0
  30. package/dist/ipc/__tests__/protocol.test.js.map +1 -0
  31. package/dist/ipc/client.d.ts +1 -16
  32. package/dist/ipc/client.js +1 -100
  33. package/dist/ipc/client.js.map +1 -1
  34. package/dist/ipc/protocol.d.ts +1 -8
  35. package/dist/ipc/protocol.js +1 -28
  36. package/dist/ipc/protocol.js.map +1 -1
  37. package/dist/ipc/router.js +8 -0
  38. package/dist/ipc/router.js.map +1 -1
  39. package/dist/ipc/server.d.ts +1 -22
  40. package/dist/ipc/server.js +1 -163
  41. package/dist/ipc/server.js.map +1 -1
  42. package/dist/mcp/http-server.d.ts +1 -7
  43. package/dist/mcp/http-server.js +6 -117
  44. package/dist/mcp/http-server.js.map +1 -1
  45. package/dist/mcp/server.js +5 -61
  46. package/dist/mcp/server.js.map +1 -1
  47. package/dist/signals/__tests__/fingerprint.test.d.ts +1 -0
  48. package/dist/signals/__tests__/fingerprint.test.js +118 -0
  49. package/dist/signals/__tests__/fingerprint.test.js.map +1 -0
  50. package/dist/types/ipc.types.d.ts +1 -11
  51. package/dist/utils/__tests__/hash.test.d.ts +1 -0
  52. package/dist/utils/__tests__/hash.test.js +32 -0
  53. package/dist/utils/__tests__/hash.test.js.map +1 -0
  54. package/dist/utils/__tests__/paths.test.d.ts +1 -0
  55. package/dist/utils/__tests__/paths.test.js +75 -0
  56. package/dist/utils/__tests__/paths.test.js.map +1 -0
  57. package/dist/utils/events.d.ts +4 -8
  58. package/dist/utils/events.js +2 -14
  59. package/dist/utils/events.js.map +1 -1
  60. package/dist/utils/hash.d.ts +1 -1
  61. package/dist/utils/hash.js +1 -4
  62. package/dist/utils/hash.js.map +1 -1
  63. package/dist/utils/logger.d.ts +3 -2
  64. package/dist/utils/logger.js +8 -35
  65. package/dist/utils/logger.js.map +1 -1
  66. package/dist/utils/paths.d.ts +2 -1
  67. package/dist/utils/paths.js +4 -13
  68. package/dist/utils/paths.js.map +1 -1
  69. package/gen_avatar.py +142 -0
  70. package/package.json +2 -1
  71. package/BRAIN_PLAN.md +0 -3324
  72. package/src/api/server.ts +0 -395
  73. package/src/brain.ts +0 -266
  74. package/src/cli/colors.ts +0 -116
  75. package/src/cli/commands/config.ts +0 -169
  76. package/src/cli/commands/doctor.ts +0 -124
  77. package/src/cli/commands/explain.ts +0 -83
  78. package/src/cli/commands/export.ts +0 -31
  79. package/src/cli/commands/import.ts +0 -199
  80. package/src/cli/commands/insights.ts +0 -65
  81. package/src/cli/commands/learn.ts +0 -24
  82. package/src/cli/commands/modules.ts +0 -53
  83. package/src/cli/commands/network.ts +0 -67
  84. package/src/cli/commands/projects.ts +0 -42
  85. package/src/cli/commands/query.ts +0 -120
  86. package/src/cli/commands/start.ts +0 -62
  87. package/src/cli/commands/status.ts +0 -75
  88. package/src/cli/commands/stop.ts +0 -34
  89. package/src/cli/ipc-helper.ts +0 -22
  90. package/src/cli/update-check.ts +0 -63
  91. package/src/code/analyzer.ts +0 -117
  92. package/src/code/fingerprint.ts +0 -87
  93. package/src/code/matcher.ts +0 -129
  94. package/src/code/parsers/generic.ts +0 -29
  95. package/src/code/parsers/python.ts +0 -54
  96. package/src/code/parsers/typescript.ts +0 -65
  97. package/src/code/registry.ts +0 -60
  98. package/src/code/scorer.ts +0 -120
  99. package/src/config.ts +0 -135
  100. package/src/dashboard/server.ts +0 -142
  101. package/src/db/connection.ts +0 -22
  102. package/src/db/migrations/001_core_schema.ts +0 -120
  103. package/src/db/migrations/002_learning_schema.ts +0 -38
  104. package/src/db/migrations/003_code_schema.ts +0 -53
  105. package/src/db/migrations/004_synapses_schema.ts +0 -57
  106. package/src/db/migrations/005_fts_indexes.ts +0 -78
  107. package/src/db/migrations/006_synapses_phase3.ts +0 -17
  108. package/src/db/migrations/007_feedback.ts +0 -13
  109. package/src/db/migrations/008_git_integration.ts +0 -38
  110. package/src/db/migrations/009_embeddings.ts +0 -8
  111. package/src/db/migrations/index.ts +0 -70
  112. package/src/db/repositories/antipattern.repository.ts +0 -66
  113. package/src/db/repositories/code-module.repository.ts +0 -142
  114. package/src/db/repositories/error.repository.ts +0 -189
  115. package/src/db/repositories/insight.repository.ts +0 -99
  116. package/src/db/repositories/notification.repository.ts +0 -66
  117. package/src/db/repositories/project.repository.ts +0 -93
  118. package/src/db/repositories/rule.repository.ts +0 -108
  119. package/src/db/repositories/solution.repository.ts +0 -154
  120. package/src/db/repositories/synapse.repository.ts +0 -163
  121. package/src/db/repositories/terminal.repository.ts +0 -101
  122. package/src/embeddings/engine.ts +0 -238
  123. package/src/hooks/post-tool-use.ts +0 -92
  124. package/src/hooks/post-write.ts +0 -129
  125. package/src/index.ts +0 -63
  126. package/src/ipc/client.ts +0 -118
  127. package/src/ipc/protocol.ts +0 -35
  128. package/src/ipc/router.ts +0 -133
  129. package/src/ipc/server.ts +0 -176
  130. package/src/learning/confidence-scorer.ts +0 -80
  131. package/src/learning/decay.ts +0 -46
  132. package/src/learning/learning-engine.ts +0 -170
  133. package/src/learning/pattern-extractor.ts +0 -90
  134. package/src/learning/rule-generator.ts +0 -74
  135. package/src/main.rs:10:5 +0 -0
  136. package/src/matching/error-matcher.ts +0 -166
  137. package/src/matching/fingerprint.ts +0 -34
  138. package/src/matching/similarity.ts +0 -61
  139. package/src/matching/tfidf.ts +0 -74
  140. package/src/matching/tokenizer.ts +0 -41
  141. package/src/mcp/auto-detect.ts +0 -93
  142. package/src/mcp/http-server.ts +0 -140
  143. package/src/mcp/server.ts +0 -73
  144. package/src/mcp/tools.ts +0 -328
  145. package/src/parsing/error-parser.ts +0 -28
  146. package/src/parsing/parsers/compiler.ts +0 -93
  147. package/src/parsing/parsers/generic.ts +0 -28
  148. package/src/parsing/parsers/go.ts +0 -97
  149. package/src/parsing/parsers/node.ts +0 -69
  150. package/src/parsing/parsers/python.ts +0 -62
  151. package/src/parsing/parsers/rust.ts +0 -50
  152. package/src/parsing/parsers/shell.ts +0 -42
  153. package/src/parsing/types.ts +0 -47
  154. package/src/research/gap-analyzer.ts +0 -135
  155. package/src/research/insight-generator.ts +0 -123
  156. package/src/research/research-engine.ts +0 -116
  157. package/src/research/synergy-detector.ts +0 -126
  158. package/src/research/template-extractor.ts +0 -130
  159. package/src/research/trend-analyzer.ts +0 -127
  160. package/src/services/analytics.service.ts +0 -226
  161. package/src/services/code.service.ts +0 -271
  162. package/src/services/error.service.ts +0 -266
  163. package/src/services/git.service.ts +0 -132
  164. package/src/services/notification.service.ts +0 -41
  165. package/src/services/prevention.service.ts +0 -159
  166. package/src/services/research.service.ts +0 -98
  167. package/src/services/solution.service.ts +0 -174
  168. package/src/services/synapse.service.ts +0 -59
  169. package/src/services/terminal.service.ts +0 -81
  170. package/src/synapses/activation.ts +0 -80
  171. package/src/synapses/decay.ts +0 -38
  172. package/src/synapses/hebbian.ts +0 -69
  173. package/src/synapses/pathfinder.ts +0 -81
  174. package/src/synapses/synapse-manager.ts +0 -113
  175. package/src/types/code.types.ts +0 -52
  176. package/src/types/config.types.ts +0 -103
  177. package/src/types/error.types.ts +0 -67
  178. package/src/types/ipc.types.ts +0 -8
  179. package/src/types/mcp.types.ts +0 -53
  180. package/src/types/research.types.ts +0 -28
  181. package/src/types/solution.types.ts +0 -30
  182. package/src/types/synapse.types.ts +0 -50
  183. package/src/utils/events.ts +0 -45
  184. package/src/utils/hash.ts +0 -5
  185. package/src/utils/logger.ts +0 -48
  186. package/src/utils/paths.ts +0 -19
  187. package/tests/e2e/test_code_intelligence.py +0 -1015
  188. package/tests/e2e/test_error_memory.py +0 -451
  189. package/tests/e2e/test_full_integration.py +0 -534
  190. package/tests/fixtures/code-modules/modules.ts +0 -83
  191. package/tests/fixtures/errors/go.ts +0 -9
  192. package/tests/fixtures/errors/node.ts +0 -24
  193. package/tests/fixtures/errors/python.ts +0 -21
  194. package/tests/fixtures/errors/rust.ts +0 -25
  195. package/tests/fixtures/errors/shell.ts +0 -15
  196. package/tests/fixtures/solutions/solutions.ts +0 -27
  197. package/tests/helpers/setup-db.ts +0 -52
  198. package/tests/integration/code-flow.test.ts +0 -86
  199. package/tests/integration/error-flow.test.ts +0 -83
  200. package/tests/integration/ipc-flow.test.ts +0 -166
  201. package/tests/integration/learning-cycle.test.ts +0 -82
  202. package/tests/integration/synapse-flow.test.ts +0 -117
  203. package/tests/unit/code/analyzer.test.ts +0 -58
  204. package/tests/unit/code/fingerprint.test.ts +0 -51
  205. package/tests/unit/code/scorer.test.ts +0 -55
  206. package/tests/unit/learning/confidence-scorer.test.ts +0 -60
  207. package/tests/unit/learning/decay.test.ts +0 -45
  208. package/tests/unit/learning/pattern-extractor.test.ts +0 -50
  209. package/tests/unit/matching/error-matcher.test.ts +0 -69
  210. package/tests/unit/matching/fingerprint.test.ts +0 -47
  211. package/tests/unit/matching/similarity.test.ts +0 -65
  212. package/tests/unit/matching/tfidf.test.ts +0 -71
  213. package/tests/unit/matching/tokenizer.test.ts +0 -83
  214. package/tests/unit/parsing/parsers.test.ts +0 -113
  215. package/tests/unit/research/gap-analyzer.test.ts +0 -45
  216. package/tests/unit/research/trend-analyzer.test.ts +0 -45
  217. package/tests/unit/synapses/activation.test.ts +0 -80
  218. package/tests/unit/synapses/decay.test.ts +0 -27
  219. package/tests/unit/synapses/hebbian.test.ts +0 -96
  220. package/tests/unit/synapses/pathfinder.test.ts +0 -72
  221. package/tsconfig.json +0 -18
@@ -0,0 +1,75 @@
1
+ import { describe, it, expect, afterEach } from 'vitest';
2
+ import os from 'node:os';
3
+ import path from 'node:path';
4
+ import { normalizePath, getDataDir, getPipeName } from '../paths.js';
5
+ describe('normalizePath', () => {
6
+ it('converts backslashes to forward slashes', () => {
7
+ expect(normalizePath('C:\\Users\\test\\file.ts')).toBe('C:/Users/test/file.ts');
8
+ });
9
+ it('leaves forward slashes unchanged', () => {
10
+ expect(normalizePath('/home/user/file.ts')).toBe('/home/user/file.ts');
11
+ });
12
+ it('handles mixed slashes', () => {
13
+ expect(normalizePath('src\\utils/hash.ts')).toBe('src/utils/hash.ts');
14
+ });
15
+ it('handles empty string', () => {
16
+ expect(normalizePath('')).toBe('');
17
+ });
18
+ it('handles path with no slashes', () => {
19
+ expect(normalizePath('file.ts')).toBe('file.ts');
20
+ });
21
+ it('handles multiple consecutive backslashes', () => {
22
+ expect(normalizePath('a\\\\b\\\\c')).toBe('a//b//c');
23
+ });
24
+ });
25
+ describe('getDataDir', () => {
26
+ const originalEnv = process.env['BRAIN_DATA_DIR'];
27
+ afterEach(() => {
28
+ if (originalEnv !== undefined) {
29
+ process.env['BRAIN_DATA_DIR'] = originalEnv;
30
+ }
31
+ else {
32
+ delete process.env['BRAIN_DATA_DIR'];
33
+ }
34
+ });
35
+ it('returns BRAIN_DATA_DIR when env variable is set', () => {
36
+ process.env['BRAIN_DATA_DIR'] = '/tmp/brain-test';
37
+ const dir = getDataDir();
38
+ expect(dir).toBe(path.resolve('/tmp/brain-test'));
39
+ });
40
+ it('resolves relative BRAIN_DATA_DIR to absolute path', () => {
41
+ process.env['BRAIN_DATA_DIR'] = './data';
42
+ const dir = getDataDir();
43
+ expect(path.isAbsolute(dir)).toBe(true);
44
+ });
45
+ it('returns ~/.brain when env variable is not set', () => {
46
+ delete process.env['BRAIN_DATA_DIR'];
47
+ const dir = getDataDir();
48
+ expect(dir).toBe(path.join(os.homedir(), '.brain'));
49
+ });
50
+ });
51
+ describe('getPipeName', () => {
52
+ it('uses default name "brain"', () => {
53
+ const pipe = getPipeName();
54
+ if (process.platform === 'win32') {
55
+ expect(pipe).toBe('\\\\.\\pipe\\brain');
56
+ }
57
+ else {
58
+ expect(pipe).toBe(path.join(os.tmpdir(), 'brain.sock'));
59
+ }
60
+ });
61
+ it('accepts a custom name', () => {
62
+ const pipe = getPipeName('custom');
63
+ if (process.platform === 'win32') {
64
+ expect(pipe).toBe('\\\\.\\pipe\\custom');
65
+ }
66
+ else {
67
+ expect(pipe).toBe(path.join(os.tmpdir(), 'custom.sock'));
68
+ }
69
+ });
70
+ it('returns a string containing the name', () => {
71
+ const pipe = getPipeName('myservice');
72
+ expect(pipe).toContain('myservice');
73
+ });
74
+ });
75
+ //# 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":"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"}
@@ -1,5 +1,5 @@
1
- import { EventEmitter } from 'node:events';
2
- export interface BrainEvents {
1
+ import { TypedEventBus as GenericEventBus } from '@timmeck/brain-core';
2
+ export type BrainEvents = {
3
3
  'error:reported': {
4
4
  errorId: number;
5
5
  projectId: number;
@@ -48,12 +48,8 @@ export interface BrainEvents {
48
48
  'terminal:disconnected': {
49
49
  terminalId: number;
50
50
  };
51
- }
51
+ };
52
52
  export type BrainEventName = keyof BrainEvents;
53
- export declare class TypedEventBus extends EventEmitter {
54
- emit<K extends BrainEventName>(event: K, data: BrainEvents[K]): boolean;
55
- on<K extends BrainEventName>(event: K, listener: (data: BrainEvents[K]) => void): this;
56
- once<K extends BrainEventName>(event: K, listener: (data: BrainEvents[K]) => void): this;
57
- off<K extends BrainEventName>(event: K, listener: (data: BrainEvents[K]) => void): this;
53
+ export declare class TypedEventBus extends GenericEventBus<BrainEvents> {
58
54
  }
59
55
  export declare function getEventBus(): TypedEventBus;
@@ -1,17 +1,5 @@
1
- import { EventEmitter } from 'node:events';
2
- export class TypedEventBus extends EventEmitter {
3
- emit(event, data) {
4
- return super.emit(event, data);
5
- }
6
- on(event, listener) {
7
- return super.on(event, listener);
8
- }
9
- once(event, listener) {
10
- return super.once(event, listener);
11
- }
12
- off(event, listener) {
13
- return super.off(event, listener);
14
- }
1
+ import { TypedEventBus as GenericEventBus } from '@timmeck/brain-core';
2
+ export class TypedEventBus extends GenericEventBus {
15
3
  }
16
4
  let busInstance = null;
17
5
  export function getEventBus() {
@@ -1 +1 @@
1
- {"version":3,"file":"events.js","sourceRoot":"","sources":["../../src/utils/events.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAmB3C,MAAM,OAAO,aAAc,SAAQ,YAAY;IAC7C,IAAI,CAA2B,KAAQ,EAAE,IAAoB;QAC3D,OAAO,KAAK,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;IACjC,CAAC;IAED,EAAE,CAA2B,KAAQ,EAAE,QAAwC;QAC7E,OAAO,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;IACnC,CAAC;IAED,IAAI,CAA2B,KAAQ,EAAE,QAAwC;QAC/E,OAAO,KAAK,CAAC,IAAI,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;IACrC,CAAC;IAED,GAAG,CAA2B,KAAQ,EAAE,QAAwC;QAC9E,OAAO,KAAK,CAAC,GAAG,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;IACpC,CAAC;CACF;AAED,IAAI,WAAW,GAAyB,IAAI,CAAC;AAE7C,MAAM,UAAU,WAAW;IACzB,IAAI,CAAC,WAAW,EAAE,CAAC;QACjB,WAAW,GAAG,IAAI,aAAa,EAAE,CAAC;IACpC,CAAC;IACD,OAAO,WAAW,CAAC;AACrB,CAAC"}
1
+ {"version":3,"file":"events.js","sourceRoot":"","sources":["../../src/utils/events.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,IAAI,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAmBvE,MAAM,OAAO,aAAc,SAAQ,eAA4B;CAAG;AAElE,IAAI,WAAW,GAAyB,IAAI,CAAC;AAE7C,MAAM,UAAU,WAAW;IACzB,IAAI,CAAC,WAAW,EAAE,CAAC;QACjB,WAAW,GAAG,IAAI,aAAa,EAAE,CAAC;IACpC,CAAC;IACD,OAAO,WAAW,CAAC;AACrB,CAAC"}
@@ -1 +1 @@
1
- export declare function sha256(input: string): string;
1
+ export { sha256 } from '@timmeck/brain-core';
@@ -1,5 +1,2 @@
1
- import { createHash } from 'node:crypto';
2
- export function sha256(input) {
3
- return createHash('sha256').update(input).digest('hex');
4
- }
1
+ export { sha256 } from '@timmeck/brain-core';
5
2
  //# sourceMappingURL=hash.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"hash.js","sourceRoot":"","sources":["../../src/utils/hash.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEzC,MAAM,UAAU,MAAM,CAAC,KAAa;IAClC,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAC1D,CAAC"}
1
+ {"version":3,"file":"hash.js","sourceRoot":"","sources":["../../src/utils/hash.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC"}
@@ -1,8 +1,9 @@
1
- import winston from 'winston';
1
+ import { getLogger, resetLogger } from '@timmeck/brain-core';
2
+ import type winston from 'winston';
2
3
  export declare function createLogger(opts?: {
3
4
  level?: string;
4
5
  file?: string;
5
6
  maxSize?: number;
6
7
  maxFiles?: number;
7
8
  }): winston.Logger;
8
- export declare function getLogger(): winston.Logger;
9
+ export { getLogger, resetLogger };
@@ -1,39 +1,12 @@
1
- import winston from 'winston';
2
- import path from 'node:path';
1
+ import { createLogger as coreCreateLogger, getLogger, resetLogger } from '@timmeck/brain-core';
3
2
  import { getDataDir } from './paths.js';
4
- const { combine, timestamp, printf, colorize } = winston.format;
5
- const logFormat = printf(({ level, message, timestamp, ...meta }) => {
6
- const metaStr = Object.keys(meta).length ? ` ${JSON.stringify(meta)}` : '';
7
- return `${timestamp} [${level}]${metaStr} ${message}`;
8
- });
9
- let loggerInstance = null;
10
3
  export function createLogger(opts) {
11
- if (loggerInstance)
12
- return loggerInstance;
13
- const level = opts?.level ?? process.env['BRAIN_LOG_LEVEL'] ?? 'info';
14
- const logFile = opts?.file ?? path.join(getDataDir(), 'brain.log');
15
- const maxSize = opts?.maxSize ?? 10 * 1024 * 1024; // 10MB
16
- const maxFiles = opts?.maxFiles ?? 3;
17
- const transports = [
18
- new winston.transports.File({
19
- filename: logFile,
20
- maxsize: maxSize,
21
- maxFiles,
22
- format: combine(timestamp(), logFormat),
23
- }),
24
- ];
25
- if (process.env['NODE_ENV'] !== 'production') {
26
- transports.push(new winston.transports.Console({
27
- format: combine(colorize(), timestamp(), logFormat),
28
- }));
29
- }
30
- loggerInstance = winston.createLogger({ level, transports });
31
- return loggerInstance;
32
- }
33
- export function getLogger() {
34
- if (!loggerInstance) {
35
- return createLogger();
36
- }
37
- return loggerInstance;
4
+ return coreCreateLogger({
5
+ ...opts,
6
+ envVar: 'BRAIN_LOG_LEVEL',
7
+ defaultFilename: 'brain.log',
8
+ dataDir: opts?.file ? undefined : getDataDir(),
9
+ });
38
10
  }
11
+ export { getLogger, resetLogger };
39
12
  //# sourceMappingURL=logger.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,SAAS,CAAC;AAC9B,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAExC,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC;AAEhE,MAAM,SAAS,GAAG,MAAM,CAAC,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,GAAG,IAAI,EAAE,EAAE,EAAE;IAClE,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IAC3E,OAAO,GAAG,SAAS,KAAK,KAAK,IAAI,OAAO,IAAI,OAAO,EAAE,CAAC;AACxD,CAAC,CAAC,CAAC;AAEH,IAAI,cAAc,GAA0B,IAAI,CAAC;AAEjD,MAAM,UAAU,YAAY,CAAC,IAA6E;IACxG,IAAI,cAAc;QAAE,OAAO,cAAc,CAAC;IAE1C,MAAM,KAAK,GAAG,IAAI,EAAE,KAAK,IAAI,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC,IAAI,MAAM,CAAC;IACtE,MAAM,OAAO,GAAG,IAAI,EAAE,IAAI,IAAI,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,EAAE,WAAW,CAAC,CAAC;IACnE,MAAM,OAAO,GAAG,IAAI,EAAE,OAAO,IAAI,EAAE,GAAG,IAAI,GAAG,IAAI,CAAC,CAAC,OAAO;IAC1D,MAAM,QAAQ,GAAG,IAAI,EAAE,QAAQ,IAAI,CAAC,CAAC;IAErC,MAAM,UAAU,GAAwB;QACtC,IAAI,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC;YAC1B,QAAQ,EAAE,OAAO;YACjB,OAAO,EAAE,OAAO;YAChB,QAAQ;YACR,MAAM,EAAE,OAAO,CAAC,SAAS,EAAE,EAAE,SAAS,CAAC;SACxC,CAAC;KACH,CAAC;IAEF,IAAI,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,KAAK,YAAY,EAAE,CAAC;QAC7C,UAAU,CAAC,IAAI,CACb,IAAI,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC;YAC7B,MAAM,EAAE,OAAO,CAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,EAAE,SAAS,CAAC;SACpD,CAAC,CACH,CAAC;IACJ,CAAC;IAED,cAAc,GAAG,OAAO,CAAC,YAAY,CAAC,EAAE,KAAK,EAAE,UAAU,EAAE,CAAC,CAAC;IAC7D,OAAO,cAAc,CAAC;AACxB,CAAC;AAED,MAAM,UAAU,SAAS;IACvB,IAAI,CAAC,cAAc,EAAE,CAAC;QACpB,OAAO,YAAY,EAAE,CAAC;IACxB,CAAC;IACD,OAAO,cAAc,CAAC;AACxB,CAAC"}
1
+ {"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,IAAI,gBAAgB,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAE/F,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAExC,MAAM,UAAU,YAAY,CAAC,IAA6E;IACxG,OAAO,gBAAgB,CAAC;QACtB,GAAG,IAAI;QACP,MAAM,EAAE,iBAAiB;QACzB,eAAe,EAAE,WAAW;QAC5B,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,UAAU,EAAE;KAC/C,CAAC,CAAC;AACL,CAAC;AAED,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,CAAC"}
@@ -1,3 +1,4 @@
1
- export declare function normalizePath(filePath: string): string;
1
+ import { normalizePath } from '@timmeck/brain-core';
2
+ export { normalizePath };
2
3
  export declare function getDataDir(): string;
3
4
  export declare function getPipeName(name?: string): string;
@@ -1,18 +1,9 @@
1
- import path from 'node:path';
2
- import os from 'node:os';
3
- export function normalizePath(filePath) {
4
- return filePath.replace(/\\/g, '/');
5
- }
1
+ import { normalizePath, getDataDir as coreGetDataDir, getPipeName as coreGetPipeName } from '@timmeck/brain-core';
2
+ export { normalizePath };
6
3
  export function getDataDir() {
7
- const envDir = process.env['BRAIN_DATA_DIR'];
8
- if (envDir)
9
- return path.resolve(envDir);
10
- return path.join(os.homedir(), '.brain');
4
+ return coreGetDataDir('BRAIN_DATA_DIR', '.brain');
11
5
  }
12
6
  export function getPipeName(name = 'brain') {
13
- if (process.platform === 'win32') {
14
- return `\\\\.\\pipe\\${name}`;
15
- }
16
- return path.join(os.tmpdir(), `${name}.sock`);
7
+ return coreGetPipeName(name);
17
8
  }
18
9
  //# sourceMappingURL=paths.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"paths.js","sourceRoot":"","sources":["../../src/utils/paths.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,MAAM,SAAS,CAAC;AAEzB,MAAM,UAAU,aAAa,CAAC,QAAgB;IAC5C,OAAO,QAAQ,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;AACtC,CAAC;AAED,MAAM,UAAU,UAAU;IACxB,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC;IAC7C,IAAI,MAAM;QAAE,OAAO,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IACxC,OAAO,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,QAAQ,CAAC,CAAC;AAC3C,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,OAAe,OAAO;IAChD,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC;QACjC,OAAO,gBAAgB,IAAI,EAAE,CAAC;IAChC,CAAC;IACD,OAAO,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,GAAG,IAAI,OAAO,CAAC,CAAC;AAChD,CAAC"}
1
+ {"version":3,"file":"paths.js","sourceRoot":"","sources":["../../src/utils/paths.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,UAAU,IAAI,cAAc,EAAE,WAAW,IAAI,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAElH,OAAO,EAAE,aAAa,EAAE,CAAC;AAEzB,MAAM,UAAU,UAAU;IACxB,OAAO,cAAc,CAAC,gBAAgB,EAAE,QAAQ,CAAC,CAAC;AACpD,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,OAAe,OAAO;IAChD,OAAO,eAAe,CAAC,IAAI,CAAC,CAAC;AAC/B,CAAC"}
package/gen_avatar.py ADDED
@@ -0,0 +1,142 @@
1
+ """Generate a circular Brain avatar for GitHub/X profile pictures."""
2
+ from PIL import Image, ImageDraw, ImageFilter, ImageFont
3
+ import math
4
+ import random
5
+
6
+ random.seed(42)
7
+
8
+ SIZE = 1024
9
+ CENTER = SIZE // 2
10
+ R = SIZE // 2 - 20 # circle radius
11
+
12
+ img = Image.new('RGBA', (SIZE, SIZE), (0, 0, 0, 0))
13
+ draw = ImageDraw.Draw(img)
14
+
15
+ # --- Background circle with dark gradient ---
16
+ bg = Image.new('RGBA', (SIZE, SIZE), (0, 0, 0, 0))
17
+ bg_draw = ImageDraw.Draw(bg)
18
+ for r in range(R, 0, -1):
19
+ t = r / R
20
+ c1 = (10, 12, 28) # center
21
+ c2 = (18, 20, 42) # edge
22
+ color = tuple(int(c1[i] * t + c2[i] * (1 - t)) for i in range(3))
23
+ bg_draw.ellipse([CENTER - r, CENTER - r, CENTER + r, CENTER + r], fill=(*color, 255))
24
+ img = Image.alpha_composite(img, bg)
25
+
26
+ # --- Generate synapse network nodes ---
27
+ node_types = {
28
+ 'project': {'color': (255, 179, 71), 'count': 4, 'radius': (18, 28)},
29
+ 'code_module': {'color': (180, 122, 255), 'count': 22, 'radius': (6, 12)},
30
+ 'error': {'color': (255, 85, 119), 'count': 10, 'radius': (7, 13)},
31
+ 'solution': {'color': (61, 255, 160), 'count': 6, 'radius': (7, 11)},
32
+ 'rule': {'color': (91, 156, 255), 'count': 5, 'radius': (5, 9)},
33
+ }
34
+
35
+ nodes = []
36
+ for ntype, cfg in node_types.items():
37
+ for _ in range(cfg['count']):
38
+ # Place within circle
39
+ for _attempt in range(50):
40
+ angle = random.uniform(0, 2 * math.pi)
41
+ dist = random.uniform(40, R - 50)
42
+ x = CENTER + math.cos(angle) * dist
43
+ y = CENTER + math.sin(angle) * dist
44
+ # Check no overlap
45
+ too_close = False
46
+ for n in nodes:
47
+ if math.hypot(x - n['x'], y - n['y']) < 35:
48
+ too_close = True
49
+ break
50
+ if not too_close:
51
+ break
52
+ r = random.randint(*cfg['radius'])
53
+ nodes.append({'x': x, 'y': y, 'r': r, 'type': ntype, 'color': cfg['color']})
54
+
55
+ # --- Create edges between nearby nodes ---
56
+ edges = []
57
+ for i, n1 in enumerate(nodes):
58
+ distances = []
59
+ for j, n2 in enumerate(nodes):
60
+ if i == j:
61
+ continue
62
+ d = math.hypot(n1['x'] - n2['x'], n1['y'] - n2['y'])
63
+ distances.append((d, j))
64
+ distances.sort()
65
+ # Connect to 2-4 nearest
66
+ count = random.randint(2, 4) if n1['type'] == 'project' else random.randint(1, 3)
67
+ for d, j in distances[:count]:
68
+ if d < R * 1.2:
69
+ edge = tuple(sorted([i, j]))
70
+ if edge not in edges:
71
+ edges.append(edge)
72
+
73
+ # --- Draw on a separate layer for glow ---
74
+ glow_layer = Image.new('RGBA', (SIZE, SIZE), (0, 0, 0, 0))
75
+ glow_draw = ImageDraw.Draw(glow_layer)
76
+
77
+ # Edge colors by type combination
78
+ EDGE_COLORS = {
79
+ 'project': (91, 156, 255, 50),
80
+ 'code_module': (140, 100, 220, 40),
81
+ 'error': (200, 80, 100, 40),
82
+ 'solution': (50, 200, 130, 45),
83
+ 'rule': (70, 130, 220, 40),
84
+ }
85
+
86
+ # Draw edges
87
+ for i, j in edges:
88
+ n1, n2 = nodes[i], nodes[j]
89
+ ec = EDGE_COLORS.get(n1['type'], (91, 156, 255, 40))
90
+ glow_draw.line([(n1['x'], n1['y']), (n2['x'], n2['y'])], fill=ec, width=2)
91
+
92
+ # Draw edge glow
93
+ edge_glow = glow_layer.filter(ImageFilter.GaussianBlur(4))
94
+ img = Image.alpha_composite(img, edge_glow)
95
+ img = Image.alpha_composite(img, glow_layer)
96
+
97
+ # --- Draw nodes with glow ---
98
+ for n in nodes:
99
+ color = n['color']
100
+ r = n['r']
101
+ x, y = int(n['x']), int(n['y'])
102
+
103
+ # Outer glow
104
+ glow = Image.new('RGBA', (SIZE, SIZE), (0, 0, 0, 0))
105
+ g_draw = ImageDraw.Draw(glow)
106
+ glow_r = r + 12
107
+ g_draw.ellipse([x - glow_r, y - glow_r, x + glow_r, y + glow_r],
108
+ fill=(*color, 40))
109
+ glow = glow.filter(ImageFilter.GaussianBlur(10))
110
+ img = Image.alpha_composite(img, glow)
111
+
112
+ # Core node
113
+ draw = ImageDraw.Draw(img)
114
+ draw.ellipse([x - r, y - r, x + r, y + r], fill=(*color, 220))
115
+
116
+ # Inner highlight
117
+ hr = max(2, r // 3)
118
+ hx, hy = x - r // 4, y - r // 4
119
+ draw.ellipse([hx - hr, hy - hr, hx + hr, hy + hr], fill=(255, 255, 255, 70))
120
+
121
+ # --- Circular mask ---
122
+ mask = Image.new('L', (SIZE, SIZE), 0)
123
+ mask_draw = ImageDraw.Draw(mask)
124
+ mask_draw.ellipse([CENTER - R, CENTER - R, CENTER + R, CENTER + R], fill=255)
125
+ img.putalpha(mask)
126
+
127
+ # --- Subtle border ring ---
128
+ draw = ImageDraw.Draw(img)
129
+ for offset in range(3):
130
+ alpha = 80 - offset * 25
131
+ draw.ellipse([CENTER - R + offset, CENTER - R + offset, CENTER + R - offset, CENTER + R - offset],
132
+ outline=(91, 156, 255, max(alpha, 10)), width=1)
133
+
134
+ # --- Save ---
135
+ img.save('C:/Users/mecklenburg/Desktop/brain/assets/brain-avatar.png')
136
+
137
+ # Also save smaller sizes for different platforms
138
+ for size, name in [(512, 'brain-avatar-512.png'), (256, 'brain-avatar-256.png')]:
139
+ resized = img.resize((size, size), Image.LANCZOS)
140
+ resized.save(f'C:/Users/mecklenburg/Desktop/brain/assets/{name}')
141
+
142
+ print(f'Generated: brain-avatar.png (1024px), brain-avatar-512.png, brain-avatar-256.png')
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@timmeck/brain",
3
- "version": "1.8.5",
3
+ "version": "2.0.0",
4
4
  "description": "Adaptive error memory and code intelligence system with Hebbian synapse network, hybrid search, and REST API",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -34,6 +34,7 @@
34
34
  "dependencies": {
35
35
  "@huggingface/transformers": "^3.8.1",
36
36
  "@modelcontextprotocol/sdk": "^1.0.0",
37
+ "@timmeck/brain-core": "^1.1.0",
37
38
  "better-sqlite3": "^11.7.0",
38
39
  "chalk": "^5.6.2",
39
40
  "commander": "^13.0.0",