@timmeck/brain-core 2.36.23 → 2.36.25

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 (119) hide show
  1. package/command-center.html +259 -153
  2. package/dist/active-learning/__tests__/active-learning.test.d.ts +1 -0
  3. package/dist/active-learning/__tests__/active-learning.test.js +132 -0
  4. package/dist/active-learning/__tests__/active-learning.test.js.map +1 -0
  5. package/dist/active-learning/active-learner.d.ts +79 -0
  6. package/dist/active-learning/active-learner.js +224 -0
  7. package/dist/active-learning/active-learner.js.map +1 -0
  8. package/dist/active-learning/index.d.ts +2 -0
  9. package/dist/active-learning/index.js +2 -0
  10. package/dist/active-learning/index.js.map +1 -0
  11. package/dist/code-health/__tests__/code-health.test.d.ts +1 -0
  12. package/dist/code-health/__tests__/code-health.test.js +123 -0
  13. package/dist/code-health/__tests__/code-health.test.js.map +1 -0
  14. package/dist/code-health/health-monitor.d.ts +55 -0
  15. package/dist/code-health/health-monitor.js +180 -0
  16. package/dist/code-health/health-monitor.js.map +1 -0
  17. package/dist/code-health/index.d.ts +2 -0
  18. package/dist/code-health/index.js +2 -0
  19. package/dist/code-health/index.js.map +1 -0
  20. package/dist/consensus/__tests__/consensus.test.d.ts +1 -0
  21. package/dist/consensus/__tests__/consensus.test.js +159 -0
  22. package/dist/consensus/__tests__/consensus.test.js.map +1 -0
  23. package/dist/consensus/consensus-engine.d.ts +81 -0
  24. package/dist/consensus/consensus-engine.js +237 -0
  25. package/dist/consensus/consensus-engine.js.map +1 -0
  26. package/dist/consensus/index.d.ts +2 -0
  27. package/dist/consensus/index.js +2 -0
  28. package/dist/consensus/index.js.map +1 -0
  29. package/dist/feedback/__tests__/feedback-engine.test.d.ts +1 -0
  30. package/dist/feedback/__tests__/feedback-engine.test.js +156 -0
  31. package/dist/feedback/__tests__/feedback-engine.test.js.map +1 -0
  32. package/dist/feedback/feedback-engine.d.ts +61 -0
  33. package/dist/feedback/feedback-engine.js +203 -0
  34. package/dist/feedback/feedback-engine.js.map +1 -0
  35. package/dist/feedback/index.d.ts +2 -0
  36. package/dist/feedback/index.js +2 -0
  37. package/dist/feedback/index.js.map +1 -0
  38. package/dist/index.d.ts +32 -0
  39. package/dist/index.js +27 -0
  40. package/dist/index.js.map +1 -1
  41. package/dist/knowledge-graph/__tests__/knowledge-graph.test.d.ts +1 -0
  42. package/dist/knowledge-graph/__tests__/knowledge-graph.test.js +215 -0
  43. package/dist/knowledge-graph/__tests__/knowledge-graph.test.js.map +1 -0
  44. package/dist/knowledge-graph/fact-extractor.d.ts +23 -0
  45. package/dist/knowledge-graph/fact-extractor.js +70 -0
  46. package/dist/knowledge-graph/fact-extractor.js.map +1 -0
  47. package/dist/knowledge-graph/graph-engine.d.ts +78 -0
  48. package/dist/knowledge-graph/graph-engine.js +276 -0
  49. package/dist/knowledge-graph/graph-engine.js.map +1 -0
  50. package/dist/knowledge-graph/index.d.ts +4 -0
  51. package/dist/knowledge-graph/index.js +3 -0
  52. package/dist/knowledge-graph/index.js.map +1 -0
  53. package/dist/proactive/__tests__/proactive-engine.test.d.ts +1 -0
  54. package/dist/proactive/__tests__/proactive-engine.test.js +183 -0
  55. package/dist/proactive/__tests__/proactive-engine.test.js.map +1 -0
  56. package/dist/proactive/index.d.ts +2 -0
  57. package/dist/proactive/index.js +2 -0
  58. package/dist/proactive/index.js.map +1 -0
  59. package/dist/proactive/proactive-engine.d.ts +86 -0
  60. package/dist/proactive/proactive-engine.js +252 -0
  61. package/dist/proactive/proactive-engine.js.map +1 -0
  62. package/dist/rag/__tests__/rag-engine.test.d.ts +1 -0
  63. package/dist/rag/__tests__/rag-engine.test.js +235 -0
  64. package/dist/rag/__tests__/rag-engine.test.js.map +1 -0
  65. package/dist/rag/index.d.ts +4 -0
  66. package/dist/rag/index.js +3 -0
  67. package/dist/rag/index.js.map +1 -0
  68. package/dist/rag/rag-engine.d.ts +98 -0
  69. package/dist/rag/rag-engine.js +310 -0
  70. package/dist/rag/rag-engine.js.map +1 -0
  71. package/dist/rag/rag-indexer.d.ts +52 -0
  72. package/dist/rag/rag-indexer.js +144 -0
  73. package/dist/rag/rag-indexer.js.map +1 -0
  74. package/dist/research/__tests__/autonomy-features.test.d.ts +1 -0
  75. package/dist/research/__tests__/autonomy-features.test.js +155 -0
  76. package/dist/research/__tests__/autonomy-features.test.js.map +1 -0
  77. package/dist/research/__tests__/semantic-compressor.test.d.ts +1 -0
  78. package/dist/research/__tests__/semantic-compressor.test.js +153 -0
  79. package/dist/research/__tests__/semantic-compressor.test.js.map +1 -0
  80. package/dist/research/semantic-compressor.d.ts +55 -0
  81. package/dist/research/semantic-compressor.js +227 -0
  82. package/dist/research/semantic-compressor.js.map +1 -0
  83. package/dist/teaching/__tests__/teaching.test.d.ts +1 -0
  84. package/dist/teaching/__tests__/teaching.test.js +151 -0
  85. package/dist/teaching/__tests__/teaching.test.js.map +1 -0
  86. package/dist/teaching/curriculum.d.ts +32 -0
  87. package/dist/teaching/curriculum.js +89 -0
  88. package/dist/teaching/curriculum.js.map +1 -0
  89. package/dist/teaching/index.d.ts +4 -0
  90. package/dist/teaching/index.js +3 -0
  91. package/dist/teaching/index.js.map +1 -0
  92. package/dist/teaching/teaching-protocol.d.ts +74 -0
  93. package/dist/teaching/teaching-protocol.js +164 -0
  94. package/dist/teaching/teaching-protocol.js.map +1 -0
  95. package/dist/tool-learning/__tests__/tool-learning.test.d.ts +1 -0
  96. package/dist/tool-learning/__tests__/tool-learning.test.js +187 -0
  97. package/dist/tool-learning/__tests__/tool-learning.test.js.map +1 -0
  98. package/dist/tool-learning/index.d.ts +4 -0
  99. package/dist/tool-learning/index.js +3 -0
  100. package/dist/tool-learning/index.js.map +1 -0
  101. package/dist/tool-learning/tool-patterns.d.ts +47 -0
  102. package/dist/tool-learning/tool-patterns.js +125 -0
  103. package/dist/tool-learning/tool-patterns.js.map +1 -0
  104. package/dist/tool-learning/tool-tracker.d.ts +58 -0
  105. package/dist/tool-learning/tool-tracker.js +135 -0
  106. package/dist/tool-learning/tool-tracker.js.map +1 -0
  107. package/dist/user-model/__tests__/user-model.test.d.ts +1 -0
  108. package/dist/user-model/__tests__/user-model.test.js +142 -0
  109. package/dist/user-model/__tests__/user-model.test.js.map +1 -0
  110. package/dist/user-model/adaptive-context.d.ts +18 -0
  111. package/dist/user-model/adaptive-context.js +46 -0
  112. package/dist/user-model/adaptive-context.js.map +1 -0
  113. package/dist/user-model/index.d.ts +4 -0
  114. package/dist/user-model/index.js +3 -0
  115. package/dist/user-model/index.js.map +1 -0
  116. package/dist/user-model/user-model.d.ts +53 -0
  117. package/dist/user-model/user-model.js +204 -0
  118. package/dist/user-model/user-model.js.map +1 -0
  119. package/package.json +1 -1
@@ -0,0 +1,187 @@
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 { ToolTracker, runToolTrackerMigration } from '../tool-tracker.js';
9
+ import { ToolPatternAnalyzer } from '../tool-patterns.js';
10
+ function createDb() {
11
+ return new Database(':memory:');
12
+ }
13
+ describe('ToolTracker', () => {
14
+ let db;
15
+ beforeEach(() => {
16
+ db = createDb();
17
+ });
18
+ afterEach(() => {
19
+ db.close();
20
+ });
21
+ it('records usage and retrieves it', () => {
22
+ const tracker = new ToolTracker(db, { brainName: 'test' });
23
+ tracker.recordUsage('mcp.search', 'searching docs', 150, 'success');
24
+ const stats = tracker.getToolStats('mcp.search');
25
+ expect(stats).toEqual(expect.objectContaining({
26
+ tool: 'mcp.search',
27
+ totalUses: 1,
28
+ successRate: 1,
29
+ }));
30
+ });
31
+ it('returns stats for a single tool', () => {
32
+ const tracker = new ToolTracker(db, { brainName: 'test' });
33
+ tracker.recordUsage('mcp.search', 'ctx', 100, 'success');
34
+ tracker.recordUsage('mcp.search', 'ctx', 200, 'failure');
35
+ const stats = tracker.getToolStats('mcp.search');
36
+ expect(stats).toEqual(expect.objectContaining({
37
+ tool: 'mcp.search',
38
+ totalUses: 2,
39
+ successRate: 0.5,
40
+ avgDuration: 150,
41
+ }));
42
+ });
43
+ it('returns stats for all tools', () => {
44
+ const tracker = new ToolTracker(db, { brainName: 'test' });
45
+ tracker.recordUsage('tool-a', 'ctx', 100, 'success');
46
+ tracker.recordUsage('tool-b', 'ctx', 200, 'success');
47
+ tracker.recordUsage('tool-a', 'ctx', 300, 'success');
48
+ const stats = tracker.getToolStats();
49
+ expect(Array.isArray(stats)).toBe(true);
50
+ expect(stats.length).toBe(2);
51
+ // tool-a should be first (more uses)
52
+ expect(stats[0].tool).toBe('tool-a');
53
+ });
54
+ it('recommends tools sorted by success rate * frequency', () => {
55
+ const tracker = new ToolTracker(db, { brainName: 'test' });
56
+ // tool-a: 3 successes in 'debug' context
57
+ tracker.recordUsage('tool-a', 'debug error', 100, 'success');
58
+ tracker.recordUsage('tool-a', 'debug crash', 100, 'success');
59
+ tracker.recordUsage('tool-a', 'debug log', 100, 'success');
60
+ // tool-b: 1 success in 'debug' context
61
+ tracker.recordUsage('tool-b', 'debug issue', 200, 'success');
62
+ // tool-c: no 'debug' context
63
+ tracker.recordUsage('tool-c', 'build project', 50, 'success');
64
+ const recs = tracker.recommend('debug');
65
+ expect(recs.length).toBeGreaterThanOrEqual(2);
66
+ expect(recs[0].tool).toBe('tool-a');
67
+ // tool-c should not appear (no debug context)
68
+ expect(recs.find(r => r.tool === 'tool-c')).toBeUndefined();
69
+ });
70
+ it('records usage with different outcomes', () => {
71
+ const tracker = new ToolTracker(db, { brainName: 'test' });
72
+ tracker.recordUsage('tool-x', 'ctx', 100, 'success');
73
+ tracker.recordUsage('tool-x', 'ctx', 100, 'failure');
74
+ tracker.recordUsage('tool-x', 'ctx', 100, 'partial');
75
+ const stats = tracker.getToolStats('tool-x');
76
+ expect(stats).toEqual(expect.objectContaining({
77
+ totalUses: 3,
78
+ }));
79
+ // 1 success out of 3 = 0.333...
80
+ expect(stats.successRate).toBeCloseTo(1 / 3, 5);
81
+ });
82
+ it('returns empty stats for unknown tool', () => {
83
+ const tracker = new ToolTracker(db, { brainName: 'test' });
84
+ const stats = tracker.getToolStats('nonexistent');
85
+ expect(stats).toEqual(expect.objectContaining({
86
+ tool: 'nonexistent',
87
+ totalUses: 0,
88
+ successRate: 0,
89
+ }));
90
+ });
91
+ it('getStatus returns correct counts', () => {
92
+ const tracker = new ToolTracker(db, { brainName: 'test' });
93
+ tracker.recordUsage('tool-a', null, null, 'success');
94
+ tracker.recordUsage('tool-b', null, null, 'failure');
95
+ tracker.recordUsage('tool-a', null, null, 'success');
96
+ const status = tracker.getStatus();
97
+ expect(status.totalTracked).toBe(3);
98
+ expect(status.uniqueTools).toBe(2);
99
+ // 2 successes out of 3
100
+ expect(status.avgSuccessRate).toBeCloseTo(2 / 3, 5);
101
+ });
102
+ it('migration is idempotent', () => {
103
+ const tracker1 = new ToolTracker(db, { brainName: 'test' });
104
+ tracker1.recordUsage('tool-a', 'ctx', 100, 'success');
105
+ // Run migration again — should not throw or lose data
106
+ runToolTrackerMigration(db);
107
+ const tracker2 = new ToolTracker(db, { brainName: 'test' });
108
+ const stats = tracker2.getToolStats('tool-a');
109
+ expect(stats).toEqual(expect.objectContaining({ totalUses: 1 }));
110
+ });
111
+ it('getStatus returns zeros when empty', () => {
112
+ const tracker = new ToolTracker(db, { brainName: 'test' });
113
+ const status = tracker.getStatus();
114
+ expect(status.totalTracked).toBe(0);
115
+ expect(status.uniqueTools).toBe(0);
116
+ expect(status.avgSuccessRate).toBe(0);
117
+ });
118
+ });
119
+ describe('ToolPatternAnalyzer', () => {
120
+ let db;
121
+ beforeEach(() => {
122
+ db = createDb();
123
+ // ToolTracker migration creates the table
124
+ runToolTrackerMigration(db);
125
+ });
126
+ afterEach(() => {
127
+ db.close();
128
+ });
129
+ function insertUsage(tool, createdAt) {
130
+ db.prepare(`
131
+ INSERT INTO tool_usage (tool_name, context, outcome, created_at)
132
+ VALUES (?, 'test', 'success', ?)
133
+ `).run(tool, createdAt);
134
+ }
135
+ it('builds transitions correctly', () => {
136
+ insertUsage('search', '2026-03-06 10:00:00');
137
+ insertUsage('read', '2026-03-06 10:01:00');
138
+ insertUsage('edit', '2026-03-06 10:02:00');
139
+ insertUsage('search', '2026-03-06 10:03:00');
140
+ insertUsage('read', '2026-03-06 10:04:00');
141
+ const analyzer = new ToolPatternAnalyzer(db);
142
+ const transitions = analyzer.getTransitions();
143
+ expect(transitions.get('search')?.get('read')).toBe(2);
144
+ expect(transitions.get('read')?.get('edit')).toBe(1);
145
+ expect(transitions.get('edit')?.get('search')).toBe(1);
146
+ });
147
+ it('predicts next tool based on transitions', () => {
148
+ insertUsage('search', '2026-03-06 10:00:00');
149
+ insertUsage('read', '2026-03-06 10:01:00');
150
+ insertUsage('search', '2026-03-06 10:02:00');
151
+ insertUsage('read', '2026-03-06 10:03:00');
152
+ insertUsage('search', '2026-03-06 10:04:00');
153
+ insertUsage('edit', '2026-03-06 10:05:00');
154
+ const analyzer = new ToolPatternAnalyzer(db);
155
+ const predictions = analyzer.predictNext('search');
156
+ expect(predictions.length).toBeGreaterThanOrEqual(1);
157
+ // 'read' follows 'search' 2 out of 3 times
158
+ expect(predictions[0].tool).toBe('read');
159
+ expect(predictions[0].probability).toBeCloseTo(2 / 3, 5);
160
+ });
161
+ it('finds frequent pairs within 5-minute windows', () => {
162
+ // All within 5 minutes of each other
163
+ insertUsage('search', '2026-03-06 10:00:00');
164
+ insertUsage('read', '2026-03-06 10:01:00');
165
+ insertUsage('search', '2026-03-06 10:02:00');
166
+ insertUsage('read', '2026-03-06 10:03:00');
167
+ const analyzer = new ToolPatternAnalyzer(db);
168
+ const pairs = analyzer.getFrequentPairs();
169
+ expect(pairs.length).toBeGreaterThanOrEqual(1);
170
+ const searchRead = pairs.find(p => (p.toolA === 'read' && p.toolB === 'search') ||
171
+ (p.toolA === 'search' && p.toolB === 'read'));
172
+ expect(searchRead).toBeDefined();
173
+ expect(searchRead.count).toBeGreaterThanOrEqual(2);
174
+ });
175
+ it('returns empty predictions for unknown tool', () => {
176
+ const analyzer = new ToolPatternAnalyzer(db);
177
+ const predictions = analyzer.predictNext('nonexistent');
178
+ expect(predictions).toEqual([]);
179
+ });
180
+ it('returns empty sequences when not enough data', () => {
181
+ insertUsage('search', '2026-03-06 10:00:00');
182
+ const analyzer = new ToolPatternAnalyzer(db);
183
+ const sequences = analyzer.getSequences(3);
184
+ expect(sequences).toEqual([]);
185
+ });
186
+ });
187
+ //# sourceMappingURL=tool-learning.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tool-learning.test.js","sourceRoot":"","sources":["../../../src/tool-learning/__tests__/tool-learning.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AACzE,OAAO,QAAQ,MAAM,gBAAgB,CAAC;AAEtC,EAAE,CAAC,IAAI,CAAC,uBAAuB,EAAE,GAAG,EAAE,CAAC,CAAC;IACtC,SAAS,EAAE,GAAG,EAAE,CAAC,CAAC;QAChB,IAAI,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE,CAAC,EAAE,EAAE;KAC7D,CAAC;CACH,CAAC,CAAC,CAAC;AAEJ,OAAO,EAAE,WAAW,EAAE,uBAAuB,EAAE,MAAM,oBAAoB,CAAC;AAC1E,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAE1D,SAAS,QAAQ;IACf,OAAO,IAAI,QAAQ,CAAC,UAAU,CAAC,CAAC;AAClC,CAAC;AAED,QAAQ,CAAC,aAAa,EAAE,GAAG,EAAE;IAC3B,IAAI,EAAqB,CAAC;IAE1B,UAAU,CAAC,GAAG,EAAE;QACd,EAAE,GAAG,QAAQ,EAAE,CAAC;IAClB,CAAC,CAAC,CAAC;IAEH,SAAS,CAAC,GAAG,EAAE;QACb,EAAE,CAAC,KAAK,EAAE,CAAC;IACb,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,gCAAgC,EAAE,GAAG,EAAE;QACxC,MAAM,OAAO,GAAG,IAAI,WAAW,CAAC,EAAE,EAAE,EAAE,SAAS,EAAE,MAAM,EAAE,CAAC,CAAC;QAC3D,OAAO,CAAC,WAAW,CAAC,YAAY,EAAE,gBAAgB,EAAE,GAAG,EAAE,SAAS,CAAC,CAAC;QAEpE,MAAM,KAAK,GAAG,OAAO,CAAC,YAAY,CAAC,YAAY,CAAC,CAAC;QACjD,MAAM,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,gBAAgB,CAAC;YAC5C,IAAI,EAAE,YAAY;YAClB,SAAS,EAAE,CAAC;YACZ,WAAW,EAAE,CAAC;SACf,CAAC,CAAC,CAAC;IACN,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iCAAiC,EAAE,GAAG,EAAE;QACzC,MAAM,OAAO,GAAG,IAAI,WAAW,CAAC,EAAE,EAAE,EAAE,SAAS,EAAE,MAAM,EAAE,CAAC,CAAC;QAC3D,OAAO,CAAC,WAAW,CAAC,YAAY,EAAE,KAAK,EAAE,GAAG,EAAE,SAAS,CAAC,CAAC;QACzD,OAAO,CAAC,WAAW,CAAC,YAAY,EAAE,KAAK,EAAE,GAAG,EAAE,SAAS,CAAC,CAAC;QAEzD,MAAM,KAAK,GAAG,OAAO,CAAC,YAAY,CAAC,YAAY,CAAC,CAAC;QACjD,MAAM,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,gBAAgB,CAAC;YAC5C,IAAI,EAAE,YAAY;YAClB,SAAS,EAAE,CAAC;YACZ,WAAW,EAAE,GAAG;YAChB,WAAW,EAAE,GAAG;SACjB,CAAC,CAAC,CAAC;IACN,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6BAA6B,EAAE,GAAG,EAAE;QACrC,MAAM,OAAO,GAAG,IAAI,WAAW,CAAC,EAAE,EAAE,EAAE,SAAS,EAAE,MAAM,EAAE,CAAC,CAAC;QAC3D,OAAO,CAAC,WAAW,CAAC,QAAQ,EAAE,KAAK,EAAE,GAAG,EAAE,SAAS,CAAC,CAAC;QACrD,OAAO,CAAC,WAAW,CAAC,QAAQ,EAAE,KAAK,EAAE,GAAG,EAAE,SAAS,CAAC,CAAC;QACrD,OAAO,CAAC,WAAW,CAAC,QAAQ,EAAE,KAAK,EAAE,GAAG,EAAE,SAAS,CAAC,CAAC;QAErD,MAAM,KAAK,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC;QACrC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACxC,MAAM,CAAE,KAAwB,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACjD,qCAAqC;QACrC,MAAM,CAAE,KAAiC,CAAC,CAAC,CAAE,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACrE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qDAAqD,EAAE,GAAG,EAAE;QAC7D,MAAM,OAAO,GAAG,IAAI,WAAW,CAAC,EAAE,EAAE,EAAE,SAAS,EAAE,MAAM,EAAE,CAAC,CAAC;QAC3D,yCAAyC;QACzC,OAAO,CAAC,WAAW,CAAC,QAAQ,EAAE,aAAa,EAAE,GAAG,EAAE,SAAS,CAAC,CAAC;QAC7D,OAAO,CAAC,WAAW,CAAC,QAAQ,EAAE,aAAa,EAAE,GAAG,EAAE,SAAS,CAAC,CAAC;QAC7D,OAAO,CAAC,WAAW,CAAC,QAAQ,EAAE,WAAW,EAAE,GAAG,EAAE,SAAS,CAAC,CAAC;QAC3D,uCAAuC;QACvC,OAAO,CAAC,WAAW,CAAC,QAAQ,EAAE,aAAa,EAAE,GAAG,EAAE,SAAS,CAAC,CAAC;QAC7D,6BAA6B;QAC7B,OAAO,CAAC,WAAW,CAAC,QAAQ,EAAE,eAAe,EAAE,EAAE,EAAE,SAAS,CAAC,CAAC;QAE9D,MAAM,IAAI,GAAG,OAAO,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;QACxC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,sBAAsB,CAAC,CAAC,CAAC,CAAC;QAC9C,MAAM,CAAC,IAAI,CAAC,CAAC,CAAE,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACrC,8CAA8C;QAC9C,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,aAAa,EAAE,CAAC;IAC9D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,uCAAuC,EAAE,GAAG,EAAE;QAC/C,MAAM,OAAO,GAAG,IAAI,WAAW,CAAC,EAAE,EAAE,EAAE,SAAS,EAAE,MAAM,EAAE,CAAC,CAAC;QAC3D,OAAO,CAAC,WAAW,CAAC,QAAQ,EAAE,KAAK,EAAE,GAAG,EAAE,SAAS,CAAC,CAAC;QACrD,OAAO,CAAC,WAAW,CAAC,QAAQ,EAAE,KAAK,EAAE,GAAG,EAAE,SAAS,CAAC,CAAC;QACrD,OAAO,CAAC,WAAW,CAAC,QAAQ,EAAE,KAAK,EAAE,GAAG,EAAE,SAAS,CAAC,CAAC;QAErD,MAAM,KAAK,GAAG,OAAO,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC;QAC7C,MAAM,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,gBAAgB,CAAC;YAC5C,SAAS,EAAE,CAAC;SACb,CAAC,CAAC,CAAC;QACJ,gCAAgC;QAChC,MAAM,CAAE,KAAiC,CAAC,WAAW,CAAC,CAAC,WAAW,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;IAC/E,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,sCAAsC,EAAE,GAAG,EAAE;QAC9C,MAAM,OAAO,GAAG,IAAI,WAAW,CAAC,EAAE,EAAE,EAAE,SAAS,EAAE,MAAM,EAAE,CAAC,CAAC;QAC3D,MAAM,KAAK,GAAG,OAAO,CAAC,YAAY,CAAC,aAAa,CAAC,CAAC;QAClD,MAAM,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,gBAAgB,CAAC;YAC5C,IAAI,EAAE,aAAa;YACnB,SAAS,EAAE,CAAC;YACZ,WAAW,EAAE,CAAC;SACf,CAAC,CAAC,CAAC;IACN,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,kCAAkC,EAAE,GAAG,EAAE;QAC1C,MAAM,OAAO,GAAG,IAAI,WAAW,CAAC,EAAE,EAAE,EAAE,SAAS,EAAE,MAAM,EAAE,CAAC,CAAC;QAC3D,OAAO,CAAC,WAAW,CAAC,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,SAAS,CAAC,CAAC;QACrD,OAAO,CAAC,WAAW,CAAC,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,SAAS,CAAC,CAAC;QACrD,OAAO,CAAC,WAAW,CAAC,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,SAAS,CAAC,CAAC;QAErD,MAAM,MAAM,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC;QACnC,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACpC,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACnC,uBAAuB;QACvB,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC,WAAW,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;IACtD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,yBAAyB,EAAE,GAAG,EAAE;QACjC,MAAM,QAAQ,GAAG,IAAI,WAAW,CAAC,EAAE,EAAE,EAAE,SAAS,EAAE,MAAM,EAAE,CAAC,CAAC;QAC5D,QAAQ,CAAC,WAAW,CAAC,QAAQ,EAAE,KAAK,EAAE,GAAG,EAAE,SAAS,CAAC,CAAC;QAEtD,sDAAsD;QACtD,uBAAuB,CAAC,EAAE,CAAC,CAAC;QAC5B,MAAM,QAAQ,GAAG,IAAI,WAAW,CAAC,EAAE,EAAE,EAAE,SAAS,EAAE,MAAM,EAAE,CAAC,CAAC;QAE5D,MAAM,KAAK,GAAG,QAAQ,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC;QAC9C,MAAM,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,gBAAgB,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;IACnE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,oCAAoC,EAAE,GAAG,EAAE;QAC5C,MAAM,OAAO,GAAG,IAAI,WAAW,CAAC,EAAE,EAAE,EAAE,SAAS,EAAE,MAAM,EAAE,CAAC,CAAC;QAC3D,MAAM,MAAM,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC;QACnC,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACpC,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACnC,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACxC,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,qBAAqB,EAAE,GAAG,EAAE;IACnC,IAAI,EAAqB,CAAC;IAE1B,UAAU,CAAC,GAAG,EAAE;QACd,EAAE,GAAG,QAAQ,EAAE,CAAC;QAChB,0CAA0C;QAC1C,uBAAuB,CAAC,EAAE,CAAC,CAAC;IAC9B,CAAC,CAAC,CAAC;IAEH,SAAS,CAAC,GAAG,EAAE;QACb,EAAE,CAAC,KAAK,EAAE,CAAC;IACb,CAAC,CAAC,CAAC;IAEH,SAAS,WAAW,CAAC,IAAY,EAAE,SAAiB;QAClD,EAAE,CAAC,OAAO,CAAC;;;KAGV,CAAC,CAAC,GAAG,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;IAC1B,CAAC;IAED,EAAE,CAAC,8BAA8B,EAAE,GAAG,EAAE;QACtC,WAAW,CAAC,QAAQ,EAAE,qBAAqB,CAAC,CAAC;QAC7C,WAAW,CAAC,MAAM,EAAI,qBAAqB,CAAC,CAAC;QAC7C,WAAW,CAAC,MAAM,EAAI,qBAAqB,CAAC,CAAC;QAC7C,WAAW,CAAC,QAAQ,EAAE,qBAAqB,CAAC,CAAC;QAC7C,WAAW,CAAC,MAAM,EAAI,qBAAqB,CAAC,CAAC;QAE7C,MAAM,QAAQ,GAAG,IAAI,mBAAmB,CAAC,EAAE,CAAC,CAAC;QAC7C,MAAM,WAAW,GAAG,QAAQ,CAAC,cAAc,EAAE,CAAC;QAE9C,MAAM,CAAC,WAAW,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACvD,MAAM,CAAC,WAAW,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACrD,MAAM,CAAC,WAAW,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACzD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,yCAAyC,EAAE,GAAG,EAAE;QACjD,WAAW,CAAC,QAAQ,EAAE,qBAAqB,CAAC,CAAC;QAC7C,WAAW,CAAC,MAAM,EAAI,qBAAqB,CAAC,CAAC;QAC7C,WAAW,CAAC,QAAQ,EAAE,qBAAqB,CAAC,CAAC;QAC7C,WAAW,CAAC,MAAM,EAAI,qBAAqB,CAAC,CAAC;QAC7C,WAAW,CAAC,QAAQ,EAAE,qBAAqB,CAAC,CAAC;QAC7C,WAAW,CAAC,MAAM,EAAI,qBAAqB,CAAC,CAAC;QAE7C,MAAM,QAAQ,GAAG,IAAI,mBAAmB,CAAC,EAAE,CAAC,CAAC;QAC7C,MAAM,WAAW,GAAG,QAAQ,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC;QAEnD,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,sBAAsB,CAAC,CAAC,CAAC,CAAC;QACrD,2CAA2C;QAC3C,MAAM,CAAC,WAAW,CAAC,CAAC,CAAE,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAC1C,MAAM,CAAC,WAAW,CAAC,CAAC,CAAE,CAAC,WAAW,CAAC,CAAC,WAAW,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;IAC5D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8CAA8C,EAAE,GAAG,EAAE;QACtD,qCAAqC;QACrC,WAAW,CAAC,QAAQ,EAAE,qBAAqB,CAAC,CAAC;QAC7C,WAAW,CAAC,MAAM,EAAI,qBAAqB,CAAC,CAAC;QAC7C,WAAW,CAAC,QAAQ,EAAE,qBAAqB,CAAC,CAAC;QAC7C,WAAW,CAAC,MAAM,EAAI,qBAAqB,CAAC,CAAC;QAE7C,MAAM,QAAQ,GAAG,IAAI,mBAAmB,CAAC,EAAE,CAAC,CAAC;QAC7C,MAAM,KAAK,GAAG,QAAQ,CAAC,gBAAgB,EAAE,CAAC;QAE1C,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,sBAAsB,CAAC,CAAC,CAAC,CAAC;QAC/C,MAAM,UAAU,GAAG,KAAK,CAAC,IAAI,CAC3B,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,KAAK,KAAK,MAAM,IAAI,CAAC,CAAC,KAAK,KAAK,QAAQ,CAAC;YAC5C,CAAC,CAAC,CAAC,KAAK,KAAK,QAAQ,IAAI,CAAC,CAAC,KAAK,KAAK,MAAM,CAAC,CAClD,CAAC;QACF,MAAM,CAAC,UAAU,CAAC,CAAC,WAAW,EAAE,CAAC;QACjC,MAAM,CAAC,UAAW,CAAC,KAAK,CAAC,CAAC,sBAAsB,CAAC,CAAC,CAAC,CAAC;IACtD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4CAA4C,EAAE,GAAG,EAAE;QACpD,MAAM,QAAQ,GAAG,IAAI,mBAAmB,CAAC,EAAE,CAAC,CAAC;QAC7C,MAAM,WAAW,GAAG,QAAQ,CAAC,WAAW,CAAC,aAAa,CAAC,CAAC;QACxD,MAAM,CAAC,WAAW,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IAClC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8CAA8C,EAAE,GAAG,EAAE;QACtD,WAAW,CAAC,QAAQ,EAAE,qBAAqB,CAAC,CAAC;QAE7C,MAAM,QAAQ,GAAG,IAAI,mBAAmB,CAAC,EAAE,CAAC,CAAC;QAC7C,MAAM,SAAS,GAAG,QAAQ,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QAC3C,MAAM,CAAC,SAAS,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IAChC,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,4 @@
1
+ export { ToolTracker, runToolTrackerMigration } from './tool-tracker.js';
2
+ export { ToolPatternAnalyzer } from './tool-patterns.js';
3
+ export type { ToolOutcome, ToolUsageRecord, ToolStats, ToolRecommendation, ToolTrackerStatus, ToolTrackerConfig, } from './tool-tracker.js';
4
+ export type { ToolSequence, ToolPrediction, ToolPair, ToolTransition, } from './tool-patterns.js';
@@ -0,0 +1,3 @@
1
+ export { ToolTracker, runToolTrackerMigration } from './tool-tracker.js';
2
+ export { ToolPatternAnalyzer } from './tool-patterns.js';
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/tool-learning/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,uBAAuB,EAAE,MAAM,mBAAmB,CAAC;AACzE,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC"}
@@ -0,0 +1,47 @@
1
+ import type Database from 'better-sqlite3';
2
+ export interface ToolSequence {
3
+ sequence: string[];
4
+ count: number;
5
+ }
6
+ export interface ToolPrediction {
7
+ tool: string;
8
+ probability: number;
9
+ }
10
+ export interface ToolPair {
11
+ toolA: string;
12
+ toolB: string;
13
+ count: number;
14
+ }
15
+ /** A single from→to transition with its count. */
16
+ export interface ToolTransition {
17
+ from: string;
18
+ to: string;
19
+ count: number;
20
+ }
21
+ export declare class ToolPatternAnalyzer {
22
+ private db;
23
+ private log;
24
+ private stmtAllUsage;
25
+ private stmtWindowUsage;
26
+ constructor(db: Database.Database);
27
+ /**
28
+ * Find common tool sequences (N-grams) of the given window size.
29
+ * Returns sequences sorted by frequency descending.
30
+ */
31
+ getSequences(windowSize?: number): ToolSequence[];
32
+ /**
33
+ * Build a Markov transition matrix: which tool follows which.
34
+ * Returns Map<toolA, Map<toolB, count>>.
35
+ */
36
+ getTransitions(): Map<string, Map<string, number>>;
37
+ /**
38
+ * Predict the top 3 most likely next tools given the current tool,
39
+ * based on transition probabilities from the Markov chain.
40
+ */
41
+ predictNext(currentTool: string): ToolPrediction[];
42
+ /**
43
+ * Find tool pairs that frequently occur together within 5-minute windows.
44
+ * Returns pairs sorted by co-occurrence count descending.
45
+ */
46
+ getFrequentPairs(): ToolPair[];
47
+ }
@@ -0,0 +1,125 @@
1
+ // ── Tool Pattern Analyzer — Sequence & Transition Analysis ───
2
+ //
3
+ // Analyzes tool usage sequences to find patterns, build Markov
4
+ // transition matrices, and predict likely next tools.
5
+ import { getLogger } from '../utils/logger.js';
6
+ // ── Engine ──────────────────────────────────────────────
7
+ export class ToolPatternAnalyzer {
8
+ db;
9
+ log = getLogger();
10
+ // Prepared statements
11
+ stmtAllUsage;
12
+ stmtWindowUsage;
13
+ constructor(db) {
14
+ this.db = db;
15
+ // These statements query the tool_usage table created by ToolTracker
16
+ this.stmtAllUsage = db.prepare(`
17
+ SELECT tool_name, created_at FROM tool_usage ORDER BY created_at ASC
18
+ `);
19
+ this.stmtWindowUsage = db.prepare(`
20
+ SELECT tool_name, created_at FROM tool_usage ORDER BY created_at ASC
21
+ `);
22
+ this.log.info('[tool-patterns] Analyzer initialized');
23
+ }
24
+ /**
25
+ * Find common tool sequences (N-grams) of the given window size.
26
+ * Returns sequences sorted by frequency descending.
27
+ */
28
+ getSequences(windowSize = 3) {
29
+ const rows = this.stmtAllUsage.all();
30
+ if (rows.length < windowSize)
31
+ return [];
32
+ const seqMap = new Map();
33
+ for (let i = 0; i <= rows.length - windowSize; i++) {
34
+ const seq = rows.slice(i, i + windowSize).map(r => r.tool_name);
35
+ const key = seq.join(' → ');
36
+ seqMap.set(key, (seqMap.get(key) ?? 0) + 1);
37
+ }
38
+ const sequences = [];
39
+ for (const [key, count] of seqMap.entries()) {
40
+ if (count >= 2) {
41
+ sequences.push({ sequence: key.split(' → '), count });
42
+ }
43
+ }
44
+ sequences.sort((a, b) => b.count - a.count);
45
+ return sequences;
46
+ }
47
+ /**
48
+ * Build a Markov transition matrix: which tool follows which.
49
+ * Returns Map<toolA, Map<toolB, count>>.
50
+ */
51
+ getTransitions() {
52
+ const rows = this.stmtAllUsage.all();
53
+ const transitions = new Map();
54
+ for (let i = 0; i < rows.length - 1; i++) {
55
+ const from = rows[i].tool_name;
56
+ const to = rows[i + 1].tool_name;
57
+ if (!transitions.has(from)) {
58
+ transitions.set(from, new Map());
59
+ }
60
+ const inner = transitions.get(from);
61
+ inner.set(to, (inner.get(to) ?? 0) + 1);
62
+ }
63
+ return transitions;
64
+ }
65
+ /**
66
+ * Predict the top 3 most likely next tools given the current tool,
67
+ * based on transition probabilities from the Markov chain.
68
+ */
69
+ predictNext(currentTool) {
70
+ const transitions = this.getTransitions();
71
+ const fromMap = transitions.get(currentTool);
72
+ if (!fromMap || fromMap.size === 0)
73
+ return [];
74
+ // Calculate total transitions from this tool
75
+ let total = 0;
76
+ for (const count of fromMap.values()) {
77
+ total += count;
78
+ }
79
+ const predictions = [];
80
+ for (const [tool, count] of fromMap.entries()) {
81
+ predictions.push({
82
+ tool,
83
+ probability: count / total,
84
+ });
85
+ }
86
+ predictions.sort((a, b) => b.probability - a.probability);
87
+ return predictions.slice(0, 3);
88
+ }
89
+ /**
90
+ * Find tool pairs that frequently occur together within 5-minute windows.
91
+ * Returns pairs sorted by co-occurrence count descending.
92
+ */
93
+ getFrequentPairs() {
94
+ const rows = this.stmtWindowUsage.all();
95
+ if (rows.length < 2)
96
+ return [];
97
+ const pairMap = new Map();
98
+ const WINDOW_MS = 5 * 60 * 1000; // 5 minutes
99
+ for (let i = 0; i < rows.length; i++) {
100
+ const timeI = new Date(rows[i].created_at).getTime();
101
+ for (let j = i + 1; j < rows.length; j++) {
102
+ const timeJ = new Date(rows[j].created_at).getTime();
103
+ if (timeJ - timeI > WINDOW_MS)
104
+ break;
105
+ const toolA = rows[i].tool_name;
106
+ const toolB = rows[j].tool_name;
107
+ if (toolA === toolB)
108
+ continue;
109
+ // Normalize pair key (alphabetical order) so A-B and B-A count together
110
+ const key = toolA < toolB ? `${toolA}|${toolB}` : `${toolB}|${toolA}`;
111
+ pairMap.set(key, (pairMap.get(key) ?? 0) + 1);
112
+ }
113
+ }
114
+ const pairs = [];
115
+ for (const [key, count] of pairMap.entries()) {
116
+ if (count >= 2) {
117
+ const [toolA, toolB] = key.split('|');
118
+ pairs.push({ toolA, toolB, count });
119
+ }
120
+ }
121
+ pairs.sort((a, b) => b.count - a.count);
122
+ return pairs;
123
+ }
124
+ }
125
+ //# sourceMappingURL=tool-patterns.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tool-patterns.js","sourceRoot":"","sources":["../../src/tool-learning/tool-patterns.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,58 @@
1
+ import type Database from 'better-sqlite3';
2
+ import type { ThoughtStream } from '../consciousness/thought-stream.js';
3
+ export type ToolOutcome = 'success' | 'failure' | 'partial';
4
+ export interface ToolUsageRecord {
5
+ id?: number;
6
+ tool_name: string;
7
+ context: string | null;
8
+ duration_ms: number | null;
9
+ outcome: ToolOutcome;
10
+ metadata: Record<string, unknown> | null;
11
+ created_at: string;
12
+ }
13
+ export interface ToolStats {
14
+ tool: string;
15
+ totalUses: number;
16
+ successRate: number;
17
+ avgDuration: number;
18
+ lastUsed: string;
19
+ }
20
+ export interface ToolRecommendation {
21
+ tool: string;
22
+ score: number;
23
+ successRate: number;
24
+ frequency: number;
25
+ }
26
+ export interface ToolTrackerStatus {
27
+ totalTracked: number;
28
+ uniqueTools: number;
29
+ avgSuccessRate: number;
30
+ }
31
+ export interface ToolTrackerConfig {
32
+ brainName: string;
33
+ }
34
+ export declare function runToolTrackerMigration(db: Database.Database): void;
35
+ export declare class ToolTracker {
36
+ private db;
37
+ private config;
38
+ private ts;
39
+ private log;
40
+ private stmtInsert;
41
+ private stmtStatsSingle;
42
+ private stmtStatsAll;
43
+ private stmtRecommend;
44
+ private stmtTotalTracked;
45
+ private stmtUniqueTools;
46
+ private stmtAvgSuccessRate;
47
+ constructor(db: Database.Database, config: ToolTrackerConfig);
48
+ /** Set the ThoughtStream for consciousness integration. */
49
+ setThoughtStream(stream: ThoughtStream): void;
50
+ /** Record a tool usage event. */
51
+ recordUsage(tool: string, context: string | null, duration: number | null, outcome?: ToolOutcome, metadata?: Record<string, unknown>): void;
52
+ /** Get statistics for a specific tool, or all tools if none specified. */
53
+ getToolStats(tool?: string): ToolStats | ToolStats[];
54
+ /** Recommend top-5 tools for a given context based on success rate * frequency. */
55
+ recommend(context: string): ToolRecommendation[];
56
+ /** Get tracker status summary. */
57
+ getStatus(): ToolTrackerStatus;
58
+ }
@@ -0,0 +1,135 @@
1
+ // ── Tool Tracker — Usage Recording & Recommendation ──────────
2
+ //
3
+ // Tracks tool usage with context, duration, and outcome.
4
+ // Provides statistics and context-based recommendations.
5
+ import { getLogger } from '../utils/logger.js';
6
+ // ── Migration ───────────────────────────────────────────
7
+ export function runToolTrackerMigration(db) {
8
+ db.exec(`
9
+ CREATE TABLE IF NOT EXISTS tool_usage (
10
+ id INTEGER PRIMARY KEY,
11
+ tool_name TEXT NOT NULL,
12
+ context TEXT,
13
+ duration_ms INTEGER,
14
+ outcome TEXT DEFAULT 'success' CHECK(outcome IN ('success','failure','partial')),
15
+ metadata TEXT,
16
+ created_at TEXT DEFAULT (datetime('now'))
17
+ );
18
+ CREATE INDEX IF NOT EXISTS idx_tool_usage_tool_name ON tool_usage(tool_name);
19
+ `);
20
+ }
21
+ // ── Engine ──────────────────────────────────────────────
22
+ export class ToolTracker {
23
+ db;
24
+ config;
25
+ ts = null;
26
+ log = getLogger();
27
+ // Prepared statements
28
+ stmtInsert;
29
+ stmtStatsSingle;
30
+ stmtStatsAll;
31
+ stmtRecommend;
32
+ stmtTotalTracked;
33
+ stmtUniqueTools;
34
+ stmtAvgSuccessRate;
35
+ constructor(db, config) {
36
+ this.db = db;
37
+ this.config = config;
38
+ runToolTrackerMigration(db);
39
+ // Prepare all statements
40
+ this.stmtInsert = db.prepare(`
41
+ INSERT INTO tool_usage (tool_name, context, duration_ms, outcome, metadata)
42
+ VALUES (?, ?, ?, ?, ?)
43
+ `);
44
+ this.stmtStatsSingle = db.prepare(`
45
+ SELECT
46
+ tool_name AS tool,
47
+ COUNT(*) AS totalUses,
48
+ CAST(SUM(CASE WHEN outcome = 'success' THEN 1 ELSE 0 END) AS REAL) / COUNT(*) AS successRate,
49
+ COALESCE(AVG(duration_ms), 0) AS avgDuration,
50
+ MAX(created_at) AS lastUsed
51
+ FROM tool_usage
52
+ WHERE tool_name = ?
53
+ GROUP BY tool_name
54
+ `);
55
+ this.stmtStatsAll = db.prepare(`
56
+ SELECT
57
+ tool_name AS tool,
58
+ COUNT(*) AS totalUses,
59
+ CAST(SUM(CASE WHEN outcome = 'success' THEN 1 ELSE 0 END) AS REAL) / COUNT(*) AS successRate,
60
+ COALESCE(AVG(duration_ms), 0) AS avgDuration,
61
+ MAX(created_at) AS lastUsed
62
+ FROM tool_usage
63
+ GROUP BY tool_name
64
+ ORDER BY totalUses DESC
65
+ `);
66
+ this.stmtRecommend = db.prepare(`
67
+ SELECT
68
+ tool_name AS tool,
69
+ COUNT(*) AS frequency,
70
+ CAST(SUM(CASE WHEN outcome = 'success' THEN 1 ELSE 0 END) AS REAL) / COUNT(*) AS successRate
71
+ FROM tool_usage
72
+ WHERE context LIKE ?
73
+ GROUP BY tool_name
74
+ ORDER BY (CAST(SUM(CASE WHEN outcome = 'success' THEN 1 ELSE 0 END) AS REAL) / COUNT(*)) * COUNT(*) DESC
75
+ LIMIT 5
76
+ `);
77
+ this.stmtTotalTracked = db.prepare(`
78
+ SELECT COUNT(*) AS total FROM tool_usage
79
+ `);
80
+ this.stmtUniqueTools = db.prepare(`
81
+ SELECT COUNT(DISTINCT tool_name) AS unique_tools FROM tool_usage
82
+ `);
83
+ this.stmtAvgSuccessRate = db.prepare(`
84
+ SELECT COALESCE(
85
+ CAST(SUM(CASE WHEN outcome = 'success' THEN 1 ELSE 0 END) AS REAL) / NULLIF(COUNT(*), 0),
86
+ 0
87
+ ) AS avgRate
88
+ FROM tool_usage
89
+ `);
90
+ this.log.info(`[tool-tracker] Initialized for ${config.brainName}`);
91
+ }
92
+ /** Set the ThoughtStream for consciousness integration. */
93
+ setThoughtStream(stream) {
94
+ this.ts = stream;
95
+ }
96
+ /** Record a tool usage event. */
97
+ recordUsage(tool, context, duration, outcome = 'success', metadata) {
98
+ this.stmtInsert.run(tool, context, duration, outcome, metadata ? JSON.stringify(metadata) : null);
99
+ this.ts?.emit('tool-tracker', 'analyzing', `Recorded ${tool} usage: ${outcome}${duration ? ` (${duration}ms)` : ''}`, 'routine');
100
+ }
101
+ /** Get statistics for a specific tool, or all tools if none specified. */
102
+ getToolStats(tool) {
103
+ if (tool) {
104
+ const row = this.stmtStatsSingle.get(tool);
105
+ if (!row) {
106
+ return { tool, totalUses: 0, successRate: 0, avgDuration: 0, lastUsed: '' };
107
+ }
108
+ return row;
109
+ }
110
+ return this.stmtStatsAll.all();
111
+ }
112
+ /** Recommend top-5 tools for a given context based on success rate * frequency. */
113
+ recommend(context) {
114
+ const pattern = `%${context}%`;
115
+ const rows = this.stmtRecommend.all(pattern);
116
+ return rows.map(r => ({
117
+ tool: r.tool,
118
+ score: r.successRate * r.frequency,
119
+ successRate: r.successRate,
120
+ frequency: r.frequency,
121
+ }));
122
+ }
123
+ /** Get tracker status summary. */
124
+ getStatus() {
125
+ const total = this.stmtTotalTracked.get().total;
126
+ const unique = this.stmtUniqueTools.get().unique_tools;
127
+ const avgRate = this.stmtAvgSuccessRate.get().avgRate;
128
+ return {
129
+ totalTracked: total,
130
+ uniqueTools: unique,
131
+ avgSuccessRate: avgRate,
132
+ };
133
+ }
134
+ }
135
+ //# sourceMappingURL=tool-tracker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tool-tracker.js","sourceRoot":"","sources":["../../src/tool-learning/tool-tracker.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export {};