@kernel.chat/kbot 2.3.1 → 2.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agent.d.ts.map +1 -1
- package/dist/agent.js +45 -22
- package/dist/agent.js.map +1 -1
- package/dist/auth.d.ts +2 -0
- package/dist/auth.d.ts.map +1 -1
- package/dist/auth.js +41 -12
- package/dist/auth.js.map +1 -1
- package/dist/auth.test.js +35 -37
- package/dist/auth.test.js.map +1 -1
- package/dist/cli.js +106 -6
- package/dist/cli.js.map +1 -1
- package/dist/cloud-sync.d.ts +19 -0
- package/dist/cloud-sync.d.ts.map +1 -0
- package/dist/cloud-sync.js +184 -0
- package/dist/cloud-sync.js.map +1 -0
- package/dist/context-manager.d.ts +55 -0
- package/dist/context-manager.d.ts.map +1 -0
- package/dist/context-manager.js +192 -0
- package/dist/context-manager.js.map +1 -0
- package/dist/embeddings.d.ts +40 -0
- package/dist/embeddings.d.ts.map +1 -0
- package/dist/embeddings.js +224 -0
- package/dist/embeddings.js.map +1 -0
- package/dist/learned-router.d.ts +54 -0
- package/dist/learned-router.d.ts.map +1 -0
- package/dist/learned-router.js +273 -0
- package/dist/learned-router.js.map +1 -0
- package/dist/learning.d.ts +1 -1
- package/dist/learning.d.ts.map +1 -1
- package/dist/learning.js +35 -20
- package/dist/learning.js.map +1 -1
- package/dist/learning.test.js +34 -43
- package/dist/learning.test.js.map +1 -1
- package/dist/permissions.d.ts.map +1 -1
- package/dist/permissions.js +15 -12
- package/dist/permissions.js.map +1 -1
- package/dist/plugins.d.ts.map +1 -1
- package/dist/plugins.js +30 -1
- package/dist/plugins.js.map +1 -1
- package/dist/prompt-cache.d.ts +53 -0
- package/dist/prompt-cache.d.ts.map +1 -0
- package/dist/prompt-cache.js +111 -0
- package/dist/prompt-cache.js.map +1 -0
- package/dist/serve.d.ts +8 -0
- package/dist/serve.d.ts.map +1 -0
- package/dist/serve.js +159 -0
- package/dist/serve.js.map +1 -0
- package/dist/streaming.d.ts.map +1 -1
- package/dist/streaming.js +6 -1
- package/dist/streaming.js.map +1 -1
- package/dist/tools/files.d.ts.map +1 -1
- package/dist/tools/files.js +16 -7
- package/dist/tools/files.js.map +1 -1
- package/dist/tools/index.test.js +39 -46
- package/dist/tools/index.test.js.map +1 -1
- package/dist/ui.d.ts.map +1 -1
- package/dist/ui.js +39 -2
- package/dist/ui.js.map +1 -1
- package/dist/updater.d.ts +11 -1
- package/dist/updater.d.ts.map +1 -1
- package/dist/updater.js +110 -17
- package/dist/updater.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
// K:BOT Embeddings — Semantic Similarity via Ollama
|
|
2
|
+
//
|
|
3
|
+
// Based on research showing embeddings-based matching outperforms
|
|
4
|
+
// keyword Jaccard similarity for solution retrieval and pattern matching.
|
|
5
|
+
//
|
|
6
|
+
// Uses Ollama's nomic-embed-text model (or falls back to Jaccard).
|
|
7
|
+
// Maintains a local cache (~1000 entries) to avoid redundant embedding calls.
|
|
8
|
+
import { homedir } from 'node:os';
|
|
9
|
+
import { join } from 'node:path';
|
|
10
|
+
import { existsSync, readFileSync, writeFileSync, mkdirSync } from 'node:fs';
|
|
11
|
+
const CACHE_DIR = join(homedir(), '.kbot', 'memory');
|
|
12
|
+
const CACHE_FILE = join(CACHE_DIR, 'embedding-cache.json');
|
|
13
|
+
const MAX_CACHE_SIZE = 1000;
|
|
14
|
+
const OLLAMA_URL = 'http://127.0.0.1:11434';
|
|
15
|
+
const EMBED_MODEL = 'nomic-embed-text';
|
|
16
|
+
let cache = new Map();
|
|
17
|
+
let ollamaAvailable = null;
|
|
18
|
+
let cacheLoaded = false;
|
|
19
|
+
function ensureDir() {
|
|
20
|
+
if (!existsSync(CACHE_DIR))
|
|
21
|
+
mkdirSync(CACHE_DIR, { recursive: true });
|
|
22
|
+
}
|
|
23
|
+
function loadCache() {
|
|
24
|
+
if (cacheLoaded)
|
|
25
|
+
return;
|
|
26
|
+
cacheLoaded = true;
|
|
27
|
+
try {
|
|
28
|
+
if (existsSync(CACHE_FILE)) {
|
|
29
|
+
const data = JSON.parse(readFileSync(CACHE_FILE, 'utf-8'));
|
|
30
|
+
if (Array.isArray(data)) {
|
|
31
|
+
for (const entry of data) {
|
|
32
|
+
if (entry.text && entry.vector) {
|
|
33
|
+
cache.set(entry.text, entry);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
catch { /* start fresh */ }
|
|
40
|
+
}
|
|
41
|
+
/** Save cache to disk (debounced externally) */
|
|
42
|
+
export function saveEmbeddingCache() {
|
|
43
|
+
ensureDir();
|
|
44
|
+
const entries = Array.from(cache.values())
|
|
45
|
+
.sort((a, b) => b.created - a.created)
|
|
46
|
+
.slice(0, MAX_CACHE_SIZE);
|
|
47
|
+
try {
|
|
48
|
+
writeFileSync(CACHE_FILE, JSON.stringify(entries));
|
|
49
|
+
}
|
|
50
|
+
catch { /* non-critical */ }
|
|
51
|
+
}
|
|
52
|
+
/** Check if Ollama is running and has the embedding model */
|
|
53
|
+
async function checkOllama() {
|
|
54
|
+
if (ollamaAvailable !== null)
|
|
55
|
+
return ollamaAvailable;
|
|
56
|
+
try {
|
|
57
|
+
const res = await fetch(`${OLLAMA_URL}/api/tags`, {
|
|
58
|
+
signal: AbortSignal.timeout(2000),
|
|
59
|
+
});
|
|
60
|
+
if (!res.ok) {
|
|
61
|
+
ollamaAvailable = false;
|
|
62
|
+
return false;
|
|
63
|
+
}
|
|
64
|
+
const data = await res.json();
|
|
65
|
+
ollamaAvailable = data.models?.some(m => m.name.includes('nomic-embed')) ?? false;
|
|
66
|
+
return ollamaAvailable;
|
|
67
|
+
}
|
|
68
|
+
catch {
|
|
69
|
+
ollamaAvailable = false;
|
|
70
|
+
return false;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
/** Get embedding vector from Ollama */
|
|
74
|
+
async function getEmbedding(text) {
|
|
75
|
+
loadCache();
|
|
76
|
+
// Check cache first
|
|
77
|
+
const normalized = text.toLowerCase().trim().slice(0, 500);
|
|
78
|
+
const cached = cache.get(normalized);
|
|
79
|
+
if (cached)
|
|
80
|
+
return cached.vector;
|
|
81
|
+
// Check Ollama availability
|
|
82
|
+
if (!(await checkOllama()))
|
|
83
|
+
return null;
|
|
84
|
+
try {
|
|
85
|
+
const res = await fetch(`${OLLAMA_URL}/api/embed`, {
|
|
86
|
+
method: 'POST',
|
|
87
|
+
headers: { 'Content-Type': 'application/json' },
|
|
88
|
+
body: JSON.stringify({ model: EMBED_MODEL, input: normalized }),
|
|
89
|
+
signal: AbortSignal.timeout(5000),
|
|
90
|
+
});
|
|
91
|
+
if (!res.ok)
|
|
92
|
+
return null;
|
|
93
|
+
const data = await res.json();
|
|
94
|
+
const vector = data.embeddings?.[0];
|
|
95
|
+
if (!vector || vector.length === 0)
|
|
96
|
+
return null;
|
|
97
|
+
// Cache it
|
|
98
|
+
cache.set(normalized, { text: normalized, vector, created: Date.now() });
|
|
99
|
+
// Evict oldest if over limit
|
|
100
|
+
if (cache.size > MAX_CACHE_SIZE) {
|
|
101
|
+
const entries = Array.from(cache.entries())
|
|
102
|
+
.sort((a, b) => a[1].created - b[1].created);
|
|
103
|
+
const toDelete = entries.slice(0, entries.length - MAX_CACHE_SIZE);
|
|
104
|
+
for (const [key] of toDelete)
|
|
105
|
+
cache.delete(key);
|
|
106
|
+
}
|
|
107
|
+
return vector;
|
|
108
|
+
}
|
|
109
|
+
catch {
|
|
110
|
+
return null;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
/** Cosine similarity between two vectors */
|
|
114
|
+
function cosineSimilarity(a, b) {
|
|
115
|
+
if (a.length !== b.length || a.length === 0)
|
|
116
|
+
return 0;
|
|
117
|
+
let dotProduct = 0;
|
|
118
|
+
let normA = 0;
|
|
119
|
+
let normB = 0;
|
|
120
|
+
for (let i = 0; i < a.length; i++) {
|
|
121
|
+
dotProduct += a[i] * b[i];
|
|
122
|
+
normA += a[i] * a[i];
|
|
123
|
+
normB += b[i] * b[i];
|
|
124
|
+
}
|
|
125
|
+
const denom = Math.sqrt(normA) * Math.sqrt(normB);
|
|
126
|
+
return denom === 0 ? 0 : dotProduct / denom;
|
|
127
|
+
}
|
|
128
|
+
/** Jaccard similarity fallback (keyword-based) */
|
|
129
|
+
function jaccardSimilarity(a, b) {
|
|
130
|
+
const wordsA = new Set(a.toLowerCase().replace(/[^a-z0-9\s]/g, ' ').split(/\s+/).filter(w => w.length > 2));
|
|
131
|
+
const wordsB = new Set(b.toLowerCase().replace(/[^a-z0-9\s]/g, ' ').split(/\s+/).filter(w => w.length > 2));
|
|
132
|
+
if (wordsA.size === 0 || wordsB.size === 0)
|
|
133
|
+
return 0;
|
|
134
|
+
const intersection = [...wordsA].filter(w => wordsB.has(w)).length;
|
|
135
|
+
const union = new Set([...wordsA, ...wordsB]).size;
|
|
136
|
+
return union > 0 ? intersection / union : 0;
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Compute semantic similarity between two texts.
|
|
140
|
+
* Uses embeddings if Ollama is available, falls back to Jaccard.
|
|
141
|
+
*/
|
|
142
|
+
export async function semanticSimilarity(a, b) {
|
|
143
|
+
const vecA = await getEmbedding(a);
|
|
144
|
+
const vecB = await getEmbedding(b);
|
|
145
|
+
if (vecA && vecB) {
|
|
146
|
+
return cosineSimilarity(vecA, vecB);
|
|
147
|
+
}
|
|
148
|
+
// Fallback to Jaccard
|
|
149
|
+
return jaccardSimilarity(a, b);
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Find the best match from a list of candidates.
|
|
153
|
+
* Returns the candidate with highest similarity above the threshold.
|
|
154
|
+
*/
|
|
155
|
+
export async function findBestMatch(query, candidates, threshold = 0.5) {
|
|
156
|
+
let bestId = null;
|
|
157
|
+
let bestScore = 0;
|
|
158
|
+
// Try embeddings first
|
|
159
|
+
const queryVec = await getEmbedding(query);
|
|
160
|
+
for (const candidate of candidates) {
|
|
161
|
+
let score;
|
|
162
|
+
if (queryVec) {
|
|
163
|
+
const candidateVec = await getEmbedding(candidate.text);
|
|
164
|
+
score = candidateVec
|
|
165
|
+
? cosineSimilarity(queryVec, candidateVec)
|
|
166
|
+
: jaccardSimilarity(query, candidate.text);
|
|
167
|
+
}
|
|
168
|
+
else {
|
|
169
|
+
score = jaccardSimilarity(query, candidate.text);
|
|
170
|
+
}
|
|
171
|
+
if (score > bestScore && score >= threshold) {
|
|
172
|
+
bestScore = score;
|
|
173
|
+
bestId = candidate.id;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
return bestId ? { id: bestId, score: bestScore } : null;
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Rank candidates by semantic similarity to query.
|
|
180
|
+
* Returns sorted array with scores.
|
|
181
|
+
*/
|
|
182
|
+
export async function rankBySimilarity(query, candidates, topK = 5) {
|
|
183
|
+
const queryVec = await getEmbedding(query);
|
|
184
|
+
const scored = [];
|
|
185
|
+
for (const candidate of candidates) {
|
|
186
|
+
let score;
|
|
187
|
+
if (queryVec) {
|
|
188
|
+
const candidateVec = await getEmbedding(candidate.text);
|
|
189
|
+
score = candidateVec
|
|
190
|
+
? cosineSimilarity(queryVec, candidateVec)
|
|
191
|
+
: jaccardSimilarity(query, candidate.text);
|
|
192
|
+
}
|
|
193
|
+
else {
|
|
194
|
+
score = jaccardSimilarity(query, candidate.text);
|
|
195
|
+
}
|
|
196
|
+
scored.push({ id: candidate.id, score });
|
|
197
|
+
}
|
|
198
|
+
return scored
|
|
199
|
+
.sort((a, b) => b.score - a.score)
|
|
200
|
+
.slice(0, topK);
|
|
201
|
+
}
|
|
202
|
+
/** Warm the embedding cache with common queries (call on startup) */
|
|
203
|
+
export async function warmCache(texts) {
|
|
204
|
+
loadCache();
|
|
205
|
+
if (!(await checkOllama()))
|
|
206
|
+
return;
|
|
207
|
+
const uncached = texts.filter(t => !cache.has(t.toLowerCase().trim().slice(0, 500)));
|
|
208
|
+
// Warm up to 20 at a time to avoid hammering Ollama
|
|
209
|
+
for (const text of uncached.slice(0, 20)) {
|
|
210
|
+
await getEmbedding(text);
|
|
211
|
+
}
|
|
212
|
+
if (uncached.length > 0)
|
|
213
|
+
saveEmbeddingCache();
|
|
214
|
+
}
|
|
215
|
+
/** Check if embeddings are available (Ollama + nomic-embed-text) */
|
|
216
|
+
export async function isEmbeddingsAvailable() {
|
|
217
|
+
return checkOllama();
|
|
218
|
+
}
|
|
219
|
+
/** Get cache stats */
|
|
220
|
+
export function getCacheStats() {
|
|
221
|
+
loadCache();
|
|
222
|
+
return { size: cache.size, maxSize: MAX_CACHE_SIZE, available: ollamaAvailable };
|
|
223
|
+
}
|
|
224
|
+
//# sourceMappingURL=embeddings.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"embeddings.js","sourceRoot":"","sources":["../src/embeddings.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/** A recorded routing decision */
|
|
2
|
+
export interface RoutingRecord {
|
|
3
|
+
/** Normalized intent string */
|
|
4
|
+
intent: string;
|
|
5
|
+
/** Keywords extracted from the message */
|
|
6
|
+
keywords: string[];
|
|
7
|
+
/** Which agent was selected */
|
|
8
|
+
agent: string;
|
|
9
|
+
/** How the route was determined: 'learned' | 'keyword' | 'category' | 'llm' */
|
|
10
|
+
method: 'learned' | 'keyword' | 'category' | 'llm';
|
|
11
|
+
/** Was the routing successful (user didn't override) */
|
|
12
|
+
success: boolean;
|
|
13
|
+
/** Times this exact route has been used */
|
|
14
|
+
count: number;
|
|
15
|
+
/** Last used */
|
|
16
|
+
lastUsed: string;
|
|
17
|
+
}
|
|
18
|
+
/** Routing result from the cascaded classifier */
|
|
19
|
+
export interface RouteResult {
|
|
20
|
+
/** Selected agent */
|
|
21
|
+
agent: string;
|
|
22
|
+
/** Confidence 0-1 */
|
|
23
|
+
confidence: number;
|
|
24
|
+
/** Which cascade level resolved it */
|
|
25
|
+
method: 'learned' | 'keyword' | 'category' | 'llm';
|
|
26
|
+
/** Was this a cache hit (no LLM needed) */
|
|
27
|
+
cached: boolean;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Cascaded route — try each level in order, return first confident match.
|
|
31
|
+
*
|
|
32
|
+
* Level 1: Exact intent lookup (from history)
|
|
33
|
+
* Level 2: Keyword voting (weighted by history frequency)
|
|
34
|
+
* Level 3: Category pattern matching
|
|
35
|
+
* Level 4: Returns null — caller should use LLM
|
|
36
|
+
*/
|
|
37
|
+
export declare function learnedRoute(message: string): RouteResult | null;
|
|
38
|
+
/**
|
|
39
|
+
* Record a routing decision for future learning.
|
|
40
|
+
* Call this after the agent responds (or when user overrides).
|
|
41
|
+
*/
|
|
42
|
+
export declare function recordRoute(message: string, agent: string, method: RouteResult['method'], success?: boolean): void;
|
|
43
|
+
/** Get routing stats */
|
|
44
|
+
export declare function getRoutingStats(): {
|
|
45
|
+
totalRoutes: number;
|
|
46
|
+
learnedHits: number;
|
|
47
|
+
keywordHits: number;
|
|
48
|
+
categoryHits: number;
|
|
49
|
+
llmFallbacks: number;
|
|
50
|
+
cacheHitRate: string;
|
|
51
|
+
};
|
|
52
|
+
/** Override a route (user correction) */
|
|
53
|
+
export declare function overrideRoute(message: string, correctAgent: string): void;
|
|
54
|
+
//# sourceMappingURL=learned-router.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"learned-router.d.ts","sourceRoot":"","sources":["../src/learned-router.ts"],"names":[],"mappings":"AAqBA,kCAAkC;AAClC,MAAM,WAAW,aAAa;IAC5B,+BAA+B;IAC/B,MAAM,EAAE,MAAM,CAAA;IACd,0CAA0C;IAC1C,QAAQ,EAAE,MAAM,EAAE,CAAA;IAClB,+BAA+B;IAC/B,KAAK,EAAE,MAAM,CAAA;IACb,+EAA+E;IAC/E,MAAM,EAAE,SAAS,GAAG,SAAS,GAAG,UAAU,GAAG,KAAK,CAAA;IAClD,wDAAwD;IACxD,OAAO,EAAE,OAAO,CAAA;IAChB,2CAA2C;IAC3C,KAAK,EAAE,MAAM,CAAA;IACb,gBAAgB;IAChB,QAAQ,EAAE,MAAM,CAAA;CACjB;AAED,kDAAkD;AAClD,MAAM,WAAW,WAAW;IAC1B,qBAAqB;IACrB,KAAK,EAAE,MAAM,CAAA;IACb,qBAAqB;IACrB,UAAU,EAAE,MAAM,CAAA;IAClB,sCAAsC;IACtC,MAAM,EAAE,SAAS,GAAG,SAAS,GAAG,UAAU,GAAG,KAAK,CAAA;IAClD,2CAA2C;IAC3C,MAAM,EAAE,OAAO,CAAA;CAChB;AA4FD;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI,CA8DhE;AAED;;;GAGG;AACH,wBAAgB,WAAW,CACzB,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,WAAW,CAAC,QAAQ,CAAC,EAC7B,OAAO,GAAE,OAAc,GACtB,IAAI,CA0CN;AA0BD,wBAAwB;AACxB,wBAAgB,eAAe,IAAI;IACjC,WAAW,EAAE,MAAM,CAAA;IACnB,WAAW,EAAE,MAAM,CAAA;IACnB,WAAW,EAAE,MAAM,CAAA;IACnB,YAAY,EAAE,MAAM,CAAA;IACpB,YAAY,EAAE,MAAM,CAAA;IACpB,YAAY,EAAE,MAAM,CAAA;CACrB,CAmBA;AAED,yCAAyC;AACzC,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,IAAI,CAYzE"}
|
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
// K:BOT Learned Router — MasRouter-style Cascaded Routing
|
|
2
|
+
//
|
|
3
|
+
// Based on MasRouter (ACL 2025): instead of calling an LLM to classify
|
|
4
|
+
// intent every time, learn from actual routing outcomes and cascade
|
|
5
|
+
// through increasingly expensive classifiers:
|
|
6
|
+
//
|
|
7
|
+
// 1. Exact intent match (free, instant)
|
|
8
|
+
// 2. Keyword voting (free, instant)
|
|
9
|
+
// 3. Category fallback (free, instant)
|
|
10
|
+
// 4. LLM classifier (expensive, last resort)
|
|
11
|
+
//
|
|
12
|
+
// Over time, steps 1-3 handle 90%+ of messages without any API call.
|
|
13
|
+
import { homedir } from 'node:os';
|
|
14
|
+
import { join } from 'node:path';
|
|
15
|
+
import { existsSync, readFileSync, writeFileSync, mkdirSync } from 'node:fs';
|
|
16
|
+
const ROUTER_DIR = join(homedir(), '.kbot', 'memory');
|
|
17
|
+
const HISTORY_FILE = join(ROUTER_DIR, 'routing-history.json');
|
|
18
|
+
const MAX_HISTORY = 500;
|
|
19
|
+
function ensureDir() {
|
|
20
|
+
if (!existsSync(ROUTER_DIR))
|
|
21
|
+
mkdirSync(ROUTER_DIR, { recursive: true });
|
|
22
|
+
}
|
|
23
|
+
let history = [];
|
|
24
|
+
let loaded = false;
|
|
25
|
+
function loadHistory() {
|
|
26
|
+
if (loaded)
|
|
27
|
+
return;
|
|
28
|
+
loaded = true;
|
|
29
|
+
try {
|
|
30
|
+
if (existsSync(HISTORY_FILE)) {
|
|
31
|
+
history = JSON.parse(readFileSync(HISTORY_FILE, 'utf-8'));
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
catch {
|
|
35
|
+
history = [];
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
function saveHistory() {
|
|
39
|
+
ensureDir();
|
|
40
|
+
try {
|
|
41
|
+
writeFileSync(HISTORY_FILE, JSON.stringify(history.slice(0, MAX_HISTORY), null, 2));
|
|
42
|
+
}
|
|
43
|
+
catch { /* non-critical */ }
|
|
44
|
+
}
|
|
45
|
+
// ── Stop words for normalization ──
|
|
46
|
+
const STOP_WORDS = new Set([
|
|
47
|
+
'the', 'a', 'an', 'is', 'are', 'was', 'were', 'be', 'been', 'being',
|
|
48
|
+
'have', 'has', 'had', 'do', 'does', 'did', 'will', 'would', 'could',
|
|
49
|
+
'should', 'may', 'might', 'shall', 'can', 'to', 'of', 'in', 'for',
|
|
50
|
+
'on', 'with', 'at', 'by', 'from', 'it', 'this', 'that', 'these',
|
|
51
|
+
'those', 'i', 'me', 'my', 'we', 'you', 'your', 'he', 'she', 'they',
|
|
52
|
+
'them', 'and', 'or', 'but', 'not', 'so', 'if', 'then', 'please',
|
|
53
|
+
]);
|
|
54
|
+
function normalizeIntent(message) {
|
|
55
|
+
return message.toLowerCase()
|
|
56
|
+
.replace(/[^a-z0-9\s]/g, ' ')
|
|
57
|
+
.split(/\s+/)
|
|
58
|
+
.filter(w => w.length > 2 && !STOP_WORDS.has(w))
|
|
59
|
+
.join(' ');
|
|
60
|
+
}
|
|
61
|
+
// ── Agent keyword maps ──
|
|
62
|
+
// These are the learned keyword→agent associations. They start with
|
|
63
|
+
// reasonable defaults and improve as routing history accumulates.
|
|
64
|
+
const AGENT_KEYWORDS = {
|
|
65
|
+
coder: [
|
|
66
|
+
'code', 'function', 'class', 'bug', 'error', 'fix', 'implement', 'build',
|
|
67
|
+
'create', 'write', 'typescript', 'javascript', 'python', 'rust', 'react',
|
|
68
|
+
'component', 'test', 'refactor', 'api', 'endpoint', 'database', 'sql',
|
|
69
|
+
'npm', 'install', 'package', 'import', 'export', 'async', 'type',
|
|
70
|
+
'interface', 'module', 'compile', 'lint', 'debug', 'crash', 'exception',
|
|
71
|
+
],
|
|
72
|
+
researcher: [
|
|
73
|
+
'research', 'find', 'search', 'compare', 'alternatives', 'benchmark',
|
|
74
|
+
'documentation', 'docs', 'article', 'paper', 'study', 'analyze',
|
|
75
|
+
'investigate', 'explore', 'discover', 'learn', 'understand', 'explain',
|
|
76
|
+
'difference', 'versus', 'pros', 'cons', 'tradeoff', 'best practice',
|
|
77
|
+
],
|
|
78
|
+
writer: [
|
|
79
|
+
'write', 'draft', 'blog', 'post', 'article', 'email', 'message',
|
|
80
|
+
'readme', 'documentation', 'changelog', 'announcement', 'copy',
|
|
81
|
+
'content', 'marketing', 'social', 'tweet', 'thread', 'newsletter',
|
|
82
|
+
'story', 'essay', 'summary', 'summarize', 'edit', 'proofread',
|
|
83
|
+
],
|
|
84
|
+
analyst: [
|
|
85
|
+
'analyze', 'strategy', 'plan', 'architecture', 'design', 'review',
|
|
86
|
+
'audit', 'evaluate', 'assess', 'optimize', 'performance', 'cost',
|
|
87
|
+
'pricing', 'business', 'metric', 'dashboard', 'report', 'insight',
|
|
88
|
+
'decision', 'tradeoff', 'priority', 'roadmap',
|
|
89
|
+
],
|
|
90
|
+
kernel: [
|
|
91
|
+
'hey', 'hello', 'hi', 'thanks', 'help', 'what', 'how', 'why',
|
|
92
|
+
'general', 'chat', 'talk', 'opinion', 'think', 'feel', 'advice',
|
|
93
|
+
],
|
|
94
|
+
};
|
|
95
|
+
// ── Category patterns (broader than keywords) ──
|
|
96
|
+
const CATEGORY_PATTERNS = [
|
|
97
|
+
{ pattern: /\b(fix|bug|error|crash|broken|fail|debug|issue)\b/i, agent: 'coder', confidence: 0.7 },
|
|
98
|
+
{ pattern: /\b(create|build|implement|scaffold|generate|add|new)\b.*\b(function|component|file|module|api|page|route)\b/i, agent: 'coder', confidence: 0.75 },
|
|
99
|
+
{ pattern: /\b(refactor|clean|reorganize|restructure|simplify|extract)\b/i, agent: 'coder', confidence: 0.7 },
|
|
100
|
+
{ pattern: /\b(test|spec|coverage|assert|mock|stub)\b/i, agent: 'coder', confidence: 0.65 },
|
|
101
|
+
{ pattern: /\b(deploy|ship|release|publish|ci|cd|pipeline)\b/i, agent: 'coder', confidence: 0.6 },
|
|
102
|
+
{ pattern: /\b(research|find|compare|benchmark|alternative|best)\b/i, agent: 'researcher', confidence: 0.6 },
|
|
103
|
+
{ pattern: /\b(write|draft|blog|post|article|email|newsletter|readme)\b/i, agent: 'writer', confidence: 0.65 },
|
|
104
|
+
{ pattern: /\b(analyze|strategy|plan|architecture|review|audit|evaluate)\b/i, agent: 'analyst', confidence: 0.6 },
|
|
105
|
+
];
|
|
106
|
+
/**
|
|
107
|
+
* Cascaded route — try each level in order, return first confident match.
|
|
108
|
+
*
|
|
109
|
+
* Level 1: Exact intent lookup (from history)
|
|
110
|
+
* Level 2: Keyword voting (weighted by history frequency)
|
|
111
|
+
* Level 3: Category pattern matching
|
|
112
|
+
* Level 4: Returns null — caller should use LLM
|
|
113
|
+
*/
|
|
114
|
+
export function learnedRoute(message) {
|
|
115
|
+
loadHistory();
|
|
116
|
+
const intent = normalizeIntent(message);
|
|
117
|
+
if (!intent)
|
|
118
|
+
return null;
|
|
119
|
+
// ── Level 1: Exact intent match ──
|
|
120
|
+
const exactMatch = history.find(h => h.intent === intent && h.success && h.count >= 2);
|
|
121
|
+
if (exactMatch) {
|
|
122
|
+
return {
|
|
123
|
+
agent: exactMatch.agent,
|
|
124
|
+
confidence: Math.min(0.95, 0.7 + (exactMatch.count * 0.05)),
|
|
125
|
+
method: 'learned',
|
|
126
|
+
cached: true,
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
// ── Level 2: Keyword voting ──
|
|
130
|
+
const intentWords = intent.split(' ');
|
|
131
|
+
const votes = {};
|
|
132
|
+
// Vote from built-in keyword maps
|
|
133
|
+
for (const [agent, keywords] of Object.entries(AGENT_KEYWORDS)) {
|
|
134
|
+
const matchCount = intentWords.filter(w => keywords.includes(w)).length;
|
|
135
|
+
if (matchCount > 0) {
|
|
136
|
+
votes[agent] = (votes[agent] || 0) + matchCount;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
// Boost votes from successful history
|
|
140
|
+
for (const record of history) {
|
|
141
|
+
if (!record.success)
|
|
142
|
+
continue;
|
|
143
|
+
const recordWords = new Set(record.intent.split(' '));
|
|
144
|
+
const overlap = intentWords.filter(w => recordWords.has(w)).length;
|
|
145
|
+
if (overlap >= 2) {
|
|
146
|
+
votes[record.agent] = (votes[record.agent] || 0) + overlap * 0.5;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
const topVote = Object.entries(votes).sort((a, b) => b[1] - a[1])[0];
|
|
150
|
+
if (topVote && topVote[1] >= 3) {
|
|
151
|
+
const totalVotes = Object.values(votes).reduce((a, b) => a + b, 0);
|
|
152
|
+
const confidence = topVote[1] / totalVotes;
|
|
153
|
+
if (confidence >= 0.5) {
|
|
154
|
+
return {
|
|
155
|
+
agent: topVote[0],
|
|
156
|
+
confidence: Math.min(0.85, confidence),
|
|
157
|
+
method: 'keyword',
|
|
158
|
+
cached: true,
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
// ── Level 3: Category pattern matching ──
|
|
163
|
+
for (const { pattern, agent, confidence } of CATEGORY_PATTERNS) {
|
|
164
|
+
if (pattern.test(message)) {
|
|
165
|
+
return { agent, confidence, method: 'category', cached: true };
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
// ── Level 4: No match — caller should use LLM ──
|
|
169
|
+
return null;
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Record a routing decision for future learning.
|
|
173
|
+
* Call this after the agent responds (or when user overrides).
|
|
174
|
+
*/
|
|
175
|
+
export function recordRoute(message, agent, method, success = true) {
|
|
176
|
+
loadHistory();
|
|
177
|
+
const intent = normalizeIntent(message);
|
|
178
|
+
if (!intent)
|
|
179
|
+
return;
|
|
180
|
+
const keywords = intent.split(' ');
|
|
181
|
+
const existing = history.find(h => h.intent === intent);
|
|
182
|
+
if (existing) {
|
|
183
|
+
if (success) {
|
|
184
|
+
existing.agent = agent;
|
|
185
|
+
existing.success = true;
|
|
186
|
+
existing.count++;
|
|
187
|
+
}
|
|
188
|
+
else {
|
|
189
|
+
// Failed route — decrease count but don't delete
|
|
190
|
+
existing.count = Math.max(0, existing.count - 1);
|
|
191
|
+
if (existing.count === 0)
|
|
192
|
+
existing.success = false;
|
|
193
|
+
}
|
|
194
|
+
existing.method = method;
|
|
195
|
+
existing.lastUsed = new Date().toISOString();
|
|
196
|
+
}
|
|
197
|
+
else {
|
|
198
|
+
history.push({
|
|
199
|
+
intent,
|
|
200
|
+
keywords,
|
|
201
|
+
agent,
|
|
202
|
+
method,
|
|
203
|
+
success,
|
|
204
|
+
count: 1,
|
|
205
|
+
lastUsed: new Date().toISOString(),
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
// Keep top records by count
|
|
209
|
+
history.sort((a, b) => b.count - a.count);
|
|
210
|
+
history = history.slice(0, MAX_HISTORY);
|
|
211
|
+
saveHistory();
|
|
212
|
+
// Update keyword maps from successful routes
|
|
213
|
+
if (success) {
|
|
214
|
+
updateKeywordMaps(keywords, agent);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
/** Dynamically grow keyword maps from observed routing */
|
|
218
|
+
function updateKeywordMaps(keywords, agent) {
|
|
219
|
+
if (!AGENT_KEYWORDS[agent])
|
|
220
|
+
return;
|
|
221
|
+
const existing = new Set(AGENT_KEYWORDS[agent]);
|
|
222
|
+
for (const kw of keywords) {
|
|
223
|
+
// Only add keywords that appear in multiple successful routes for this agent
|
|
224
|
+
if (kw.length > 3 && !existing.has(kw)) {
|
|
225
|
+
const kwRoutes = history.filter(h => h.success && h.agent === agent && h.keywords.includes(kw));
|
|
226
|
+
if (kwRoutes.length >= 3) {
|
|
227
|
+
AGENT_KEYWORDS[agent].push(kw);
|
|
228
|
+
existing.add(kw);
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
// Cap keyword lists
|
|
233
|
+
for (const agent of Object.keys(AGENT_KEYWORDS)) {
|
|
234
|
+
if (AGENT_KEYWORDS[agent].length > 100) {
|
|
235
|
+
AGENT_KEYWORDS[agent] = AGENT_KEYWORDS[agent].slice(0, 100);
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
/** Get routing stats */
|
|
240
|
+
export function getRoutingStats() {
|
|
241
|
+
loadHistory();
|
|
242
|
+
const learned = history.filter(h => h.method === 'learned').length;
|
|
243
|
+
const keyword = history.filter(h => h.method === 'keyword').length;
|
|
244
|
+
const category = history.filter(h => h.method === 'category').length;
|
|
245
|
+
const llm = history.filter(h => h.method === 'llm').length;
|
|
246
|
+
const total = history.length;
|
|
247
|
+
const cached = learned + keyword + category;
|
|
248
|
+
const rate = total > 0 ? Math.round((cached / total) * 100) : 0;
|
|
249
|
+
return {
|
|
250
|
+
totalRoutes: total,
|
|
251
|
+
learnedHits: learned,
|
|
252
|
+
keywordHits: keyword,
|
|
253
|
+
categoryHits: category,
|
|
254
|
+
llmFallbacks: llm,
|
|
255
|
+
cacheHitRate: `${rate}%`,
|
|
256
|
+
};
|
|
257
|
+
}
|
|
258
|
+
/** Override a route (user correction) */
|
|
259
|
+
export function overrideRoute(message, correctAgent) {
|
|
260
|
+
const intent = normalizeIntent(message);
|
|
261
|
+
const existing = history.find(h => h.intent === intent);
|
|
262
|
+
if (existing) {
|
|
263
|
+
existing.agent = correctAgent;
|
|
264
|
+
existing.success = true;
|
|
265
|
+
existing.count = Math.max(existing.count, 3); // Boost corrected routes
|
|
266
|
+
existing.lastUsed = new Date().toISOString();
|
|
267
|
+
}
|
|
268
|
+
else {
|
|
269
|
+
recordRoute(message, correctAgent, 'learned', true);
|
|
270
|
+
}
|
|
271
|
+
saveHistory();
|
|
272
|
+
}
|
|
273
|
+
//# sourceMappingURL=learned-router.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"learned-router.js","sourceRoot":"","sources":["../src/learned-router.ts"],"names":[],"mappings":"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"}
|
package/dist/learning.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/** Flush all pending writes immediately (call on exit) */
|
|
1
|
+
/** Flush all pending writes immediately (call on exit) — only saves dirty files */
|
|
2
2
|
export declare function flushPendingWrites(): void;
|
|
3
3
|
export interface CachedPattern {
|
|
4
4
|
/** Normalized intent (lowercase, stop-words removed) */
|
package/dist/learning.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"learning.d.ts","sourceRoot":"","sources":["../src/learning.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"learning.d.ts","sourceRoot":"","sources":["../src/learning.ts"],"names":[],"mappings":"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"}
|