@monoes/routing 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/capability-index.d.ts +15 -0
- package/dist/capability-index.d.ts.map +1 -0
- package/dist/capability-index.js +32 -0
- package/dist/capability-index.js.map +1 -0
- package/dist/cosine.d.ts +11 -0
- package/dist/cosine.d.ts.map +1 -0
- package/dist/cosine.js +41 -0
- package/dist/cosine.js.map +1 -0
- package/dist/encoder.d.ts +37 -0
- package/dist/encoder.d.ts.map +1 -0
- package/dist/encoder.js +75 -0
- package/dist/encoder.js.map +1 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +9 -0
- package/dist/index.js.map +1 -0
- package/dist/keyword-pre-filter.d.ts +44 -0
- package/dist/keyword-pre-filter.d.ts.map +1 -0
- package/dist/keyword-pre-filter.js +109 -0
- package/dist/keyword-pre-filter.js.map +1 -0
- package/dist/llm-fallback.d.ts +18 -0
- package/dist/llm-fallback.d.ts.map +1 -0
- package/dist/llm-fallback.js +76 -0
- package/dist/llm-fallback.js.map +1 -0
- package/dist/prompts/classify.d.ts +5 -0
- package/dist/prompts/classify.d.ts.map +1 -0
- package/dist/prompts/classify.js +25 -0
- package/dist/prompts/classify.js.map +1 -0
- package/dist/route-layer.d.ts +25 -0
- package/dist/route-layer.d.ts.map +1 -0
- package/dist/route-layer.js +129 -0
- package/dist/route-layer.js.map +1 -0
- package/dist/routes/core.route.d.ts +3 -0
- package/dist/routes/core.route.d.ts.map +1 -0
- package/dist/routes/core.route.js +106 -0
- package/dist/routes/core.route.js.map +1 -0
- package/dist/routes/design.route.d.ts +3 -0
- package/dist/routes/design.route.d.ts.map +1 -0
- package/dist/routes/design.route.js +94 -0
- package/dist/routes/design.route.js.map +1 -0
- package/dist/routes/engineering.route.d.ts +3 -0
- package/dist/routes/engineering.route.d.ts.map +1 -0
- package/dist/routes/engineering.route.js +191 -0
- package/dist/routes/engineering.route.js.map +1 -0
- package/dist/routes/game-dev.route.d.ts +3 -0
- package/dist/routes/game-dev.route.d.ts.map +1 -0
- package/dist/routes/game-dev.route.js +109 -0
- package/dist/routes/game-dev.route.js.map +1 -0
- package/dist/routes/index.d.ts +13 -0
- package/dist/routes/index.d.ts.map +1 -0
- package/dist/routes/index.js +31 -0
- package/dist/routes/index.js.map +1 -0
- package/dist/routes/marketing.route.d.ts +3 -0
- package/dist/routes/marketing.route.d.ts.map +1 -0
- package/dist/routes/marketing.route.js +94 -0
- package/dist/routes/marketing.route.js.map +1 -0
- package/dist/routes/product.route.d.ts +3 -0
- package/dist/routes/product.route.d.ts.map +1 -0
- package/dist/routes/product.route.js +75 -0
- package/dist/routes/product.route.js.map +1 -0
- package/dist/routes/security.route.d.ts +3 -0
- package/dist/routes/security.route.d.ts.map +1 -0
- package/dist/routes/security.route.js +101 -0
- package/dist/routes/security.route.js.map +1 -0
- package/dist/routes/specialized.route.d.ts +3 -0
- package/dist/routes/specialized.route.d.ts.map +1 -0
- package/dist/routes/specialized.route.js +107 -0
- package/dist/routes/specialized.route.js.map +1 -0
- package/dist/routes/testing.route.d.ts +3 -0
- package/dist/routes/testing.route.d.ts.map +1 -0
- package/dist/routes/testing.route.js +115 -0
- package/dist/routes/testing.route.js.map +1 -0
- package/dist/types.d.ts +86 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +30 -0
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { Route } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Build a compact text index of all agent capabilities for LLM classification.
|
|
4
|
+
* Each entry: "<agentSlug>: <description>"
|
|
5
|
+
* Total output stays under MAX_INDEX_CHARS to fit in a single LLM prompt.
|
|
6
|
+
*/
|
|
7
|
+
export declare function buildCapabilityIndex(routes: Route[]): string;
|
|
8
|
+
/**
|
|
9
|
+
* Build a compact list of the top-N candidate agents by semantic score for hint injection.
|
|
10
|
+
*/
|
|
11
|
+
export declare function buildCandidateHints(scores: Array<{
|
|
12
|
+
agentSlug: string;
|
|
13
|
+
score: number;
|
|
14
|
+
}>, topN?: number): string;
|
|
15
|
+
//# sourceMappingURL=capability-index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"capability-index.d.ts","sourceRoot":"","sources":["../src/capability-index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAInC;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,CAgB5D;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,KAAK,CAAC;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,EACnD,IAAI,SAAI,GACP,MAAM,CAKR"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
const MAX_INDEX_CHARS = 8000;
|
|
2
|
+
/**
|
|
3
|
+
* Build a compact text index of all agent capabilities for LLM classification.
|
|
4
|
+
* Each entry: "<agentSlug>: <description>"
|
|
5
|
+
* Total output stays under MAX_INDEX_CHARS to fit in a single LLM prompt.
|
|
6
|
+
*/
|
|
7
|
+
export function buildCapabilityIndex(routes) {
|
|
8
|
+
const lines = [];
|
|
9
|
+
for (const route of routes) {
|
|
10
|
+
const description = route.description ?? route.utterances[0] ?? route.name;
|
|
11
|
+
lines.push(`${route.agentSlug}: ${description}`);
|
|
12
|
+
}
|
|
13
|
+
let index = lines.join('\n');
|
|
14
|
+
if (index.length > MAX_INDEX_CHARS) {
|
|
15
|
+
const trimmedLines = routes.map(r => {
|
|
16
|
+
const desc = (r.description ?? r.utterances[0] ?? r.name).slice(0, 80);
|
|
17
|
+
return `${r.agentSlug}: ${desc}`;
|
|
18
|
+
});
|
|
19
|
+
index = trimmedLines.join('\n').slice(0, MAX_INDEX_CHARS);
|
|
20
|
+
}
|
|
21
|
+
return index;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Build a compact list of the top-N candidate agents by semantic score for hint injection.
|
|
25
|
+
*/
|
|
26
|
+
export function buildCandidateHints(scores, topN = 3) {
|
|
27
|
+
return scores
|
|
28
|
+
.slice(0, topN)
|
|
29
|
+
.map(s => `- ${s.agentSlug} (similarity: ${s.score.toFixed(3)})`)
|
|
30
|
+
.join('\n');
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=capability-index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"capability-index.js","sourceRoot":"","sources":["../src/capability-index.ts"],"names":[],"mappings":"AAEA,MAAM,eAAe,GAAG,IAAI,CAAC;AAE7B;;;;GAIG;AACH,MAAM,UAAU,oBAAoB,CAAC,MAAe;IAClD,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,MAAM,WAAW,GAAG,KAAK,CAAC,WAAW,IAAI,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,IAAI,CAAC;QAC3E,KAAK,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,SAAS,KAAK,WAAW,EAAE,CAAC,CAAC;IACnD,CAAC;IAED,IAAI,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC7B,IAAI,KAAK,CAAC,MAAM,GAAG,eAAe,EAAE,CAAC;QACnC,MAAM,YAAY,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE;YAClC,MAAM,IAAI,GAAG,CAAC,CAAC,CAAC,WAAW,IAAI,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YACvE,OAAO,GAAG,CAAC,CAAC,SAAS,KAAK,IAAI,EAAE,CAAC;QACnC,CAAC,CAAC,CAAC;QACH,KAAK,GAAG,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,eAAe,CAAC,CAAC;IAC5D,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,mBAAmB,CACjC,MAAmD,EACnD,IAAI,GAAG,CAAC;IAER,OAAO,MAAM;SACV,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC;SACd,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,SAAS,iBAAiB,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC;SAChE,IAAI,CAAC,IAAI,CAAC,CAAC;AAChB,CAAC"}
|
package/dist/cosine.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Compute cosine similarity between two vectors.
|
|
3
|
+
* Returns a value in [-1, 1], where 1 = identical direction.
|
|
4
|
+
*/
|
|
5
|
+
export declare function cosineSimilarity(a: number[], b: number[]): number;
|
|
6
|
+
/**
|
|
7
|
+
* Compute the mean centroid of a list of vectors.
|
|
8
|
+
* All vectors must have the same dimensionality.
|
|
9
|
+
*/
|
|
10
|
+
export declare function computeCentroid(vectors: number[][]): number[];
|
|
11
|
+
//# sourceMappingURL=cosine.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cosine.d.ts","sourceRoot":"","sources":["../src/cosine.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,MAAM,EAAE,GAAG,MAAM,CAejE;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,GAAG,MAAM,EAAE,CAa7D"}
|
package/dist/cosine.js
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Compute cosine similarity between two vectors.
|
|
3
|
+
* Returns a value in [-1, 1], where 1 = identical direction.
|
|
4
|
+
*/
|
|
5
|
+
export function cosineSimilarity(a, b) {
|
|
6
|
+
if (a.length !== b.length) {
|
|
7
|
+
throw new Error(`Vector length mismatch: ${a.length} vs ${b.length}`);
|
|
8
|
+
}
|
|
9
|
+
let dot = 0;
|
|
10
|
+
let normA = 0;
|
|
11
|
+
let normB = 0;
|
|
12
|
+
for (let i = 0; i < a.length; i++) {
|
|
13
|
+
dot += a[i] * b[i];
|
|
14
|
+
normA += a[i] * a[i];
|
|
15
|
+
normB += b[i] * b[i];
|
|
16
|
+
}
|
|
17
|
+
const denominator = Math.sqrt(normA) * Math.sqrt(normB);
|
|
18
|
+
if (denominator === 0)
|
|
19
|
+
return 0;
|
|
20
|
+
return dot / denominator;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Compute the mean centroid of a list of vectors.
|
|
24
|
+
* All vectors must have the same dimensionality.
|
|
25
|
+
*/
|
|
26
|
+
export function computeCentroid(vectors) {
|
|
27
|
+
if (vectors.length === 0)
|
|
28
|
+
throw new Error('Cannot compute centroid of empty array');
|
|
29
|
+
const dim = vectors[0].length;
|
|
30
|
+
const centroid = new Array(dim).fill(0);
|
|
31
|
+
for (const vec of vectors) {
|
|
32
|
+
for (let i = 0; i < dim; i++) {
|
|
33
|
+
centroid[i] += vec[i];
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
for (let i = 0; i < dim; i++) {
|
|
37
|
+
centroid[i] /= vectors.length;
|
|
38
|
+
}
|
|
39
|
+
return centroid;
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=cosine.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cosine.js","sourceRoot":"","sources":["../src/cosine.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAAC,CAAW,EAAE,CAAW;IACvD,IAAI,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,MAAM,EAAE,CAAC;QAC1B,MAAM,IAAI,KAAK,CAAC,2BAA2B,CAAC,CAAC,MAAM,OAAO,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC;IACxE,CAAC;IACD,IAAI,GAAG,GAAG,CAAC,CAAC;IACZ,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAClC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QACnB,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QACrB,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IACvB,CAAC;IACD,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACxD,IAAI,WAAW,KAAK,CAAC;QAAE,OAAO,CAAC,CAAC;IAChC,OAAO,GAAG,GAAG,WAAW,CAAC;AAC3B,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,eAAe,CAAC,OAAmB;IACjD,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,wCAAwC,CAAC,CAAC;IACpF,MAAM,GAAG,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;IAC9B,MAAM,QAAQ,GAAG,IAAI,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACxC,KAAK,MAAM,GAAG,IAAI,OAAO,EAAE,CAAC;QAC1B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC;YAC7B,QAAQ,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC;QACxB,CAAC;IACH,CAAC;IACD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC;QAC7B,QAAQ,CAAC,CAAC,CAAC,IAAI,OAAO,CAAC,MAAM,CAAC;IAChC,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
export interface Encoder {
|
|
2
|
+
encode(text: string): Promise<number[]>;
|
|
3
|
+
encodeAll(texts: string[]): Promise<number[][]>;
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* Local encoder that produces deterministic pseudo-embeddings from text.
|
|
7
|
+
* Uses n-gram hashing to spread tokens across a fixed-dimensional vector.
|
|
8
|
+
* NOTE: Real semantic routing requires a real embedding model.
|
|
9
|
+
* In production, replace with HNSWEncoder backed by a proper embedding model.
|
|
10
|
+
*/
|
|
11
|
+
export declare class LocalEncoder implements Encoder {
|
|
12
|
+
private readonly DIM;
|
|
13
|
+
private cache;
|
|
14
|
+
encode(text: string): Promise<number[]>;
|
|
15
|
+
encodeAll(texts: string[]): Promise<number[][]>;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Production encoder backed by a real embedding model.
|
|
19
|
+
*
|
|
20
|
+
* The model is injected by the host (the CLI wires in a local
|
|
21
|
+
* `@huggingface/transformers` feature-extraction pipeline) so this package
|
|
22
|
+
* carries no model dependency. When no embedder is injected it degrades to the
|
|
23
|
+
* deterministic {@link LocalEncoder}.
|
|
24
|
+
*/
|
|
25
|
+
export declare class HNSWEncoder implements Encoder {
|
|
26
|
+
private fallback;
|
|
27
|
+
private embed?;
|
|
28
|
+
/**
|
|
29
|
+
* @param embed Optional real embedding function. When provided it is used
|
|
30
|
+
* exclusively — the hash-based LocalEncoder is NOT mixed in, since combining
|
|
31
|
+
* vectors of different dimensionality would break cosine comparison.
|
|
32
|
+
*/
|
|
33
|
+
constructor(embed?: (text: string) => Promise<number[]>);
|
|
34
|
+
encode(text: string): Promise<number[]>;
|
|
35
|
+
encodeAll(texts: string[]): Promise<number[][]>;
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=encoder.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"encoder.d.ts","sourceRoot":"","sources":["../src/encoder.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,OAAO;IACtB,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IACxC,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;CACjD;AAED;;;;;GAKG;AACH,qBAAa,YAAa,YAAW,OAAO;IAC1C,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAO;IAC3B,OAAO,CAAC,KAAK,CAA+B;IAEtC,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CA6B5C;IAEK,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAEpD;CACF;AAED;;;;;;;GAOG;AACH,qBAAa,WAAY,YAAW,OAAO;IACzC,OAAO,CAAC,QAAQ,CAAsB;IACtC,OAAO,CAAC,KAAK,CAAC,CAAsC;IAEpD;;;;OAIG;IACH,YAAY,KAAK,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,EAAE,CAAC,EAEtD;IAEK,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAE5C;IAEK,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAOpD;CACF"}
|
package/dist/encoder.js
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { createHash } from 'crypto';
|
|
2
|
+
/**
|
|
3
|
+
* Local encoder that produces deterministic pseudo-embeddings from text.
|
|
4
|
+
* Uses n-gram hashing to spread tokens across a fixed-dimensional vector.
|
|
5
|
+
* NOTE: Real semantic routing requires a real embedding model.
|
|
6
|
+
* In production, replace with HNSWEncoder backed by a proper embedding model.
|
|
7
|
+
*/
|
|
8
|
+
export class LocalEncoder {
|
|
9
|
+
DIM = 256;
|
|
10
|
+
cache = new Map();
|
|
11
|
+
async encode(text) {
|
|
12
|
+
const key = createHash('sha256').update(text.toLowerCase().trim()).digest('hex');
|
|
13
|
+
if (this.cache.has(key))
|
|
14
|
+
return this.cache.get(key);
|
|
15
|
+
const vector = new Array(this.DIM).fill(0);
|
|
16
|
+
const words = text.toLowerCase().split(/\s+/);
|
|
17
|
+
// Unigrams
|
|
18
|
+
for (const word of words) {
|
|
19
|
+
const hash = createHash('md5').update(word).digest();
|
|
20
|
+
for (let i = 0; i < Math.min(hash.length, this.DIM); i++) {
|
|
21
|
+
vector[i % this.DIM] += (hash[i] - 128) / 128;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
// Bigrams for better phrase sensitivity
|
|
25
|
+
for (let i = 0; i < words.length - 1; i++) {
|
|
26
|
+
const bigram = `${words[i]} ${words[i + 1]}`;
|
|
27
|
+
const hash = createHash('md5').update(bigram).digest();
|
|
28
|
+
for (let j = 0; j < Math.min(hash.length, this.DIM); j++) {
|
|
29
|
+
vector[(j + this.DIM / 2) % this.DIM] += (hash[j] - 128) / 128 * 0.5;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
// L2 normalize
|
|
33
|
+
const norm = Math.sqrt(vector.reduce((s, v) => s + v * v, 0)) || 1;
|
|
34
|
+
const normalized = vector.map(v => v / norm);
|
|
35
|
+
this.cache.set(key, normalized);
|
|
36
|
+
return normalized;
|
|
37
|
+
}
|
|
38
|
+
async encodeAll(texts) {
|
|
39
|
+
return Promise.all(texts.map(t => this.encode(t)));
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Production encoder backed by a real embedding model.
|
|
44
|
+
*
|
|
45
|
+
* The model is injected by the host (the CLI wires in a local
|
|
46
|
+
* `@huggingface/transformers` feature-extraction pipeline) so this package
|
|
47
|
+
* carries no model dependency. When no embedder is injected it degrades to the
|
|
48
|
+
* deterministic {@link LocalEncoder}.
|
|
49
|
+
*/
|
|
50
|
+
export class HNSWEncoder {
|
|
51
|
+
fallback = new LocalEncoder();
|
|
52
|
+
embed;
|
|
53
|
+
/**
|
|
54
|
+
* @param embed Optional real embedding function. When provided it is used
|
|
55
|
+
* exclusively — the hash-based LocalEncoder is NOT mixed in, since combining
|
|
56
|
+
* vectors of different dimensionality would break cosine comparison.
|
|
57
|
+
*/
|
|
58
|
+
constructor(embed) {
|
|
59
|
+
this.embed = embed;
|
|
60
|
+
}
|
|
61
|
+
async encode(text) {
|
|
62
|
+
return this.embed ? this.embed(text) : this.fallback.encode(text);
|
|
63
|
+
}
|
|
64
|
+
async encodeAll(texts) {
|
|
65
|
+
if (!this.embed)
|
|
66
|
+
return this.fallback.encodeAll(texts);
|
|
67
|
+
// Sequential: the underlying transformers pipeline is single-threaded, so
|
|
68
|
+
// Promise.all would not parallelise — it would only inflate peak memory.
|
|
69
|
+
const out = [];
|
|
70
|
+
for (const t of texts)
|
|
71
|
+
out.push(await this.embed(t));
|
|
72
|
+
return out;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
//# sourceMappingURL=encoder.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"encoder.js","sourceRoot":"","sources":["../src/encoder.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export { RouteLayer } from './route-layer.js';
|
|
2
|
+
export { cosineSimilarity, computeCentroid } from './cosine.js';
|
|
3
|
+
export { LocalEncoder, HNSWEncoder } from './encoder.js';
|
|
4
|
+
export type { Encoder } from './encoder.js';
|
|
5
|
+
export { LLMFallbackRouter } from './llm-fallback.js';
|
|
6
|
+
export { buildCapabilityIndex, buildCandidateHints } from './capability-index.js';
|
|
7
|
+
export { buildClassificationPrompt } from './prompts/classify.js';
|
|
8
|
+
export type { Route, RouteResult, RouteLayerConfig, AgentCapability, LLMFallbackConfig } from './types.js';
|
|
9
|
+
export { ALL_ROUTES } from './routes/index.js';
|
|
10
|
+
export { KeywordPreFilter, DEFAULT_KEYWORD_ROUTES } from './keyword-pre-filter.js';
|
|
11
|
+
export type { KeywordRule } from './keyword-pre-filter.js';
|
|
12
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAChE,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AACzD,YAAY,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAClF,OAAO,EAAE,yBAAyB,EAAE,MAAM,uBAAuB,CAAC;AAClE,YAAY,EAAE,KAAK,EAAE,WAAW,EAAE,gBAAgB,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAC3G,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,gBAAgB,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAC;AACnF,YAAY,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export { RouteLayer } from './route-layer.js';
|
|
2
|
+
export { cosineSimilarity, computeCentroid } from './cosine.js';
|
|
3
|
+
export { LocalEncoder, HNSWEncoder } from './encoder.js';
|
|
4
|
+
export { LLMFallbackRouter } from './llm-fallback.js';
|
|
5
|
+
export { buildCapabilityIndex, buildCandidateHints } from './capability-index.js';
|
|
6
|
+
export { buildClassificationPrompt } from './prompts/classify.js';
|
|
7
|
+
export { ALL_ROUTES } from './routes/index.js';
|
|
8
|
+
export { KeywordPreFilter, DEFAULT_KEYWORD_ROUTES } from './keyword-pre-filter.js';
|
|
9
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAChE,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAEzD,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAClF,OAAO,EAAE,yBAAyB,EAAE,MAAM,uBAAuB,CAAC;AAElE,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,gBAAgB,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAC"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { RouteResult } from './types.js';
|
|
2
|
+
export interface KeywordRule {
|
|
3
|
+
/** Regex pattern to match against task description */
|
|
4
|
+
pattern: RegExp;
|
|
5
|
+
/** Agent slug to route to when matched */
|
|
6
|
+
agentSlug: string;
|
|
7
|
+
/** Human-readable name for this route */
|
|
8
|
+
routeName: string;
|
|
9
|
+
/** Description of what this rule matches */
|
|
10
|
+
description: string;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* 30+ default keyword rules for fast, deterministic routing.
|
|
14
|
+
* First-match wins — order matters.
|
|
15
|
+
*/
|
|
16
|
+
export declare const DEFAULT_KEYWORD_ROUTES: KeywordRule[];
|
|
17
|
+
/**
|
|
18
|
+
* Fast keyword-based pre-filter for routing.
|
|
19
|
+
* Runs regex matches against task descriptions before falling through
|
|
20
|
+
* to semantic (embedding-based) routing. First match wins.
|
|
21
|
+
*/
|
|
22
|
+
export declare class KeywordPreFilter {
|
|
23
|
+
private rules;
|
|
24
|
+
constructor(customRules?: Array<{
|
|
25
|
+
pattern: RegExp;
|
|
26
|
+
agentSlug: string;
|
|
27
|
+
routeName: string;
|
|
28
|
+
description: string;
|
|
29
|
+
}>);
|
|
30
|
+
/**
|
|
31
|
+
* Match a task description against keyword rules.
|
|
32
|
+
* Returns the first matching route or null if no keyword matches.
|
|
33
|
+
*/
|
|
34
|
+
match(taskDescription: string): RouteResult | null;
|
|
35
|
+
/**
|
|
36
|
+
* Prepend a custom rule (highest priority).
|
|
37
|
+
*/
|
|
38
|
+
addRule(rule: KeywordRule): void;
|
|
39
|
+
/**
|
|
40
|
+
* Return a copy of the current rules (immutable view).
|
|
41
|
+
*/
|
|
42
|
+
getRules(): ReadonlyArray<KeywordRule>;
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=keyword-pre-filter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"keyword-pre-filter.d.ts","sourceRoot":"","sources":["../src/keyword-pre-filter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAEzC,MAAM,WAAW,WAAW;IAC1B,sDAAsD;IACtD,OAAO,EAAE,MAAM,CAAC;IAChB,0CAA0C;IAC1C,SAAS,EAAE,MAAM,CAAC;IAClB,yCAAyC;IACzC,SAAS,EAAE,MAAM,CAAC;IAClB,4CAA4C;IAC5C,WAAW,EAAE,MAAM,CAAC;CACrB;AAED;;;GAGG;AACH,eAAO,MAAM,sBAAsB,EAAE,WAAW,EA2E/C,CAAC;AAEF;;;;GAIG;AACH,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,KAAK,CAAgB;IAE7B,YAAY,WAAW,CAAC,EAAE,KAAK,CAAC;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,CAAC,EAM9G;IAED;;;OAGG;IACH,KAAK,CAAC,eAAe,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI,CAYjD;IAED;;OAEG;IACH,OAAO,CAAC,IAAI,EAAE,WAAW,GAAG,IAAI,CAE/B;IAED;;OAEG;IACH,QAAQ,IAAI,aAAa,CAAC,WAAW,CAAC,CAErC;CACF"}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 30+ default keyword rules for fast, deterministic routing.
|
|
3
|
+
* First-match wins — order matters.
|
|
4
|
+
*/
|
|
5
|
+
export const DEFAULT_KEYWORD_ROUTES = [
|
|
6
|
+
// Security / CVE
|
|
7
|
+
{ pattern: /CVE-\d{4}-\d+/i, agentSlug: 'engineering-security-engineer', routeName: 'cve-remediation', description: 'CVE identifier detected' },
|
|
8
|
+
{ pattern: /\bOWASP\b/i, agentSlug: 'engineering-security-engineer', routeName: 'owasp-security', description: 'OWASP security reference' },
|
|
9
|
+
{ pattern: /\bthreat\s*model/i, agentSlug: 'engineering-security-engineer', routeName: 'threat-modeling', description: 'Threat modeling task' },
|
|
10
|
+
// Test files
|
|
11
|
+
{ pattern: /\.(test|spec)\.(ts|js|tsx|jsx)\b/i, agentSlug: 'tdd-london-swarm', routeName: 'test-file', description: 'Test file detected' },
|
|
12
|
+
{ pattern: /\b(write|create|add|fix)\s+(unit|integration|e2e)?\s*tests?\b/i, agentSlug: 'tdd-london-swarm', routeName: 'test-writing', description: 'Test writing task' },
|
|
13
|
+
// Docker / DevOps
|
|
14
|
+
{ pattern: /\bDockerfile\b/i, agentSlug: 'engineering-devops-automator', routeName: 'dockerfile', description: 'Dockerfile detected' },
|
|
15
|
+
{ pattern: /\bdocker[-.]?compose\b/i, agentSlug: 'engineering-devops-automator', routeName: 'docker-compose', description: 'Docker Compose detected' },
|
|
16
|
+
{ pattern: /\bterraform\b/i, agentSlug: 'engineering-devops-automator', routeName: 'terraform', description: 'Terraform infrastructure' },
|
|
17
|
+
{ pattern: /\bgithub\s*actions?\b/i, agentSlug: 'engineering-devops-automator', routeName: 'github-actions', description: 'GitHub Actions workflow' },
|
|
18
|
+
{ pattern: /\b\.github\/workflows\b/i, agentSlug: 'engineering-devops-automator', routeName: 'github-workflows', description: 'GitHub workflow file' },
|
|
19
|
+
{ pattern: /\bkubernetes\b|\bk8s\b|\bhelm\b(?=[\s\S]{0,60}\b(?:kubernetes|k8s|chart|deploy|helmfile)\b)|\b(?:kubernetes|k8s|chart|deploy|helmfile)\b(?=[\s\S]{0,60}\bhelm\b)/i, agentSlug: 'engineering-devops-automator', routeName: 'kubernetes', description: 'Kubernetes / Helm (bare "helm" requires nearby Kubernetes context — "take the helm" is not Kubernetes)' },
|
|
20
|
+
// Git operations
|
|
21
|
+
{ pattern: /\bgit\s+(rebase|blame|bisect|cherry-pick|stash|reflog)\b/i, agentSlug: 'engineering-git-workflow-master', routeName: 'git-operations', description: 'Advanced git operation' },
|
|
22
|
+
{ pattern: /\bgit\s+(merge|branch|tag|log|diff)\b/i, agentSlug: 'engineering-git-workflow-master', routeName: 'git-workflow', description: 'Git workflow operation' },
|
|
23
|
+
// Solidity / Smart contracts
|
|
24
|
+
{ pattern: /\.sol\b/i, agentSlug: 'engineering-solidity-smart-contract-engineer', routeName: 'solidity-file', description: 'Solidity file detected' },
|
|
25
|
+
{ pattern: /\bsolidity\b|\bsmart\s*contract\b/i, agentSlug: 'engineering-solidity-smart-contract-engineer', routeName: 'solidity', description: 'Solidity / smart contract' },
|
|
26
|
+
// ZK proofs
|
|
27
|
+
{ pattern: /\bzkp\b|\bcircom\b|\bsnark\b|\bzk[-\s]?proof/i, agentSlug: 'zk-steward', routeName: 'zk-proofs', description: 'Zero-knowledge proof' },
|
|
28
|
+
// MCP
|
|
29
|
+
{ pattern: /\bMCP\s*(server|builder|tool)\b/i, agentSlug: 'specialized-mcp-builder', routeName: 'mcp-builder', description: 'MCP server/tool building' },
|
|
30
|
+
// React Native / Mobile
|
|
31
|
+
{ pattern: /\breact[-\s]?native\b/i, agentSlug: 'engineering-react-native-developer', routeName: 'react-native', description: 'React Native development' },
|
|
32
|
+
// iOS / Swift
|
|
33
|
+
// Bare "swift" is a common English word ("a swift fix") — only match it when
|
|
34
|
+
// iOS/Xcode/Apple context appears nearby (either word order). swiftui/xcode/
|
|
35
|
+
// "ios app" are already unambiguous domain qualifiers.
|
|
36
|
+
{ pattern: /\bswiftui\b|\bxcode\b|\bios\s+app\b|\bswift\b(?=[\s\S]{0,60}\b(?:ios|xcode|apple|app)\b)|\b(?:ios|xcode|apple|app)\b(?=[\s\S]{0,60}\bswift\b)/i, agentSlug: 'engineering-ios-swift-developer', routeName: 'ios-swift', description: 'iOS / Swift development' },
|
|
37
|
+
// Android / Kotlin
|
|
38
|
+
{ pattern: /\bkotlin\b|\bandroid\s+(app|dev)/i, agentSlug: 'engineering-android-kotlin-developer', routeName: 'android-kotlin', description: 'Android / Kotlin development' },
|
|
39
|
+
// Embedded / Firmware
|
|
40
|
+
// Bare "embedded" is a common English word ("the config embedded in the file")
|
|
41
|
+
// — only match it near hardware/firmware context (either word order).
|
|
42
|
+
{ pattern: /\bfirmware\b|\brtos\b|\bmicrocontroller\b|\bembedded\b(?=[\s\S]{0,60}\b(?:firmware|hardware|mcu|rtos|chip|microcontroller|device|system)\b)|\b(?:firmware|hardware|mcu|rtos|chip|microcontroller|device|system)\b(?=[\s\S]{0,60}\bembedded\b)/i, agentSlug: 'engineering-embedded-firmware-engineer', routeName: 'embedded-firmware', description: 'Embedded / firmware development' },
|
|
43
|
+
// Salesforce
|
|
44
|
+
// Bare "apex" is a common English word ("the apex of the call graph") —
|
|
45
|
+
// only match it near Salesforce context (either word order).
|
|
46
|
+
{ pattern: /\bsalesforce\b|\bsoql\b|\bapex\b(?=[\s\S]{0,60}\b(?:salesforce|soql|trigger|lwc|visualforce)\b)|\b(?:salesforce|soql|trigger|lwc|visualforce)\b(?=[\s\S]{0,60}\bapex\b)/i, agentSlug: 'specialized-salesforce-developer', routeName: 'salesforce', description: 'Salesforce / Apex / SOQL' },
|
|
47
|
+
// Game engines
|
|
48
|
+
// Bare "blender" is a common English word (kitchen appliance) — only match
|
|
49
|
+
// it near 3D/render context (either word order).
|
|
50
|
+
{ pattern: /\bblender\b(?=[\s\S]{0,60}\b(?:3d|model|render|animation|mesh|scene|texture)\b)|\b(?:3d|model|render|animation|mesh|scene|texture)\b(?=[\s\S]{0,60}\bblender\b)/i, agentSlug: 'specialized-blender-3d-artist', routeName: 'blender', description: 'Blender 3D modeling' },
|
|
51
|
+
{ pattern: /\bunreal\s*engine\b|\bUE[45]\b/i, agentSlug: 'specialized-unreal-engine-developer', routeName: 'unreal-engine', description: 'Unreal Engine development' },
|
|
52
|
+
// Bare "unity" is a common English word ("ensure unity between modules") —
|
|
53
|
+
// only match it near game/engine context (either word order).
|
|
54
|
+
{ pattern: /\bC#\s*game\b|\bunity3d\b|\bunity\b(?=[\s\S]{0,60}\b(?:game|engine|3d|prefab|asset|c#)\b)|\b(?:game|engine|3d|prefab|asset|c#)\b(?=[\s\S]{0,60}\bunity\b)/i, agentSlug: 'specialized-unity-developer', routeName: 'unity', description: 'Unity game development' },
|
|
55
|
+
{ pattern: /\bgodot\b|\bgdscript\b/i, agentSlug: 'specialized-godot-developer', routeName: 'godot', description: 'Godot game development' },
|
|
56
|
+
// SEO
|
|
57
|
+
{ pattern: /\bSEO\b|\bsearch\s*engine\s*optim/i, agentSlug: 'specialized-seo-strategist', routeName: 'seo', description: 'SEO optimization' },
|
|
58
|
+
// Supply chain
|
|
59
|
+
{ pattern: /\bsupply[-\s]?chain\b|\bSBOM\b/i, agentSlug: 'engineering-supply-chain-security', routeName: 'supply-chain', description: 'Supply chain security' },
|
|
60
|
+
// GraphQL
|
|
61
|
+
{ pattern: /\bgraphql\b|\b\.graphql\b|\b\.gql\b/i, agentSlug: 'engineering-graphql-developer', routeName: 'graphql', description: 'GraphQL development' },
|
|
62
|
+
// Database / SQL
|
|
63
|
+
{ pattern: /\bpostgres\b|\bmysql\b|\bmongodb\b|\bredis\b/i, agentSlug: 'engineering-database-engineer', routeName: 'database', description: 'Database engineering' },
|
|
64
|
+
];
|
|
65
|
+
/**
|
|
66
|
+
* Fast keyword-based pre-filter for routing.
|
|
67
|
+
* Runs regex matches against task descriptions before falling through
|
|
68
|
+
* to semantic (embedding-based) routing. First match wins.
|
|
69
|
+
*/
|
|
70
|
+
export class KeywordPreFilter {
|
|
71
|
+
rules;
|
|
72
|
+
constructor(customRules) {
|
|
73
|
+
this.rules = [...DEFAULT_KEYWORD_ROUTES];
|
|
74
|
+
if (customRules) {
|
|
75
|
+
// Prepend custom rules so they take priority
|
|
76
|
+
this.rules = [...customRules, ...this.rules];
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Match a task description against keyword rules.
|
|
81
|
+
* Returns the first matching route or null if no keyword matches.
|
|
82
|
+
*/
|
|
83
|
+
match(taskDescription) {
|
|
84
|
+
for (const rule of this.rules) {
|
|
85
|
+
if (rule.pattern.test(taskDescription)) {
|
|
86
|
+
return {
|
|
87
|
+
agentSlug: rule.agentSlug,
|
|
88
|
+
confidence: 1.0,
|
|
89
|
+
method: 'keyword',
|
|
90
|
+
routeName: rule.routeName,
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
return null;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Prepend a custom rule (highest priority).
|
|
98
|
+
*/
|
|
99
|
+
addRule(rule) {
|
|
100
|
+
this.rules.unshift(rule);
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Return a copy of the current rules (immutable view).
|
|
104
|
+
*/
|
|
105
|
+
getRules() {
|
|
106
|
+
return [...this.rules];
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
//# sourceMappingURL=keyword-pre-filter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"keyword-pre-filter.js","sourceRoot":"","sources":["../src/keyword-pre-filter.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { Route, RouteResult, LLMFallbackConfig } from './types.js';
|
|
2
|
+
export declare class LLMFallbackRouter {
|
|
3
|
+
private config;
|
|
4
|
+
/** Session-scoped fallback counter per route name */
|
|
5
|
+
private fallbackCounts;
|
|
6
|
+
constructor(config: LLMFallbackConfig);
|
|
7
|
+
/**
|
|
8
|
+
* Classify a task description using an LLM when semantic routing confidence is too low.
|
|
9
|
+
*/
|
|
10
|
+
classify(taskDescription: string, routes: Route[], scores: Array<{
|
|
11
|
+
routeName: string;
|
|
12
|
+
agentSlug: string;
|
|
13
|
+
score: number;
|
|
14
|
+
}>): Promise<RouteResult>;
|
|
15
|
+
/** Returns a snapshot of fallback counts for this session */
|
|
16
|
+
getFallbackStats(): Record<string, number>;
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=llm-fallback.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"llm-fallback.d.ts","sourceRoot":"","sources":["../src/llm-fallback.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAOnE,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,MAAM,CAAoB;IAClC,qDAAqD;IACrD,OAAO,CAAC,cAAc,CAA6B;IAEnD,YAAY,MAAM,EAAE,iBAAiB,EAEpC;IAED;;OAEG;IACG,QAAQ,CACZ,eAAe,EAAE,MAAM,EACvB,MAAM,EAAE,KAAK,EAAE,EACf,MAAM,EAAE,KAAK,CAAC;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,GACrE,OAAO,CAAC,WAAW,CAAC,CA4DtB;IAED,6DAA6D;IAC7D,gBAAgB,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAEzC;CACF"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { buildCapabilityIndex, buildCandidateHints } from './capability-index.js';
|
|
2
|
+
import { buildClassificationPrompt } from './prompts/classify.js';
|
|
3
|
+
/** Slug validation regex — must match ALLOWED_AGENT_TYPES pattern */
|
|
4
|
+
const SLUG_PATTERN = /^[a-zA-Z][a-zA-Z0-9_-]{0,63}$/;
|
|
5
|
+
export class LLMFallbackRouter {
|
|
6
|
+
config;
|
|
7
|
+
/** Session-scoped fallback counter per route name */
|
|
8
|
+
fallbackCounts = new Map();
|
|
9
|
+
constructor(config) {
|
|
10
|
+
this.config = config;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Classify a task description using an LLM when semantic routing confidence is too low.
|
|
14
|
+
*/
|
|
15
|
+
async classify(taskDescription, routes, scores) {
|
|
16
|
+
const nearestRoute = scores[0];
|
|
17
|
+
// Log the fallback event
|
|
18
|
+
const onFallback = this.config.onFallback ?? defaultFallbackLogger;
|
|
19
|
+
onFallback(nearestRoute.routeName, taskDescription, nearestRoute.score);
|
|
20
|
+
this.fallbackCounts.set(nearestRoute.routeName, (this.fallbackCounts.get(nearestRoute.routeName) ?? 0) + 1);
|
|
21
|
+
// Build prompt
|
|
22
|
+
const capabilityIndex = buildCapabilityIndex(routes);
|
|
23
|
+
const candidateHints = buildCandidateHints(scores);
|
|
24
|
+
const prompt = buildClassificationPrompt(taskDescription, capabilityIndex, candidateHints);
|
|
25
|
+
// Call LLM
|
|
26
|
+
let rawResponse;
|
|
27
|
+
try {
|
|
28
|
+
rawResponse = await this.config.llmCaller(prompt);
|
|
29
|
+
}
|
|
30
|
+
catch (err) {
|
|
31
|
+
console.error('[LLMFallback] LLM call failed, using best semantic match:', err);
|
|
32
|
+
return {
|
|
33
|
+
agentSlug: nearestRoute.agentSlug,
|
|
34
|
+
confidence: nearestRoute.score,
|
|
35
|
+
method: 'llm_fallback',
|
|
36
|
+
routeName: nearestRoute.routeName,
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
// Parse and validate the slug
|
|
40
|
+
const slug = rawResponse.trim().replace(/[`'"]/g, '').toLowerCase();
|
|
41
|
+
if (!SLUG_PATTERN.test(slug)) {
|
|
42
|
+
console.error(`[LLMFallback] Invalid slug in LLM response: "${slug}"`);
|
|
43
|
+
return {
|
|
44
|
+
agentSlug: nearestRoute.agentSlug,
|
|
45
|
+
confidence: nearestRoute.score,
|
|
46
|
+
method: 'llm_fallback',
|
|
47
|
+
routeName: nearestRoute.routeName,
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
// Verify slug exists in routes — compare case-insensitively since slug is lowercased
|
|
51
|
+
const matchedRoute = routes.find(r => r.agentSlug.toLowerCase() === slug);
|
|
52
|
+
if (!matchedRoute) {
|
|
53
|
+
console.error(`[LLMFallback] LLM returned unknown slug: "${slug}"`);
|
|
54
|
+
return {
|
|
55
|
+
agentSlug: nearestRoute.agentSlug,
|
|
56
|
+
confidence: nearestRoute.score,
|
|
57
|
+
method: 'llm_fallback',
|
|
58
|
+
routeName: nearestRoute.routeName,
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
return {
|
|
62
|
+
agentSlug: matchedRoute.agentSlug, // use canonical casing from route definition
|
|
63
|
+
confidence: 0.85,
|
|
64
|
+
method: 'llm_fallback',
|
|
65
|
+
routeName: matchedRoute.name,
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
/** Returns a snapshot of fallback counts for this session */
|
|
69
|
+
getFallbackStats() {
|
|
70
|
+
return Object.fromEntries(this.fallbackCounts.entries());
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
function defaultFallbackLogger(routeName, task, confidence) {
|
|
74
|
+
console.warn(`[LLMFallback] Route "${routeName}" confidence ${confidence.toFixed(3)} below threshold for task: "${task.slice(0, 80)}..."`);
|
|
75
|
+
}
|
|
76
|
+
//# sourceMappingURL=llm-fallback.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"llm-fallback.js","sourceRoot":"","sources":["../src/llm-fallback.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"classify.d.ts","sourceRoot":"","sources":["../../src/prompts/classify.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,wBAAgB,yBAAyB,CACvC,eAAe,EAAE,MAAM,EACvB,eAAe,EAAE,MAAM,EACvB,cAAc,EAAE,MAAM,GACrB,MAAM,CAoBR"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Build the classification prompt for LLM fallback routing.
|
|
3
|
+
*/
|
|
4
|
+
export function buildClassificationPrompt(taskDescription, capabilityIndex, candidateHints) {
|
|
5
|
+
return `You are a task routing classifier. Your job is to select the single best agent slug for a given task.
|
|
6
|
+
|
|
7
|
+
## Available Agents
|
|
8
|
+
${capabilityIndex}
|
|
9
|
+
|
|
10
|
+
## Semantic Pre-Candidates (top 3 by embedding similarity)
|
|
11
|
+
${candidateHints}
|
|
12
|
+
|
|
13
|
+
## Task to Route
|
|
14
|
+
"${taskDescription}"
|
|
15
|
+
|
|
16
|
+
## Instructions
|
|
17
|
+
1. Review the task description carefully.
|
|
18
|
+
2. Consider the semantic pre-candidates — they may already be correct.
|
|
19
|
+
3. Select the SINGLE best agent slug from the Available Agents list above.
|
|
20
|
+
4. Output ONLY the agent slug — no explanation, no markdown, no punctuation.
|
|
21
|
+
5. The slug must exactly match one of the slugs in the Available Agents list.
|
|
22
|
+
|
|
23
|
+
Agent slug:`;
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=classify.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"classify.js","sourceRoot":"","sources":["../../src/prompts/classify.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,UAAU,yBAAyB,CACvC,eAAuB,EACvB,eAAuB,EACvB,cAAsB;IAEtB,OAAO;;;EAGP,eAAe;;;EAGf,cAAc;;;GAGb,eAAe;;;;;;;;;YASN,CAAC;AACb,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { Route, RouteResult, RouteLayerConfig } from './types.js';
|
|
2
|
+
export declare class RouteLayer {
|
|
3
|
+
private centroids;
|
|
4
|
+
private encoder;
|
|
5
|
+
private config;
|
|
6
|
+
private initialized;
|
|
7
|
+
private llmFallback?;
|
|
8
|
+
private keywordFilter?;
|
|
9
|
+
constructor(config: RouteLayerConfig);
|
|
10
|
+
/**
|
|
11
|
+
* Pre-compute centroids for all routes.
|
|
12
|
+
* Idempotent — safe to call multiple times.
|
|
13
|
+
*/
|
|
14
|
+
initialize(): Promise<void>;
|
|
15
|
+
/**
|
|
16
|
+
* Route a task description to the most appropriate agent slug.
|
|
17
|
+
* Auto-initializes on first call.
|
|
18
|
+
*/
|
|
19
|
+
route(taskDescription: string): Promise<RouteResult>;
|
|
20
|
+
/**
|
|
21
|
+
* Register an additional route at runtime without re-initializing all centroids.
|
|
22
|
+
*/
|
|
23
|
+
addRoute(route: Route): Promise<void>;
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=route-layer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"route-layer.d.ts","sourceRoot":"","sources":["../src/route-layer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAWlE,qBAAa,UAAU;IACrB,OAAO,CAAC,SAAS,CAAuB;IACxC,OAAO,CAAC,OAAO,CAAU;IACzB,OAAO,CAAC,MAAM,CAAmB;IACjC,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,WAAW,CAAC,CAAoB;IACxC,OAAO,CAAC,aAAa,CAAC,CAAmB;IAEzC,YAAY,MAAM,EAAE,gBAAgB,EAkBnC;IAED;;;OAGG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC,CAuBhC;IAED;;;OAGG;IACG,KAAK,CAAC,eAAe,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAgEzD;IAED;;OAEG;IACG,QAAQ,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,CAM1C;CACF"}
|