@timmeck/brain-core 2.36.24 → 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 (115) hide show
  1. package/dist/active-learning/__tests__/active-learning.test.d.ts +1 -0
  2. package/dist/active-learning/__tests__/active-learning.test.js +132 -0
  3. package/dist/active-learning/__tests__/active-learning.test.js.map +1 -0
  4. package/dist/active-learning/active-learner.d.ts +79 -0
  5. package/dist/active-learning/active-learner.js +224 -0
  6. package/dist/active-learning/active-learner.js.map +1 -0
  7. package/dist/active-learning/index.d.ts +2 -0
  8. package/dist/active-learning/index.js +2 -0
  9. package/dist/active-learning/index.js.map +1 -0
  10. package/dist/code-health/__tests__/code-health.test.d.ts +1 -0
  11. package/dist/code-health/__tests__/code-health.test.js +123 -0
  12. package/dist/code-health/__tests__/code-health.test.js.map +1 -0
  13. package/dist/code-health/health-monitor.d.ts +55 -0
  14. package/dist/code-health/health-monitor.js +180 -0
  15. package/dist/code-health/health-monitor.js.map +1 -0
  16. package/dist/code-health/index.d.ts +2 -0
  17. package/dist/code-health/index.js +2 -0
  18. package/dist/code-health/index.js.map +1 -0
  19. package/dist/consensus/__tests__/consensus.test.d.ts +1 -0
  20. package/dist/consensus/__tests__/consensus.test.js +159 -0
  21. package/dist/consensus/__tests__/consensus.test.js.map +1 -0
  22. package/dist/consensus/consensus-engine.d.ts +81 -0
  23. package/dist/consensus/consensus-engine.js +237 -0
  24. package/dist/consensus/consensus-engine.js.map +1 -0
  25. package/dist/consensus/index.d.ts +2 -0
  26. package/dist/consensus/index.js +2 -0
  27. package/dist/consensus/index.js.map +1 -0
  28. package/dist/feedback/__tests__/feedback-engine.test.d.ts +1 -0
  29. package/dist/feedback/__tests__/feedback-engine.test.js +156 -0
  30. package/dist/feedback/__tests__/feedback-engine.test.js.map +1 -0
  31. package/dist/feedback/feedback-engine.d.ts +61 -0
  32. package/dist/feedback/feedback-engine.js +203 -0
  33. package/dist/feedback/feedback-engine.js.map +1 -0
  34. package/dist/feedback/index.d.ts +2 -0
  35. package/dist/feedback/index.js +2 -0
  36. package/dist/feedback/index.js.map +1 -0
  37. package/dist/index.d.ts +32 -0
  38. package/dist/index.js +27 -0
  39. package/dist/index.js.map +1 -1
  40. package/dist/knowledge-graph/__tests__/knowledge-graph.test.d.ts +1 -0
  41. package/dist/knowledge-graph/__tests__/knowledge-graph.test.js +215 -0
  42. package/dist/knowledge-graph/__tests__/knowledge-graph.test.js.map +1 -0
  43. package/dist/knowledge-graph/fact-extractor.d.ts +23 -0
  44. package/dist/knowledge-graph/fact-extractor.js +70 -0
  45. package/dist/knowledge-graph/fact-extractor.js.map +1 -0
  46. package/dist/knowledge-graph/graph-engine.d.ts +78 -0
  47. package/dist/knowledge-graph/graph-engine.js +276 -0
  48. package/dist/knowledge-graph/graph-engine.js.map +1 -0
  49. package/dist/knowledge-graph/index.d.ts +4 -0
  50. package/dist/knowledge-graph/index.js +3 -0
  51. package/dist/knowledge-graph/index.js.map +1 -0
  52. package/dist/proactive/__tests__/proactive-engine.test.d.ts +1 -0
  53. package/dist/proactive/__tests__/proactive-engine.test.js +183 -0
  54. package/dist/proactive/__tests__/proactive-engine.test.js.map +1 -0
  55. package/dist/proactive/index.d.ts +2 -0
  56. package/dist/proactive/index.js +2 -0
  57. package/dist/proactive/index.js.map +1 -0
  58. package/dist/proactive/proactive-engine.d.ts +86 -0
  59. package/dist/proactive/proactive-engine.js +252 -0
  60. package/dist/proactive/proactive-engine.js.map +1 -0
  61. package/dist/rag/__tests__/rag-engine.test.d.ts +1 -0
  62. package/dist/rag/__tests__/rag-engine.test.js +235 -0
  63. package/dist/rag/__tests__/rag-engine.test.js.map +1 -0
  64. package/dist/rag/index.d.ts +4 -0
  65. package/dist/rag/index.js +3 -0
  66. package/dist/rag/index.js.map +1 -0
  67. package/dist/rag/rag-engine.d.ts +98 -0
  68. package/dist/rag/rag-engine.js +310 -0
  69. package/dist/rag/rag-engine.js.map +1 -0
  70. package/dist/rag/rag-indexer.d.ts +52 -0
  71. package/dist/rag/rag-indexer.js +144 -0
  72. package/dist/rag/rag-indexer.js.map +1 -0
  73. package/dist/research/__tests__/semantic-compressor.test.d.ts +1 -0
  74. package/dist/research/__tests__/semantic-compressor.test.js +153 -0
  75. package/dist/research/__tests__/semantic-compressor.test.js.map +1 -0
  76. package/dist/research/semantic-compressor.d.ts +55 -0
  77. package/dist/research/semantic-compressor.js +227 -0
  78. package/dist/research/semantic-compressor.js.map +1 -0
  79. package/dist/teaching/__tests__/teaching.test.d.ts +1 -0
  80. package/dist/teaching/__tests__/teaching.test.js +151 -0
  81. package/dist/teaching/__tests__/teaching.test.js.map +1 -0
  82. package/dist/teaching/curriculum.d.ts +32 -0
  83. package/dist/teaching/curriculum.js +89 -0
  84. package/dist/teaching/curriculum.js.map +1 -0
  85. package/dist/teaching/index.d.ts +4 -0
  86. package/dist/teaching/index.js +3 -0
  87. package/dist/teaching/index.js.map +1 -0
  88. package/dist/teaching/teaching-protocol.d.ts +74 -0
  89. package/dist/teaching/teaching-protocol.js +164 -0
  90. package/dist/teaching/teaching-protocol.js.map +1 -0
  91. package/dist/tool-learning/__tests__/tool-learning.test.d.ts +1 -0
  92. package/dist/tool-learning/__tests__/tool-learning.test.js +187 -0
  93. package/dist/tool-learning/__tests__/tool-learning.test.js.map +1 -0
  94. package/dist/tool-learning/index.d.ts +4 -0
  95. package/dist/tool-learning/index.js +3 -0
  96. package/dist/tool-learning/index.js.map +1 -0
  97. package/dist/tool-learning/tool-patterns.d.ts +47 -0
  98. package/dist/tool-learning/tool-patterns.js +125 -0
  99. package/dist/tool-learning/tool-patterns.js.map +1 -0
  100. package/dist/tool-learning/tool-tracker.d.ts +58 -0
  101. package/dist/tool-learning/tool-tracker.js +135 -0
  102. package/dist/tool-learning/tool-tracker.js.map +1 -0
  103. package/dist/user-model/__tests__/user-model.test.d.ts +1 -0
  104. package/dist/user-model/__tests__/user-model.test.js +142 -0
  105. package/dist/user-model/__tests__/user-model.test.js.map +1 -0
  106. package/dist/user-model/adaptive-context.d.ts +18 -0
  107. package/dist/user-model/adaptive-context.js +46 -0
  108. package/dist/user-model/adaptive-context.js.map +1 -0
  109. package/dist/user-model/index.d.ts +4 -0
  110. package/dist/user-model/index.js +3 -0
  111. package/dist/user-model/index.js.map +1 -0
  112. package/dist/user-model/user-model.d.ts +53 -0
  113. package/dist/user-model/user-model.js +204 -0
  114. package/dist/user-model/user-model.js.map +1 -0
  115. package/package.json +1 -1
@@ -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 {};
@@ -0,0 +1,142 @@
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 { UserModel, runUserModelMigration } from '../user-model.js';
9
+ import { AdaptiveContext } from '../adaptive-context.js';
10
+ function createDb() {
11
+ return new Database(':memory:');
12
+ }
13
+ describe('UserModel', () => {
14
+ let db;
15
+ beforeEach(() => {
16
+ db = createDb();
17
+ });
18
+ afterEach(() => {
19
+ db.close();
20
+ });
21
+ it('sets and gets a preference', () => {
22
+ const model = new UserModel(db, { brainName: 'test' });
23
+ model.setPreference('theme', 'dark');
24
+ expect(model.getPreference('theme')).toBe('dark');
25
+ });
26
+ it('returns null for unknown preference', () => {
27
+ const model = new UserModel(db, { brainName: 'test' });
28
+ expect(model.getPreference('nonexistent')).toBeNull();
29
+ });
30
+ it('updateFromInteraction tracks tool frequency', () => {
31
+ const model = new UserModel(db, { brainName: 'test' });
32
+ model.updateFromInteraction('mcp.search', 'finding code', 'success');
33
+ model.updateFromInteraction('mcp.search', 'finding docs', 'success');
34
+ const profile = model.getProfile();
35
+ expect(profile.topTools).toContain('mcp.search');
36
+ });
37
+ it('infers beginner skill level for < 3 successful uses', () => {
38
+ const model = new UserModel(db, { brainName: 'test' });
39
+ model.updateFromInteraction('trading.analyze', 'stocks', 'success');
40
+ model.updateFromInteraction('trading.analyze', 'stocks', 'success');
41
+ const profile = model.getProfile();
42
+ expect(profile.skillDomains.get('trading')).toBe('beginner');
43
+ });
44
+ it('infers intermediate skill level for 3-10 successful uses', () => {
45
+ const model = new UserModel(db, { brainName: 'test' });
46
+ for (let i = 0; i < 5; i++) {
47
+ model.updateFromInteraction('trading.analyze', 'stocks', 'success');
48
+ }
49
+ const profile = model.getProfile();
50
+ expect(profile.skillDomains.get('trading')).toBe('intermediate');
51
+ });
52
+ it('infers expert skill level for > 10 successful uses', () => {
53
+ const model = new UserModel(db, { brainName: 'test' });
54
+ for (let i = 0; i < 12; i++) {
55
+ model.updateFromInteraction('coding.refactor', 'cleanup', 'success');
56
+ }
57
+ const profile = model.getProfile();
58
+ expect(profile.skillDomains.get('coding')).toBe('expert');
59
+ });
60
+ it('getProfile returns complete structure', () => {
61
+ const model = new UserModel(db, { brainName: 'test' });
62
+ model.updateFromInteraction('mcp.search', 'ctx', 'success');
63
+ const profile = model.getProfile();
64
+ expect(profile.skillDomains).toBeInstanceOf(Map);
65
+ expect(Array.isArray(profile.topTools)).toBe(true);
66
+ expect(Array.isArray(profile.activeHours)).toBe(true);
67
+ expect(Array.isArray(profile.errorPatterns)).toBe(true);
68
+ });
69
+ it('migration is idempotent', () => {
70
+ const model1 = new UserModel(db, { brainName: 'test' });
71
+ model1.setPreference('lang', 'en');
72
+ // Run migration again
73
+ runUserModelMigration(db);
74
+ const model2 = new UserModel(db, { brainName: 'test' });
75
+ expect(model2.getPreference('lang')).toBe('en');
76
+ });
77
+ it('getStatus returns correct counts', () => {
78
+ const model = new UserModel(db, { brainName: 'test' });
79
+ const emptyStatus = model.getStatus();
80
+ expect(emptyStatus.totalKeys).toBe(0);
81
+ expect(emptyStatus.domains).toBe(0);
82
+ expect(emptyStatus.lastUpdated).toBeNull();
83
+ model.updateFromInteraction('mcp.search', 'ctx', 'success');
84
+ const status = model.getStatus();
85
+ expect(status.totalKeys).toBeGreaterThan(0);
86
+ expect(status.domains).toBeGreaterThanOrEqual(1);
87
+ expect(status.lastUpdated).not.toBeNull();
88
+ });
89
+ });
90
+ describe('AdaptiveContext', () => {
91
+ it('returns concise for all-expert profile', () => {
92
+ const ctx = new AdaptiveContext();
93
+ const profile = {
94
+ skillDomains: new Map([['coding', 'expert'], ['trading', 'expert']]),
95
+ topTools: [],
96
+ activeHours: [],
97
+ errorPatterns: [],
98
+ };
99
+ const result = ctx.enrichPrompt('How do I do X?', profile);
100
+ expect(result).toContain('Be concise');
101
+ expect(result).toContain('How do I do X?');
102
+ expect(ctx.getDetailLevel(profile)).toBe('concise');
103
+ });
104
+ it('returns detailed for profile with any beginner domain', () => {
105
+ const ctx = new AdaptiveContext();
106
+ const profile = {
107
+ skillDomains: new Map([['coding', 'expert'], ['trading', 'beginner']]),
108
+ topTools: [],
109
+ activeHours: [],
110
+ errorPatterns: [],
111
+ };
112
+ const result = ctx.enrichPrompt('How do I do X?', profile);
113
+ expect(result).toContain('Explain in detail');
114
+ expect(result).toContain('How do I do X?');
115
+ expect(ctx.getDetailLevel(profile)).toBe('detailed');
116
+ });
117
+ it('returns unmodified prompt for default/mixed profile', () => {
118
+ const ctx = new AdaptiveContext();
119
+ const profile = {
120
+ skillDomains: new Map([['coding', 'intermediate'], ['trading', 'expert']]),
121
+ topTools: [],
122
+ activeHours: [],
123
+ errorPatterns: [],
124
+ };
125
+ const result = ctx.enrichPrompt('How do I do X?', profile);
126
+ expect(result).toBe('How do I do X?');
127
+ expect(ctx.getDetailLevel(profile)).toBe('normal');
128
+ });
129
+ it('returns normal for empty profile', () => {
130
+ const ctx = new AdaptiveContext();
131
+ const profile = {
132
+ skillDomains: new Map(),
133
+ topTools: [],
134
+ activeHours: [],
135
+ errorPatterns: [],
136
+ };
137
+ const result = ctx.enrichPrompt('Hello', profile);
138
+ expect(result).toBe('Hello');
139
+ expect(ctx.getDetailLevel(profile)).toBe('normal');
140
+ });
141
+ });
142
+ //# sourceMappingURL=user-model.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"user-model.test.js","sourceRoot":"","sources":["../../../src/user-model/__tests__/user-model.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ import type { UserProfile } from './user-model.js';
2
+ export type DetailLevel = 'concise' | 'normal' | 'detailed';
3
+ export declare class AdaptiveContext {
4
+ /**
5
+ * Enrich a base prompt based on the user's profile.
6
+ * - If all domains are 'expert': prepend concise instructions.
7
+ * - If any domain is 'beginner': prepend detailed instructions.
8
+ * - Default: return prompt unmodified.
9
+ */
10
+ enrichPrompt(basePrompt: string, profile: UserProfile): string;
11
+ /**
12
+ * Determine the appropriate detail level from a user profile.
13
+ * - 'concise': all domains are expert level
14
+ * - 'detailed': any domain is beginner level
15
+ * - 'normal': default / mixed intermediate
16
+ */
17
+ getDetailLevel(profile: UserProfile): DetailLevel;
18
+ }
@@ -0,0 +1,46 @@
1
+ // ── Adaptive Context — Prompt Enrichment Based on User Profile ─
2
+ //
3
+ // Adjusts prompt detail level based on the user's skill profile.
4
+ // Expert users get concise responses; beginners get detailed explanations.
5
+ // ── Functions ───────────────────────────────────────────
6
+ export class AdaptiveContext {
7
+ /**
8
+ * Enrich a base prompt based on the user's profile.
9
+ * - If all domains are 'expert': prepend concise instructions.
10
+ * - If any domain is 'beginner': prepend detailed instructions.
11
+ * - Default: return prompt unmodified.
12
+ */
13
+ enrichPrompt(basePrompt, profile) {
14
+ const level = this.getDetailLevel(profile);
15
+ switch (level) {
16
+ case 'concise':
17
+ return `Be concise. Skip basics.\n\n${basePrompt}`;
18
+ case 'detailed':
19
+ return `Explain in detail with examples.\n\n${basePrompt}`;
20
+ default:
21
+ return basePrompt;
22
+ }
23
+ }
24
+ /**
25
+ * Determine the appropriate detail level from a user profile.
26
+ * - 'concise': all domains are expert level
27
+ * - 'detailed': any domain is beginner level
28
+ * - 'normal': default / mixed intermediate
29
+ */
30
+ getDetailLevel(profile) {
31
+ const domains = profile.skillDomains;
32
+ if (domains.size === 0)
33
+ return 'normal';
34
+ const levels = Array.from(domains.values());
35
+ // If any domain is beginner, give detailed responses
36
+ if (levels.some(l => l === 'beginner')) {
37
+ return 'detailed';
38
+ }
39
+ // If ALL domains are expert, be concise
40
+ if (levels.every(l => l === 'expert')) {
41
+ return 'concise';
42
+ }
43
+ return 'normal';
44
+ }
45
+ }
46
+ //# sourceMappingURL=adaptive-context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adaptive-context.js","sourceRoot":"","sources":["../../src/user-model/adaptive-context.ts"],"names":[],"mappings":"AAAA,kEAAkE;AAClE,EAAE;AACF,iEAAiE;AACjE,2EAA2E;AAQ3E,2DAA2D;AAE3D,MAAM,OAAO,eAAe;IAC1B;;;;;OAKG;IACH,YAAY,CAAC,UAAkB,EAAE,OAAoB;QACnD,MAAM,KAAK,GAAG,IAAI,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC;QAE3C,QAAQ,KAAK,EAAE,CAAC;YACd,KAAK,SAAS;gBACZ,OAAO,+BAA+B,UAAU,EAAE,CAAC;YACrD,KAAK,UAAU;gBACb,OAAO,uCAAuC,UAAU,EAAE,CAAC;YAC7D;gBACE,OAAO,UAAU,CAAC;QACtB,CAAC;IACH,CAAC;IAED;;;;;OAKG;IACH,cAAc,CAAC,OAAoB;QACjC,MAAM,OAAO,GAAG,OAAO,CAAC,YAAY,CAAC;QAErC,IAAI,OAAO,CAAC,IAAI,KAAK,CAAC;YAAE,OAAO,QAAQ,CAAC;QAExC,MAAM,MAAM,GAAiB,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;QAE1D,qDAAqD;QACrD,IAAI,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,KAAK,UAAU,CAAC,EAAE,CAAC;YACvC,OAAO,UAAU,CAAC;QACpB,CAAC;QAED,wCAAwC;QACxC,IAAI,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,KAAK,QAAQ,CAAC,EAAE,CAAC;YACtC,OAAO,SAAS,CAAC;QACnB,CAAC;QAED,OAAO,QAAQ,CAAC;IAClB,CAAC;CACF"}
@@ -0,0 +1,4 @@
1
+ export { UserModel, runUserModelMigration } from './user-model.js';
2
+ export { AdaptiveContext } from './adaptive-context.js';
3
+ export type { SkillLevel, UserProfile, UserModelConfig, UserModelStatus, } from './user-model.js';
4
+ export type { DetailLevel, } from './adaptive-context.js';
@@ -0,0 +1,3 @@
1
+ export { UserModel, runUserModelMigration } from './user-model.js';
2
+ export { AdaptiveContext } from './adaptive-context.js';
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/user-model/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AACnE,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC"}