@timmeck/brain-core 2.36.62 → 2.36.64

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 (270) hide show
  1. package/dist/action/handlers/index.d.ts +2 -0
  2. package/dist/action/handlers/index.js +1 -0
  3. package/dist/action/handlers/index.js.map +1 -1
  4. package/dist/action/handlers/mission-handler.d.ts +17 -0
  5. package/dist/action/handlers/mission-handler.js +49 -0
  6. package/dist/action/handlers/mission-handler.js.map +1 -0
  7. package/dist/action/index.d.ts +2 -2
  8. package/dist/action/index.js +1 -1
  9. package/dist/action/index.js.map +1 -1
  10. package/dist/guardrails/guardrail-engine.d.ts +2 -0
  11. package/dist/guardrails/guardrail-engine.js +17 -9
  12. package/dist/guardrails/guardrail-engine.js.map +1 -1
  13. package/dist/index.d.ts +3 -1
  14. package/dist/index.js +2 -1
  15. package/dist/index.js.map +1 -1
  16. package/dist/metacognition/evolution-engine.d.ts +3 -0
  17. package/dist/metacognition/evolution-engine.js +25 -1
  18. package/dist/metacognition/evolution-engine.js.map +1 -1
  19. package/dist/narrative/narrative-engine.d.ts +4 -0
  20. package/dist/narrative/narrative-engine.js +17 -0
  21. package/dist/narrative/narrative-engine.js.map +1 -1
  22. package/dist/research/research-orchestrator.js +56 -5
  23. package/dist/research/research-orchestrator.js.map +1 -1
  24. package/dist/utils/memory-watchdog.d.ts +33 -0
  25. package/dist/utils/memory-watchdog.js +88 -0
  26. package/dist/utils/memory-watchdog.js.map +1 -0
  27. package/package.json +1 -1
  28. package/dist/action/__tests__/action-bridge.test.d.ts +0 -1
  29. package/dist/action/__tests__/action-bridge.test.js +0 -175
  30. package/dist/action/__tests__/action-bridge.test.js.map +0 -1
  31. package/dist/action/__tests__/adjust-parameter-handler.test.d.ts +0 -1
  32. package/dist/action/__tests__/adjust-parameter-handler.test.js +0 -138
  33. package/dist/action/__tests__/adjust-parameter-handler.test.js.map +0 -1
  34. package/dist/action/__tests__/content-handler.test.d.ts +0 -1
  35. package/dist/action/__tests__/content-handler.test.js +0 -100
  36. package/dist/action/__tests__/content-handler.test.js.map +0 -1
  37. package/dist/action/__tests__/creative-seed-handler.test.d.ts +0 -1
  38. package/dist/action/__tests__/creative-seed-handler.test.js +0 -96
  39. package/dist/action/__tests__/creative-seed-handler.test.js.map +0 -1
  40. package/dist/action/__tests__/trade-handler.test.d.ts +0 -1
  41. package/dist/action/__tests__/trade-handler.test.js +0 -165
  42. package/dist/action/__tests__/trade-handler.test.js.map +0 -1
  43. package/dist/active-learning/__tests__/active-learning.test.d.ts +0 -1
  44. package/dist/active-learning/__tests__/active-learning.test.js +0 -132
  45. package/dist/active-learning/__tests__/active-learning.test.js.map +0 -1
  46. package/dist/agent-training/__tests__/agent-trainer.test.d.ts +0 -1
  47. package/dist/agent-training/__tests__/agent-trainer.test.js +0 -158
  48. package/dist/agent-training/__tests__/agent-trainer.test.js.map +0 -1
  49. package/dist/agent-training/__tests__/sub-agent-factory.test.d.ts +0 -1
  50. package/dist/agent-training/__tests__/sub-agent-factory.test.js +0 -100
  51. package/dist/agent-training/__tests__/sub-agent-factory.test.js.map +0 -1
  52. package/dist/agent-training/__tests__/sub-agent.test.d.ts +0 -1
  53. package/dist/agent-training/__tests__/sub-agent.test.js +0 -102
  54. package/dist/agent-training/__tests__/sub-agent.test.js.map +0 -1
  55. package/dist/chat/__tests__/chat-engine.test.d.ts +0 -1
  56. package/dist/chat/__tests__/chat-engine.test.js +0 -209
  57. package/dist/chat/__tests__/chat-engine.test.js.map +0 -1
  58. package/dist/checkpoint/__tests__/checkpoint-manager.test.d.ts +0 -1
  59. package/dist/checkpoint/__tests__/checkpoint-manager.test.js +0 -160
  60. package/dist/checkpoint/__tests__/checkpoint-manager.test.js.map +0 -1
  61. package/dist/code-health/__tests__/code-health.test.d.ts +0 -1
  62. package/dist/code-health/__tests__/code-health.test.js +0 -123
  63. package/dist/code-health/__tests__/code-health.test.js.map +0 -1
  64. package/dist/codegen/__tests__/code-forge.test.d.ts +0 -1
  65. package/dist/codegen/__tests__/code-forge.test.js +0 -105
  66. package/dist/codegen/__tests__/code-forge.test.js.map +0 -1
  67. package/dist/config/__tests__/loader.test.d.ts +0 -1
  68. package/dist/config/__tests__/loader.test.js +0 -86
  69. package/dist/config/__tests__/loader.test.js.map +0 -1
  70. package/dist/consciousness/__tests__/thought-stream.test.d.ts +0 -1
  71. package/dist/consciousness/__tests__/thought-stream.test.js +0 -62
  72. package/dist/consciousness/__tests__/thought-stream.test.js.map +0 -1
  73. package/dist/consensus/__tests__/consensus.test.d.ts +0 -1
  74. package/dist/consensus/__tests__/consensus.test.js +0 -159
  75. package/dist/consensus/__tests__/consensus.test.js.map +0 -1
  76. package/dist/content/__tests__/auto-publisher.test.d.ts +0 -1
  77. package/dist/content/__tests__/auto-publisher.test.js +0 -125
  78. package/dist/content/__tests__/auto-publisher.test.js.map +0 -1
  79. package/dist/content/__tests__/content-forge.test.d.ts +0 -1
  80. package/dist/content/__tests__/content-forge.test.js +0 -117
  81. package/dist/content/__tests__/content-forge.test.js.map +0 -1
  82. package/dist/creative/__tests__/creative-engine.test.d.ts +0 -1
  83. package/dist/creative/__tests__/creative-engine.test.js +0 -229
  84. package/dist/creative/__tests__/creative-engine.test.js.map +0 -1
  85. package/dist/cross-brain/__tests__/borg-sync-engine.test.d.ts +0 -1
  86. package/dist/cross-brain/__tests__/borg-sync-engine.test.js +0 -240
  87. package/dist/cross-brain/__tests__/borg-sync-engine.test.js.map +0 -1
  88. package/dist/cross-brain/__tests__/client.test.d.ts +0 -1
  89. package/dist/cross-brain/__tests__/client.test.js +0 -31
  90. package/dist/cross-brain/__tests__/client.test.js.map +0 -1
  91. package/dist/cross-brain/__tests__/notifications.test.d.ts +0 -1
  92. package/dist/cross-brain/__tests__/notifications.test.js +0 -52
  93. package/dist/cross-brain/__tests__/notifications.test.js.map +0 -1
  94. package/dist/cross-brain/__tests__/signal-router.test.d.ts +0 -1
  95. package/dist/cross-brain/__tests__/signal-router.test.js +0 -218
  96. package/dist/cross-brain/__tests__/signal-router.test.js.map +0 -1
  97. package/dist/cross-brain/__tests__/subscription.test.d.ts +0 -1
  98. package/dist/cross-brain/__tests__/subscription.test.js +0 -75
  99. package/dist/cross-brain/__tests__/subscription.test.js.map +0 -1
  100. package/dist/dashboard/__tests__/command-center-server.test.d.ts +0 -1
  101. package/dist/dashboard/__tests__/command-center-server.test.js +0 -522
  102. package/dist/dashboard/__tests__/command-center-server.test.js.map +0 -1
  103. package/dist/dashboard/__tests__/server.test.d.ts +0 -1
  104. package/dist/dashboard/__tests__/server.test.js +0 -105
  105. package/dist/dashboard/__tests__/server.test.js.map +0 -1
  106. package/dist/db/__tests__/connection.test.d.ts +0 -1
  107. package/dist/db/__tests__/connection.test.js +0 -135
  108. package/dist/db/__tests__/connection.test.js.map +0 -1
  109. package/dist/dream/__tests__/dream-engine.test.d.ts +0 -1
  110. package/dist/dream/__tests__/dream-engine.test.js +0 -184
  111. package/dist/dream/__tests__/dream-engine.test.js.map +0 -1
  112. package/dist/embeddings/__tests__/engine.test.d.ts +0 -1
  113. package/dist/embeddings/__tests__/engine.test.js +0 -82
  114. package/dist/embeddings/__tests__/engine.test.js.map +0 -1
  115. package/dist/feedback/__tests__/feedback-engine.test.d.ts +0 -1
  116. package/dist/feedback/__tests__/feedback-engine.test.js +0 -156
  117. package/dist/feedback/__tests__/feedback-engine.test.js.map +0 -1
  118. package/dist/feedback/__tests__/feedback-router.test.d.ts +0 -1
  119. package/dist/feedback/__tests__/feedback-router.test.js +0 -173
  120. package/dist/feedback/__tests__/feedback-router.test.js.map +0 -1
  121. package/dist/goals/__tests__/goal-engine.test.d.ts +0 -1
  122. package/dist/goals/__tests__/goal-engine.test.js +0 -203
  123. package/dist/goals/__tests__/goal-engine.test.js.map +0 -1
  124. package/dist/guardrails/__tests__/guardrail-engine.test.d.ts +0 -1
  125. package/dist/guardrails/__tests__/guardrail-engine.test.js +0 -343
  126. package/dist/guardrails/__tests__/guardrail-engine.test.js.map +0 -1
  127. package/dist/ipc/__tests__/integration.test.d.ts +0 -1
  128. package/dist/ipc/__tests__/integration.test.js +0 -352
  129. package/dist/ipc/__tests__/integration.test.js.map +0 -1
  130. package/dist/ipc/__tests__/protocol.test.d.ts +0 -1
  131. package/dist/ipc/__tests__/protocol.test.js +0 -69
  132. package/dist/ipc/__tests__/protocol.test.js.map +0 -1
  133. package/dist/knowledge-graph/__tests__/contradiction-resolver.test.d.ts +0 -1
  134. package/dist/knowledge-graph/__tests__/contradiction-resolver.test.js +0 -114
  135. package/dist/knowledge-graph/__tests__/contradiction-resolver.test.js.map +0 -1
  136. package/dist/knowledge-graph/__tests__/knowledge-graph.test.d.ts +0 -1
  137. package/dist/knowledge-graph/__tests__/knowledge-graph.test.js +0 -215
  138. package/dist/knowledge-graph/__tests__/knowledge-graph.test.js.map +0 -1
  139. package/dist/learning/__tests__/base-engine.test.d.ts +0 -1
  140. package/dist/learning/__tests__/base-engine.test.js +0 -49
  141. package/dist/learning/__tests__/base-engine.test.js.map +0 -1
  142. package/dist/llm/__tests__/anthropic-provider.test.d.ts +0 -1
  143. package/dist/llm/__tests__/anthropic-provider.test.js +0 -121
  144. package/dist/llm/__tests__/anthropic-provider.test.js.map +0 -1
  145. package/dist/llm/__tests__/llm-service.test.d.ts +0 -1
  146. package/dist/llm/__tests__/llm-service.test.js +0 -507
  147. package/dist/llm/__tests__/llm-service.test.js.map +0 -1
  148. package/dist/llm/__tests__/ollama-embedding.test.d.ts +0 -1
  149. package/dist/llm/__tests__/ollama-embedding.test.js +0 -128
  150. package/dist/llm/__tests__/ollama-embedding.test.js.map +0 -1
  151. package/dist/llm/__tests__/ollama-provider.test.d.ts +0 -1
  152. package/dist/llm/__tests__/ollama-provider.test.js +0 -213
  153. package/dist/llm/__tests__/ollama-provider.test.js.map +0 -1
  154. package/dist/llm/__tests__/provider.test.d.ts +0 -1
  155. package/dist/llm/__tests__/provider.test.js +0 -126
  156. package/dist/llm/__tests__/provider.test.js.map +0 -1
  157. package/dist/math/__tests__/time-decay.test.d.ts +0 -1
  158. package/dist/math/__tests__/time-decay.test.js +0 -37
  159. package/dist/math/__tests__/time-decay.test.js.map +0 -1
  160. package/dist/math/__tests__/wilson-score.test.d.ts +0 -1
  161. package/dist/math/__tests__/wilson-score.test.js +0 -43
  162. package/dist/math/__tests__/wilson-score.test.js.map +0 -1
  163. package/dist/memory/__tests__/base-memory-engine.test.d.ts +0 -1
  164. package/dist/memory/__tests__/base-memory-engine.test.js +0 -233
  165. package/dist/memory/__tests__/base-memory-engine.test.js.map +0 -1
  166. package/dist/metacognition/__tests__/auto-experiment-engine.test.d.ts +0 -1
  167. package/dist/metacognition/__tests__/auto-experiment-engine.test.js +0 -218
  168. package/dist/metacognition/__tests__/auto-experiment-engine.test.js.map +0 -1
  169. package/dist/metacognition/__tests__/evolution-engine.test.d.ts +0 -1
  170. package/dist/metacognition/__tests__/evolution-engine.test.js +0 -473
  171. package/dist/metacognition/__tests__/evolution-engine.test.js.map +0 -1
  172. package/dist/metacognition/__tests__/parameter-registry.test.d.ts +0 -1
  173. package/dist/metacognition/__tests__/parameter-registry.test.js +0 -223
  174. package/dist/metacognition/__tests__/parameter-registry.test.js.map +0 -1
  175. package/dist/missions/__tests__/mission-engine.test.d.ts +0 -1
  176. package/dist/missions/__tests__/mission-engine.test.js +0 -67
  177. package/dist/missions/__tests__/mission-engine.test.js.map +0 -1
  178. package/dist/notifications/__tests__/notification-service.test.d.ts +0 -1
  179. package/dist/notifications/__tests__/notification-service.test.js +0 -176
  180. package/dist/notifications/__tests__/notification-service.test.js.map +0 -1
  181. package/dist/plugin/__tests__/plugin-registry.test.d.ts +0 -1
  182. package/dist/plugin/__tests__/plugin-registry.test.js +0 -166
  183. package/dist/plugin/__tests__/plugin-registry.test.js.map +0 -1
  184. package/dist/prediction/__tests__/prediction-engine.test.d.ts +0 -1
  185. package/dist/prediction/__tests__/prediction-engine.test.js +0 -252
  186. package/dist/prediction/__tests__/prediction-engine.test.js.map +0 -1
  187. package/dist/proactive/__tests__/proactive-engine.test.d.ts +0 -1
  188. package/dist/proactive/__tests__/proactive-engine.test.js +0 -183
  189. package/dist/proactive/__tests__/proactive-engine.test.js.map +0 -1
  190. package/dist/rag/__tests__/rag-engine.test.d.ts +0 -1
  191. package/dist/rag/__tests__/rag-engine.test.js +0 -235
  192. package/dist/rag/__tests__/rag-engine.test.js.map +0 -1
  193. package/dist/research/__tests__/autonomy-features.test.d.ts +0 -1
  194. package/dist/research/__tests__/autonomy-features.test.js +0 -155
  195. package/dist/research/__tests__/autonomy-features.test.js.map +0 -1
  196. package/dist/research/__tests__/base-engine.test.d.ts +0 -1
  197. package/dist/research/__tests__/base-engine.test.js +0 -56
  198. package/dist/research/__tests__/base-engine.test.js.map +0 -1
  199. package/dist/research/__tests__/semantic-compressor.test.d.ts +0 -1
  200. package/dist/research/__tests__/semantic-compressor.test.js +0 -153
  201. package/dist/research/__tests__/semantic-compressor.test.js.map +0 -1
  202. package/dist/research/adapters/__tests__/playwright-adapter.test.d.ts +0 -1
  203. package/dist/research/adapters/__tests__/playwright-adapter.test.js +0 -64
  204. package/dist/research/adapters/__tests__/playwright-adapter.test.js.map +0 -1
  205. package/dist/research/adapters/__tests__/web-adapters.test.d.ts +0 -1
  206. package/dist/research/adapters/__tests__/web-adapters.test.js +0 -106
  207. package/dist/research/adapters/__tests__/web-adapters.test.js.map +0 -1
  208. package/dist/sandbox/__tests__/code-sandbox.test.d.ts +0 -1
  209. package/dist/sandbox/__tests__/code-sandbox.test.js +0 -182
  210. package/dist/sandbox/__tests__/code-sandbox.test.js.map +0 -1
  211. package/dist/scanner/__tests__/signal-scanner.test.d.ts +0 -1
  212. package/dist/scanner/__tests__/signal-scanner.test.js +0 -142
  213. package/dist/scanner/__tests__/signal-scanner.test.js.map +0 -1
  214. package/dist/self-modification/__tests__/self-modification-engine.test.d.ts +0 -1
  215. package/dist/self-modification/__tests__/self-modification-engine.test.js +0 -313
  216. package/dist/self-modification/__tests__/self-modification-engine.test.js.map +0 -1
  217. package/dist/strategy/__tests__/strategy-forge.test.d.ts +0 -1
  218. package/dist/strategy/__tests__/strategy-forge.test.js +0 -190
  219. package/dist/strategy/__tests__/strategy-forge.test.js.map +0 -1
  220. package/dist/strategy/__tests__/strategy-mutator.test.d.ts +0 -1
  221. package/dist/strategy/__tests__/strategy-mutator.test.js +0 -141
  222. package/dist/strategy/__tests__/strategy-mutator.test.js.map +0 -1
  223. package/dist/synapses/__tests__/activation.test.d.ts +0 -1
  224. package/dist/synapses/__tests__/activation.test.js +0 -87
  225. package/dist/synapses/__tests__/activation.test.js.map +0 -1
  226. package/dist/synapses/__tests__/decay.test.d.ts +0 -1
  227. package/dist/synapses/__tests__/decay.test.js +0 -73
  228. package/dist/synapses/__tests__/decay.test.js.map +0 -1
  229. package/dist/synapses/__tests__/hebbian.test.d.ts +0 -1
  230. package/dist/synapses/__tests__/hebbian.test.js +0 -95
  231. package/dist/synapses/__tests__/hebbian.test.js.map +0 -1
  232. package/dist/synapses/__tests__/pathfinder.test.d.ts +0 -1
  233. package/dist/synapses/__tests__/pathfinder.test.js +0 -74
  234. package/dist/synapses/__tests__/pathfinder.test.js.map +0 -1
  235. package/dist/synapses/__tests__/synapse-manager.test.d.ts +0 -1
  236. package/dist/synapses/__tests__/synapse-manager.test.js +0 -94
  237. package/dist/synapses/__tests__/synapse-manager.test.js.map +0 -1
  238. package/dist/teaching/__tests__/teaching.test.d.ts +0 -1
  239. package/dist/teaching/__tests__/teaching.test.js +0 -252
  240. package/dist/teaching/__tests__/teaching.test.js.map +0 -1
  241. package/dist/techradar/__tests__/techradar-engine.test.d.ts +0 -1
  242. package/dist/techradar/__tests__/techradar-engine.test.js +0 -246
  243. package/dist/techradar/__tests__/techradar-engine.test.js.map +0 -1
  244. package/dist/tool-learning/__tests__/tool-learning.test.d.ts +0 -1
  245. package/dist/tool-learning/__tests__/tool-learning.test.js +0 -187
  246. package/dist/tool-learning/__tests__/tool-learning.test.js.map +0 -1
  247. package/dist/user-model/__tests__/user-model.test.d.ts +0 -1
  248. package/dist/user-model/__tests__/user-model.test.js +0 -142
  249. package/dist/user-model/__tests__/user-model.test.js.map +0 -1
  250. package/dist/utils/__tests__/batch-queue.test.d.ts +0 -1
  251. package/dist/utils/__tests__/batch-queue.test.js +0 -85
  252. package/dist/utils/__tests__/batch-queue.test.js.map +0 -1
  253. package/dist/utils/__tests__/events.test.d.ts +0 -1
  254. package/dist/utils/__tests__/events.test.js +0 -38
  255. package/dist/utils/__tests__/events.test.js.map +0 -1
  256. package/dist/utils/__tests__/hash.test.d.ts +0 -1
  257. package/dist/utils/__tests__/hash.test.js +0 -25
  258. package/dist/utils/__tests__/hash.test.js.map +0 -1
  259. package/dist/utils/__tests__/logger.test.d.ts +0 -1
  260. package/dist/utils/__tests__/logger.test.js +0 -55
  261. package/dist/utils/__tests__/logger.test.js.map +0 -1
  262. package/dist/utils/__tests__/paths.test.d.ts +0 -1
  263. package/dist/utils/__tests__/paths.test.js +0 -50
  264. package/dist/utils/__tests__/paths.test.js.map +0 -1
  265. package/dist/utils/__tests__/retry.test.d.ts +0 -1
  266. package/dist/utils/__tests__/retry.test.js +0 -91
  267. package/dist/utils/__tests__/retry.test.js.map +0 -1
  268. package/dist/watchdog/__tests__/watchdog-service.test.d.ts +0 -1
  269. package/dist/watchdog/__tests__/watchdog-service.test.js +0 -113
  270. package/dist/watchdog/__tests__/watchdog-service.test.js.map +0 -1
@@ -1,166 +0,0 @@
1
- import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
2
- import fs from 'node:fs';
3
- import path from 'node:path';
4
- import os from 'node:os';
5
- import { PluginRegistry } from '../plugin-registry.js';
6
- function createMockContext(name) {
7
- return {
8
- dataDir: path.join(os.tmpdir(), 'brain-test-plugins', name),
9
- log: {
10
- info: vi.fn(),
11
- warn: vi.fn(),
12
- error: vi.fn(),
13
- debug: vi.fn(),
14
- },
15
- callBrain: vi.fn().mockResolvedValue({}),
16
- notify: vi.fn().mockResolvedValue(undefined),
17
- };
18
- }
19
- describe('PluginRegistry', () => {
20
- let tmpDir;
21
- let registry;
22
- beforeEach(() => {
23
- tmpDir = path.join(os.tmpdir(), `brain-plugin-test-${Date.now()}`);
24
- fs.mkdirSync(tmpDir, { recursive: true });
25
- registry = new PluginRegistry(tmpDir);
26
- });
27
- afterEach(() => {
28
- fs.rmSync(tmpDir, { recursive: true, force: true });
29
- });
30
- it('creates plugin directory if it does not exist', () => {
31
- const newDir = path.join(tmpDir, 'subdir');
32
- const reg = new PluginRegistry(newDir);
33
- expect(fs.existsSync(newDir)).toBe(true);
34
- });
35
- it('starts with no plugins', () => {
36
- expect(registry.size).toBe(0);
37
- expect(registry.list()).toEqual([]);
38
- expect(registry.getRoutes()).toEqual([]);
39
- expect(registry.getTools()).toEqual([]);
40
- });
41
- it('has() returns false for unknown plugin', () => {
42
- expect(registry.has('nonexistent')).toBe(false);
43
- });
44
- it('get() returns null for unknown plugin', () => {
45
- expect(registry.get('nonexistent')).toBeNull();
46
- });
47
- it('loadAll with empty directory loads nothing', async () => {
48
- await registry.loadAll((name) => createMockContext(name));
49
- expect(registry.size).toBe(0);
50
- });
51
- it('loadAll skips directories without package.json', async () => {
52
- fs.mkdirSync(path.join(tmpDir, 'empty-dir'));
53
- await registry.loadAll((name) => createMockContext(name));
54
- expect(registry.size).toBe(0);
55
- });
56
- it('loadAll skips packages without brainPlugin flag', async () => {
57
- const pluginDir = path.join(tmpDir, 'normal-pkg');
58
- fs.mkdirSync(pluginDir);
59
- fs.writeFileSync(path.join(pluginDir, 'package.json'), JSON.stringify({
60
- name: 'normal-pkg',
61
- version: '1.0.0',
62
- }));
63
- fs.writeFileSync(path.join(pluginDir, 'index.js'), 'module.exports = {}');
64
- await registry.loadAll((name) => createMockContext(name));
65
- expect(registry.size).toBe(0);
66
- });
67
- it('unloadPlugin returns false for unknown plugin', async () => {
68
- expect(await registry.unloadPlugin('nonexistent')).toBe(false);
69
- });
70
- it('runCycle does nothing with no plugins', async () => {
71
- await expect(registry.runCycle(1)).resolves.toBeUndefined();
72
- });
73
- it('list returns empty array when no plugins loaded', () => {
74
- expect(registry.list()).toEqual([]);
75
- });
76
- it('getRoutes returns plugin-prefixed routes', () => {
77
- // Manually inject a plugin for testing
78
- const plugin = {
79
- name: 'test-plugin',
80
- version: '1.0.0',
81
- routes: [
82
- { method: 'test.hello', handler: () => ({ hello: 'world' }) },
83
- ],
84
- };
85
- // Access internal map (testing only)
86
- registry.plugins.set('test-plugin', {
87
- plugin,
88
- path: '/fake',
89
- loadedAt: new Date().toISOString(),
90
- error: null,
91
- });
92
- const routes = registry.getRoutes();
93
- expect(routes).toHaveLength(1);
94
- expect(routes[0].plugin).toBe('test-plugin');
95
- expect(routes[0].method).toBe('test.hello');
96
- });
97
- it('getTools returns plugin-prefixed tools', () => {
98
- const plugin = {
99
- name: 'test-plugin',
100
- version: '1.0.0',
101
- tools: [
102
- { name: 'test_tool', description: 'A test', schema: {}, handler: () => 'ok' },
103
- ],
104
- };
105
- registry.plugins.set('test-plugin', {
106
- plugin,
107
- path: '/fake',
108
- loadedAt: new Date().toISOString(),
109
- error: null,
110
- });
111
- const tools = registry.getTools();
112
- expect(tools).toHaveLength(1);
113
- expect(tools[0].plugin).toBe('test-plugin');
114
- expect(tools[0].name).toBe('test_tool');
115
- });
116
- it('runCycle calls onCycle for loaded plugins', async () => {
117
- const onCycle = vi.fn();
118
- const plugin = {
119
- name: 'cycle-plugin',
120
- version: '1.0.0',
121
- onCycle,
122
- };
123
- registry.plugins.set('cycle-plugin', {
124
- plugin,
125
- path: '/fake',
126
- loadedAt: new Date().toISOString(),
127
- error: null,
128
- });
129
- await registry.runCycle(42);
130
- expect(onCycle).toHaveBeenCalledWith(42);
131
- });
132
- it('runCycle catches errors from plugins', async () => {
133
- const plugin = {
134
- name: 'bad-plugin',
135
- version: '1.0.0',
136
- onCycle: () => { throw new Error('boom'); },
137
- };
138
- registry.plugins.set('bad-plugin', {
139
- plugin,
140
- path: '/fake',
141
- loadedAt: new Date().toISOString(),
142
- error: null,
143
- });
144
- // Should not throw
145
- await expect(registry.runCycle(1)).resolves.toBeUndefined();
146
- });
147
- it('unloadPlugin calls onUnload and removes', async () => {
148
- const onUnload = vi.fn();
149
- const plugin = {
150
- name: 'unload-test',
151
- version: '1.0.0',
152
- onUnload,
153
- };
154
- registry.plugins.set('unload-test', {
155
- plugin,
156
- path: '/fake',
157
- loadedAt: new Date().toISOString(),
158
- error: null,
159
- });
160
- expect(registry.has('unload-test')).toBe(true);
161
- await registry.unloadPlugin('unload-test');
162
- expect(registry.has('unload-test')).toBe(false);
163
- expect(onUnload).toHaveBeenCalled();
164
- });
165
- });
166
- //# sourceMappingURL=plugin-registry.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"plugin-registry.test.js","sourceRoot":"","sources":["../../../src/plugin/__tests__/plugin-registry.test.ts"],"names":[],"mappings":"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"}
@@ -1 +0,0 @@
1
- export {};
@@ -1,252 +0,0 @@
1
- import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
2
- import Database from 'better-sqlite3';
3
- vi.mock('../../utils/logger.js', () => ({
4
- getLogger: () => ({
5
- info: vi.fn(),
6
- warn: vi.fn(),
7
- error: vi.fn(),
8
- debug: vi.fn(),
9
- }),
10
- }));
11
- import { PredictionEngine, runPredictionMigration } from '../prediction-engine.js';
12
- // ── Helpers ───────────────────────────────────────────────
13
- /** Seed ascending metric data to produce a predictable upward trend. */
14
- function seedMetrics(db, metric, count, options) {
15
- const baseValue = options?.baseValue ?? 10;
16
- const step = options?.step ?? 1;
17
- const domain = options?.domain ?? 'metric';
18
- const baseTime = options?.baseTime ?? Date.now() - count * 60_000;
19
- for (let i = 0; i < count; i++) {
20
- db.prepare('INSERT INTO prediction_metrics (metric, value, domain, timestamp) VALUES (?, ?, ?, ?)').run(metric, baseValue + i * step, domain, baseTime + i * 60_000);
21
- }
22
- }
23
- // ── Tests ─────────────────────────────────────────────────
24
- describe('runPredictionMigration', () => {
25
- let db;
26
- beforeEach(() => { db = new Database(':memory:'); });
27
- afterEach(() => { db.close(); });
28
- it('creates predictions, prediction_metrics, and prediction_state tables', () => {
29
- runPredictionMigration(db);
30
- const tables = db
31
- .prepare("SELECT name FROM sqlite_master WHERE type='table' ORDER BY name")
32
- .all();
33
- const names = tables.map(t => t.name);
34
- expect(names).toContain('predictions');
35
- expect(names).toContain('prediction_metrics');
36
- expect(names).toContain('prediction_state');
37
- });
38
- it('initialises prediction_state with a single row', () => {
39
- runPredictionMigration(db);
40
- const row = db.prepare('SELECT * FROM prediction_state WHERE id = 1').get();
41
- expect(row).toBeDefined();
42
- expect(row.total_predictions).toBe(0);
43
- expect(row.total_resolved).toBe(0);
44
- expect(row.total_correct).toBe(0);
45
- expect(row.calibration_offset).toBe(0);
46
- });
47
- it('is idempotent (running twice does not throw)', () => {
48
- runPredictionMigration(db);
49
- expect(() => runPredictionMigration(db)).not.toThrow();
50
- });
51
- });
52
- describe('PredictionEngine', () => {
53
- let db;
54
- let engine;
55
- beforeEach(() => {
56
- db = new Database(':memory:');
57
- runPredictionMigration(db);
58
- engine = new PredictionEngine(db, { brainName: 'test-brain', minConfidence: 0.01, minDataPoints: 5 });
59
- });
60
- afterEach(() => {
61
- engine.stop();
62
- db.close();
63
- });
64
- // ── Creation & Config ───────────────────────────────────
65
- it('creates an engine with default config values', () => {
66
- const cfg = engine.getConfig();
67
- expect(cfg.brainName).toBe('test-brain');
68
- expect(cfg.defaultHorizonMs).toBe(600_000);
69
- expect(cfg.expirationMs).toBe(3_600_000);
70
- expect(cfg.ewmaAlpha).toBe(0.3);
71
- expect(cfg.trendBeta).toBe(0.1);
72
- expect(cfg.minDataPoints).toBe(5);
73
- expect(cfg.minConfidence).toBe(0.01);
74
- expect(cfg.maxPredictionsPerCycle).toBe(5);
75
- expect(cfg.resolveIntervalMs).toBe(60_000);
76
- });
77
- it('updateConfig merges partial updates', () => {
78
- engine.updateConfig({ ewmaAlpha: 0.5, trendBeta: 0.2 });
79
- const cfg = engine.getConfig();
80
- expect(cfg.ewmaAlpha).toBe(0.5);
81
- expect(cfg.trendBeta).toBe(0.2);
82
- // unchanged fields remain
83
- expect(cfg.minDataPoints).toBe(5);
84
- });
85
- // ── recordMetric ────────────────────────────────────────
86
- it('recordMetric inserts data points into prediction_metrics', () => {
87
- engine.recordMetric('cpu_load', 42.5, 'metric');
88
- engine.recordMetric('cpu_load', 45.0, 'metric');
89
- engine.recordMetric('cpu_load', 47.2, 'metric');
90
- const rows = db.prepare('SELECT * FROM prediction_metrics WHERE metric = ?').all('cpu_load');
91
- expect(rows).toHaveLength(3);
92
- });
93
- // ── predict ─────────────────────────────────────────────
94
- it('predict returns null when insufficient data (< 2 points)', () => {
95
- engine.recordMetric('sparse', 10);
96
- const result = engine.predict({ domain: 'metric', metric: 'sparse' });
97
- expect(result).toBeNull();
98
- });
99
- it('predict returns a Prediction with EWMA when 2-4 data points exist', () => {
100
- seedMetrics(db, 'short_series', 3, { baseValue: 10, step: 5 });
101
- const prediction = engine.predict({ domain: 'metric', metric: 'short_series' });
102
- expect(prediction).not.toBeNull();
103
- expect(prediction.method).toBe('ewma');
104
- expect(prediction.status).toBe('pending');
105
- expect(prediction.domain).toBe('metric');
106
- expect(prediction.metric).toBe('short_series');
107
- expect(prediction.prediction_id).toBeTruthy();
108
- expect(prediction.confidence).toBeGreaterThan(0);
109
- expect(prediction.horizon_ms).toBe(600_000);
110
- });
111
- it('predict returns a Prediction with holt_winters when >= minDataPoints', () => {
112
- seedMetrics(db, 'long_series', 10, { baseValue: 100, step: 2 });
113
- const prediction = engine.predict({ domain: 'trade', metric: 'long_series' });
114
- expect(prediction).not.toBeNull();
115
- expect(prediction.method).toBe('holt_winters');
116
- expect(prediction.predicted_direction).toBe('up');
117
- expect(prediction.evidence).toHaveProperty('dataPoints', 10);
118
- expect(prediction.evidence).toHaveProperty('trend');
119
- });
120
- it('predict increments total_predictions in prediction_state', () => {
121
- seedMetrics(db, 'counter_test', 3, { baseValue: 10, step: 1 });
122
- engine.predict({ domain: 'metric', metric: 'counter_test' });
123
- engine.predict({ domain: 'metric', metric: 'counter_test' });
124
- const state = db.prepare('SELECT total_predictions FROM prediction_state WHERE id = 1').get();
125
- expect(state.total_predictions).toBe(2);
126
- });
127
- // ── forecast ────────────────────────────────────────────
128
- it('forecast uses EWMA for small datasets and holt_winters for large', () => {
129
- const shortResult = engine.forecast([10, 20, 30], 60_000);
130
- expect(shortResult.method).toBe('ewma');
131
- expect(shortResult.dataPoints).toBe(3);
132
- const longResult = engine.forecast([10, 20, 30, 40, 50, 60, 70], 60_000);
133
- expect(longResult.method).toBe('holt_winters');
134
- expect(longResult.dataPoints).toBe(7);
135
- expect(longResult.direction).toBe('up');
136
- });
137
- // ── list ────────────────────────────────────────────────
138
- it('list returns stored predictions, optionally filtered by domain/status', () => {
139
- seedMetrics(db, 'm1', 3, { baseValue: 10, step: 1, domain: 'error' });
140
- seedMetrics(db, 'm2', 3, { baseValue: 50, step: 5, domain: 'trade' });
141
- engine.predict({ domain: 'error', metric: 'm1' });
142
- engine.predict({ domain: 'trade', metric: 'm2' });
143
- const all = engine.list();
144
- expect(all).toHaveLength(2);
145
- const errorOnly = engine.list('error');
146
- expect(errorOnly).toHaveLength(1);
147
- expect(errorOnly[0].domain).toBe('error');
148
- const pendingOnly = engine.list(undefined, 'pending');
149
- expect(pendingOnly).toHaveLength(2);
150
- });
151
- // ── getAccuracy ─────────────────────────────────────────
152
- it('getAccuracy returns per-domain accuracy stats after resolution', () => {
153
- // Insert a prediction directly, then resolve it via the tracker
154
- seedMetrics(db, 'acc_metric', 5, { baseValue: 100, step: 1 });
155
- const pred = engine.predict({ domain: 'error', metric: 'acc_metric' });
156
- expect(pred).not.toBeNull();
157
- // Manually resolve: set status to 'correct' in DB
158
- db.prepare("UPDATE predictions SET status = 'correct', actual_value = ?, error = 0.01 WHERE prediction_id = ?")
159
- .run(pred.predicted_value, pred.prediction_id);
160
- const accuracy = engine.getAccuracy('error');
161
- expect(accuracy).toHaveLength(1);
162
- expect(accuracy[0].domain).toBe('error');
163
- expect(accuracy[0].correct).toBe(1);
164
- expect(accuracy[0].accuracy_rate).toBe(1);
165
- });
166
- // ── getSummary ──────────────────────────────────────────
167
- it('getSummary returns a full summary with totals and recent predictions', () => {
168
- seedMetrics(db, 'sum_m', 4, { baseValue: 5, step: 2 });
169
- engine.predict({ domain: 'metric', metric: 'sum_m' });
170
- const summary = engine.getSummary();
171
- expect(summary.total_predictions).toBe(1);
172
- expect(summary.pending).toBe(1);
173
- expect(summary.resolved).toBe(0);
174
- expect(summary.accuracy_rate).toBe(0);
175
- expect(summary.calibration_offset).toBe(0);
176
- expect(summary.recent).toHaveLength(1);
177
- expect(summary.by_domain).toEqual([]);
178
- });
179
- // ── resolveExpired ──────────────────────────────────────
180
- it('resolveExpired marks predictions past expires_at as expired', () => {
181
- seedMetrics(db, 'exp_m', 3, { baseValue: 10, step: 1 });
182
- const pred = engine.predict({ domain: 'metric', metric: 'exp_m' });
183
- expect(pred).not.toBeNull();
184
- // Force the prediction to be expired by setting expires_at to the past
185
- const past = Date.now() - 10_000;
186
- db.prepare('UPDATE predictions SET expires_at = ? WHERE prediction_id = ?')
187
- .run(past, pred.prediction_id);
188
- const resolved = engine.resolveExpired();
189
- expect(resolved).toBeGreaterThanOrEqual(1);
190
- const updated = engine.list(undefined, 'expired');
191
- expect(updated).toHaveLength(1);
192
- expect(updated[0].prediction_id).toBe(pred.prediction_id);
193
- });
194
- it('resolveExpired resolves predictions past their horizon against actual data', () => {
195
- seedMetrics(db, 'res_m', 4, { baseValue: 50, step: 2 });
196
- const pred = engine.predict({ domain: 'metric', metric: 'res_m' });
197
- expect(pred).not.toBeNull();
198
- // Make the prediction resolvable: created_at + horizon_ms <= now AND expires_at >= now
199
- const now = Date.now();
200
- db.prepare('UPDATE predictions SET created_at = ?, expires_at = ? WHERE prediction_id = ?')
201
- .run(now - pred.horizon_ms - 1000, now + 100_000, pred.prediction_id);
202
- // Insert post-prediction metric values (timestamp > created_at)
203
- const predCreatedAt = now - pred.horizon_ms - 1000;
204
- for (let i = 0; i < 5; i++) {
205
- db.prepare('INSERT INTO prediction_metrics (metric, value, domain, timestamp) VALUES (?, ?, ?, ?)')
206
- .run('res_m', pred.predicted_value + i * 0.1, 'metric', predCreatedAt + 1000 + i * 1000);
207
- }
208
- const resolved = engine.resolveExpired();
209
- expect(resolved).toBeGreaterThanOrEqual(1);
210
- // The prediction should no longer be 'pending'
211
- const pending = engine.list(undefined, 'pending');
212
- const resolvedPred = pending.find(p => p.prediction_id === pred.prediction_id);
213
- expect(resolvedPred).toBeUndefined();
214
- });
215
- // ── getMetricHistory ────────────────────────────────────
216
- it('getMetricHistory returns data points in ascending timestamp order', () => {
217
- engine.recordMetric('hist_m', 10);
218
- engine.recordMetric('hist_m', 20);
219
- engine.recordMetric('hist_m', 30);
220
- const history = engine.getMetricHistory('hist_m', 10);
221
- expect(history).toHaveLength(3);
222
- expect(history[0].value).toBe(10);
223
- expect(history[2].value).toBe(30);
224
- expect(history[0].timestamp).toBeLessThanOrEqual(history[1].timestamp);
225
- expect(history[1].timestamp).toBeLessThanOrEqual(history[2].timestamp);
226
- });
227
- it('getMetricHistory respects the limit parameter', () => {
228
- for (let i = 0; i < 20; i++) {
229
- engine.recordMetric('limited_m', i);
230
- }
231
- const limited = engine.getMetricHistory('limited_m', 5);
232
- expect(limited).toHaveLength(5);
233
- });
234
- // ── start / stop ────────────────────────────────────────
235
- it('start and stop manage the resolution timer without error', () => {
236
- expect(() => engine.start()).not.toThrow();
237
- // calling start again is a no-op
238
- expect(() => engine.start()).not.toThrow();
239
- expect(() => engine.stop()).not.toThrow();
240
- // stopping again is safe
241
- expect(() => engine.stop()).not.toThrow();
242
- });
243
- // ── getCalibration ─────────────────────────────────────
244
- it('getCalibration returns offset and accuracy by domain', () => {
245
- const calibration = engine.getCalibration();
246
- expect(calibration).toHaveProperty('offset');
247
- expect(calibration).toHaveProperty('accuracyByDomain');
248
- expect(typeof calibration.offset).toBe('number');
249
- expect(Array.isArray(calibration.accuracyByDomain)).toBe(true);
250
- });
251
- });
252
- //# sourceMappingURL=prediction-engine.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"prediction-engine.test.js","sourceRoot":"","sources":["../../../src/prediction/__tests__/prediction-engine.test.ts"],"names":[],"mappings":"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"}
@@ -1 +0,0 @@
1
- export {};
@@ -1,183 +0,0 @@
1
- import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
2
- import Database from 'better-sqlite3';
3
- vi.mock('../../utils/logger.js', () => ({
4
- getLogger: () => ({
5
- info: vi.fn(), warn: vi.fn(), error: vi.fn(), debug: vi.fn(),
6
- }),
7
- }));
8
- import { ProactiveEngine, runProactiveMigration } from '../proactive-engine.js';
9
- function createDb() {
10
- return new Database(':memory:');
11
- }
12
- describe('ProactiveEngine', () => {
13
- let db;
14
- beforeEach(() => {
15
- db = createDb();
16
- });
17
- afterEach(() => {
18
- db.close();
19
- });
20
- it('creates a suggestion and retrieves it', () => {
21
- const engine = new ProactiveEngine(db, { brainName: 'test' });
22
- const ok = engine.createSuggestion('info', 'Test Suggestion', 'A description', 'Do something', 0.7);
23
- expect(ok).toBe(true);
24
- const suggestions = engine.getSuggestions();
25
- expect(suggestions).toHaveLength(1);
26
- expect(suggestions[0].title).toBe('Test Suggestion');
27
- expect(suggestions[0].priority).toBe(0.7);
28
- expect(suggestions[0].type).toBe('info');
29
- });
30
- it('returns suggestions sorted by priority descending', () => {
31
- const engine = new ProactiveEngine(db, { brainName: 'test' });
32
- engine.createSuggestion('low', 'Low Priority', undefined, undefined, 0.2);
33
- engine.createSuggestion('high', 'High Priority', undefined, undefined, 0.9);
34
- engine.createSuggestion('mid', 'Mid Priority', undefined, undefined, 0.5);
35
- const suggestions = engine.getSuggestions();
36
- expect(suggestions).toHaveLength(3);
37
- expect(suggestions[0].title).toBe('High Priority');
38
- expect(suggestions[1].title).toBe('Mid Priority');
39
- expect(suggestions[2].title).toBe('Low Priority');
40
- });
41
- it('dismisses a suggestion', () => {
42
- const engine = new ProactiveEngine(db, { brainName: 'test' });
43
- engine.createSuggestion('info', 'To Dismiss', 'desc');
44
- const before = engine.getSuggestions();
45
- expect(before).toHaveLength(1);
46
- engine.dismiss(before[0].id);
47
- const after = engine.getSuggestions();
48
- expect(after).toHaveLength(0);
49
- });
50
- it('respects rate limiting (max per hour)', () => {
51
- const engine = new ProactiveEngine(db, {
52
- brainName: 'test',
53
- maxSuggestionsPerHour: 2,
54
- });
55
- expect(engine.createSuggestion('a', 'First')).toBe(true);
56
- expect(engine.createSuggestion('b', 'Second')).toBe(true);
57
- expect(engine.createSuggestion('c', 'Third')).toBe(false); // Rate limited
58
- });
59
- it('checks recurring errors trigger', () => {
60
- const engine = new ProactiveEngine(db, {
61
- brainName: 'test',
62
- recurringThreshold: 3,
63
- });
64
- // Create error_memory table and populate
65
- db.exec(`
66
- CREATE TABLE error_memory (
67
- id INTEGER PRIMARY KEY,
68
- fingerprint TEXT NOT NULL,
69
- message TEXT NOT NULL
70
- )
71
- `);
72
- // Insert 3 errors with same fingerprint
73
- const insert = db.prepare('INSERT INTO error_memory (fingerprint, message) VALUES (?, ?)');
74
- insert.run('null-ref-001', 'Cannot read property of null');
75
- insert.run('null-ref-001', 'Cannot read property of null');
76
- insert.run('null-ref-001', 'Cannot read property of null');
77
- const created = engine.analyze({ db });
78
- expect(created).toBeGreaterThanOrEqual(1);
79
- const suggestions = engine.getSuggestions();
80
- const errorSuggestion = suggestions.find(s => s.type === 'recurring_error');
81
- expect(errorSuggestion).toBeDefined();
82
- expect(errorSuggestion.title).toContain('null-ref-001');
83
- });
84
- it('checks stale knowledge trigger', () => {
85
- const engine = new ProactiveEngine(db, {
86
- brainName: 'test',
87
- staleDays: 30,
88
- });
89
- // Create insights table with old high-confidence insight
90
- db.exec(`
91
- CREATE TABLE insights (
92
- id INTEGER PRIMARY KEY,
93
- topic TEXT NOT NULL,
94
- created_at TEXT NOT NULL,
95
- confidence REAL NOT NULL
96
- )
97
- `);
98
- db.prepare(`
99
- INSERT INTO insights (topic, created_at, confidence)
100
- VALUES (?, datetime('now', '-60 days'), 0.9)
101
- `).run('old-topic');
102
- const created = engine.analyze({ db });
103
- expect(created).toBeGreaterThanOrEqual(1);
104
- const suggestions = engine.getSuggestions();
105
- const staleSuggestion = suggestions.find(s => s.type === 'stale_knowledge');
106
- expect(staleSuggestion).toBeDefined();
107
- expect(staleSuggestion.title).toContain('old-topic');
108
- });
109
- it('getStatus returns correct counts', () => {
110
- const engine = new ProactiveEngine(db, { brainName: 'test' });
111
- engine.createSuggestion('a', 'Active 1');
112
- engine.createSuggestion('b', 'Active 2');
113
- const suggestions = engine.getSuggestions();
114
- engine.dismiss(suggestions[0].id);
115
- const status = engine.getStatus();
116
- expect(status.totalSuggestions).toBe(2);
117
- expect(status.activeSuggestions).toBe(1);
118
- expect(status.dismissedCount).toBe(1);
119
- expect(status.lastAnalysis).toBeNull(); // No analyze() called
120
- });
121
- it('migration is idempotent', () => {
122
- const engine1 = new ProactiveEngine(db, { brainName: 'test' });
123
- engine1.createSuggestion('test', 'Survives Migration');
124
- // Run migration again
125
- runProactiveMigration(db);
126
- const engine2 = new ProactiveEngine(db, { brainName: 'test' });
127
- const suggestions = engine2.getSuggestions();
128
- expect(suggestions).toHaveLength(1);
129
- expect(suggestions[0].title).toBe('Survives Migration');
130
- });
131
- it('returns zero suggestions from empty analysis', () => {
132
- const engine = new ProactiveEngine(db, { brainName: 'test' });
133
- // No error_memory, insights, or tool_usage tables exist
134
- const created = engine.analyze({ db });
135
- expect(created).toBe(0);
136
- });
137
- it('dismissed suggestions not returned by default', () => {
138
- const engine = new ProactiveEngine(db, { brainName: 'test' });
139
- engine.createSuggestion('a', 'Visible');
140
- engine.createSuggestion('b', 'Hidden');
141
- const all = engine.getSuggestions();
142
- engine.dismiss(all.find(s => s.title === 'Hidden').id);
143
- const active = engine.getSuggestions();
144
- expect(active).toHaveLength(1);
145
- expect(active[0].title).toBe('Visible');
146
- const withDismissed = engine.getSuggestions(20, true);
147
- expect(withDismissed).toHaveLength(2);
148
- });
149
- it('deduplicates suggestions with same title', () => {
150
- const engine = new ProactiveEngine(db, { brainName: 'test' });
151
- expect(engine.createSuggestion('a', 'Same Title')).toBe(true);
152
- expect(engine.createSuggestion('b', 'Same Title')).toBe(false); // Duplicate
153
- const suggestions = engine.getSuggestions();
154
- expect(suggestions).toHaveLength(1);
155
- });
156
- it('checks quick wins trigger (tool_usage table)', () => {
157
- const engine = new ProactiveEngine(db, { brainName: 'test' });
158
- // Create tool_usage table
159
- db.exec(`
160
- CREATE TABLE IF NOT EXISTS tool_usage (
161
- id INTEGER PRIMARY KEY,
162
- tool_name TEXT NOT NULL,
163
- context TEXT,
164
- duration_ms INTEGER,
165
- outcome TEXT DEFAULT 'success',
166
- metadata TEXT,
167
- created_at TEXT DEFAULT (datetime('now'))
168
- )
169
- `);
170
- // Insert a tool with high success rate but low usage
171
- const insert = db.prepare('INSERT INTO tool_usage (tool_name, outcome) VALUES (?, ?)');
172
- insert.run('rare-but-good', 'success');
173
- insert.run('rare-but-good', 'success');
174
- insert.run('rare-but-good', 'success');
175
- const created = engine.analyze({ db });
176
- expect(created).toBeGreaterThanOrEqual(1);
177
- const suggestions = engine.getSuggestions();
178
- const quickWin = suggestions.find(s => s.type === 'quick_win');
179
- expect(quickWin).toBeDefined();
180
- expect(quickWin.title).toContain('rare-but-good');
181
- });
182
- });
183
- //# sourceMappingURL=proactive-engine.test.js.map