agentic-flow 3.1.0 → 3.3.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/.agents/skills/agentic-flow-ecosystem/SKILL.md +51 -0
- package/.claude/skills/agentic-flow-ecosystem/skill.md +59 -0
- package/.claude/skills/agentic-flow-quickstart/skill.md +6 -6
- package/.claude/skills/hooks-automation/skill.md +11 -11
- package/.claude/skills/memory-patterns/skill.md +7 -7
- package/.claude/skills/sparc-methodology/skill.md +13 -13
- package/.claude/skills/swarm-coordination/skill.md +5 -5
- package/.claude/skills/worker-benchmarks/skill.md +5 -5
- package/.claude/skills/worker-integration/skill.md +5 -5
- package/CHANGELOG.md +50 -0
- package/README.md +82 -67
- package/dist/.tsbuildinfo +1 -1
- package/dist/cli/commands/init.d.ts.map +1 -1
- package/dist/cli/commands/init.js +9 -0
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/config/claudeFlow.d.ts +1 -1
- package/dist/core/agentdb-fast.d.ts +21 -11
- package/dist/core/agentdb-fast.d.ts.map +1 -1
- package/dist/core/agentdb-fast.js +39 -14
- package/dist/core/agentdb-fast.js.map +1 -1
- package/dist/integrations/agent-booster.d.ts +35 -0
- package/dist/integrations/agent-booster.d.ts.map +1 -0
- package/dist/integrations/agent-booster.js +45 -0
- package/dist/integrations/agent-booster.js.map +1 -0
- package/dist/integrations/index.d.ts +15 -0
- package/dist/integrations/index.d.ts.map +1 -0
- package/dist/integrations/index.js +11 -0
- package/dist/integrations/index.js.map +1 -0
- package/dist/integrations/onnx-wasm-embedder.d.ts +59 -0
- package/dist/integrations/onnx-wasm-embedder.d.ts.map +1 -0
- package/dist/integrations/onnx-wasm-embedder.js +145 -0
- package/dist/integrations/onnx-wasm-embedder.js.map +1 -0
- package/dist/integrations/optional.d.ts +32 -0
- package/dist/integrations/optional.d.ts.map +1 -0
- package/dist/integrations/optional.js +83 -0
- package/dist/integrations/optional.js.map +1 -0
- package/dist/integrations/prompt-injection.d.ts +52 -0
- package/dist/integrations/prompt-injection.d.ts.map +1 -0
- package/dist/integrations/prompt-injection.js +126 -0
- package/dist/integrations/prompt-injection.js.map +1 -0
- package/dist/integrations/sublinear.d.ts +99 -0
- package/dist/integrations/sublinear.d.ts.map +1 -0
- package/dist/integrations/sublinear.js +303 -0
- package/dist/integrations/sublinear.js.map +1 -0
- package/dist/integrations/task-partition.d.ts +40 -0
- package/dist/integrations/task-partition.d.ts.map +1 -0
- package/dist/integrations/task-partition.js +173 -0
- package/dist/integrations/task-partition.js.map +1 -0
- package/dist/intelligence/RuVectorIntelligence.d.ts.map +1 -1
- package/dist/intelligence/RuVectorIntelligence.js +4 -3
- package/dist/intelligence/RuVectorIntelligence.js.map +1 -1
- package/dist/mcp/mcp-policy.d.ts.map +1 -1
- package/dist/mcp/mcp-policy.js +2 -0
- package/dist/mcp/mcp-policy.js.map +1 -1
- package/dist/mcp/standalone-stdio.js +12 -26
- package/dist/mcp/standalone-stdio.js.map +1 -1
- package/dist/mcp/tools/ecosystem-tools.d.ts +49 -0
- package/dist/mcp/tools/ecosystem-tools.d.ts.map +1 -0
- package/dist/mcp/tools/ecosystem-tools.js +148 -0
- package/dist/mcp/tools/ecosystem-tools.js.map +1 -0
- package/dist/optimizations/configuration-tuning.d.ts +1 -1
- package/dist/routing/SemanticRouter.d.ts +25 -9
- package/dist/routing/SemanticRouter.d.ts.map +1 -1
- package/dist/routing/SemanticRouter.js +63 -12
- package/dist/routing/SemanticRouter.js.map +1 -1
- package/dist/services/sona-loader.d.ts +15 -1
- package/dist/services/sona-loader.d.ts.map +1 -1
- package/dist/services/sona-loader.js +54 -2
- package/dist/services/sona-loader.js.map +1 -1
- package/dist/utils/input-validator.d.ts +10 -2
- package/dist/utils/input-validator.d.ts.map +1 -1
- package/dist/utils/input-validator.js +30 -2
- package/dist/utils/input-validator.js.map +1 -1
- package/dist/utils/model-cache.d.ts.map +1 -1
- package/dist/utils/model-cache.js +6 -25
- package/dist/utils/model-cache.js.map +1 -1
- package/dist/wasm/onnx-embeddings-wasm.d.ts.map +1 -1
- package/dist/wasm/onnx-embeddings-wasm.js +21 -10
- package/dist/wasm/onnx-embeddings-wasm.js.map +1 -1
- package/docs/integrations/FASTMCP_CLI_INTEGRATION.md +1 -1
- package/package.json +13 -8
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ecosystem-tools.js","sourceRoot":"","sources":["../../../src/mcp/tools/ecosystem-tools.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Ecosystem MCP tools: in-process access to the optional ruvnet packages\n * agentic-flow integrates (aidefence, @ruvector/mincut-wasm,\n * @ruvnet/sublinear-core, agent-booster, @ruvector/router,\n * ruvector-onnx-embeddings-wasm).\n *\n * Every tool works without its optional package (built-in fallback) and says\n * which engine answered. All are pure computations with no side effects, so\n * the MCP policy admits them under the default `readonly` profile.\n */\n\nimport { z } from 'zod';\nimport { isOptionalInstalled } from '../../integrations/optional.js';\nimport { scanPromptInjection, promptInjectionEngine, getInjectionPolicy } from '../../integrations/prompt-injection.js';\nimport { partitionTaskGraph, type TaskDependency } from '../../integrations/task-partition.js';\nimport { solveLinearSystem, pageRank, type MatrixInput, type PageRankEdge } from '../../integrations/sublinear.js';\nimport { onnxWasmModelCached, onnxWasmDownloadAllowed } from '../../integrations/onnx-wasm-embedder.js';\n\nexport interface EcosystemTool {\n name: string;\n description: string;\n parameters: z.ZodTypeAny;\n execute: (args: unknown) => Promise<string>;\n}\n\n/** Optional packages and what they power. `probe` is checked without loading it. */\nexport const ECOSYSTEM_PACKAGES = [\n { pkg: 'aidefence', probe: 'aidefence/dist/detection', powers: 'prompt-injection screening (InputValidator, prompt_injection_scan)' },\n { pkg: 'agent-booster', probe: 'agent-booster', powers: 'in-process code edits (agent_booster_* tools)' },\n { pkg: '@ruvector/router', probe: '@ruvector/router', powers: 'native HNSW index for SemanticRouter' },\n { pkg: '@ruvector/mincut-wasm', probe: '@ruvector/mincut-wasm', powers: 'task-graph partitioning (swarm_partition_tasks)' },\n { pkg: '@ruvnet/sublinear-core', probe: '@ruvnet/sublinear-core', powers: 'linear solves, PageRank and personalized PageRank (sublinear_solve, sublinear_pagerank)' },\n { pkg: 'ruvector-onnx-embeddings-wasm', probe: 'ruvector-onnx-embeddings-wasm', powers: 'all-MiniLM-L6-v2 embeddings (AgentDBFast, EmbeddingService onnx-wasm)' },\n] as const;\n\n// The project compiles with strict: false, so zod infers object fields as\n// optional; the schemas themselves require them, hence the casts below.\nconst json = (v: unknown) => JSON.stringify(v, null, 2);\n\nconst statusParams = z.object({}).strict();\nconst partitionParams = z.object({\n tasks: z.array(z.string().min(1).max(200)).max(5000).describe('Task ids; tasks only named in dependencies are added'),\n dependencies: z\n .array(z.object({\n from: z.string().min(1).max(200),\n to: z.string().min(1).max(200),\n weight: z.number().nonnegative().finite().optional().describe('Coupling strength, default 1'),\n }))\n .max(50000),\n});\nconst solveParams = z.object({\n matrix: z\n .union([\n z.array(z.array(z.number().finite())).min(1).max(2000),\n z.object({\n size: z.number().int().positive().max(1_000_000),\n entries: z.array(z.object({ row: z.number().int(), col: z.number().int(), value: z.number().finite() })).max(5_000_000),\n }),\n ])\n .describe('Square matrix: dense rows, or {size, entries:[{row,col,value}]}; diagonally dominant for guaranteed convergence'),\n vector: z.array(z.number().finite()).min(1).describe('Right-hand side b'),\n tolerance: z.number().positive().max(1).optional(),\n maxIterations: z.number().int().positive().max(1_000_000).optional(),\n method: z\n .enum(['auto', 'gauss-seidel', 'conjugate-gradient', 'jacobi', 'neumann'])\n .optional()\n .describe('Default auto: conjugate-gradient for symmetric matrices with a positive diagonal, else gauss-seidel'),\n});\nconst pagerankParams = z.object({\n edges: z.array(z.object({\n from: z.string().min(1).max(200),\n to: z.string().min(1).max(200),\n weight: z.number().nonnegative().finite().optional(),\n })).max(500000),\n nodes: z.array(z.string().min(1).max(200)).max(100000).optional().describe('Extra nodes with no edges'),\n damping: z.number().gt(0).lt(1).optional().describe('Probability of following an edge (1 - restart probability), default 0.85'),\n top: z.number().int().positive().max(10000).optional().describe('Return only the top N (default all)'),\n seeds: z\n .union([\n z.array(z.string().min(1).max(200)).min(1).max(100000),\n z.record(z.string().min(1).max(200), z.number().nonnegative().finite()),\n ])\n .optional()\n .describe('Personalized PageRank: restart at these nodes (equal weight), or {node: weight}'),\n approximate: z\n .boolean()\n .optional()\n .describe('With seeds: local forward push. Work depends on epsilon, not graph size; best with top on large graphs. Returns residualMass (L1 error bound)'),\n epsilon: z.number().positive().max(0.1).optional().describe('Forward-push residual threshold, default 1e-6 (smaller = more accurate)'),\n});\nconst scanParams = z.object({\n text: z.string().max(100000),\n policy: z.enum(['block', 'strict', 'warn']).optional().describe('Override AGENTIC_FLOW_PROMPT_INJECTION for this scan'),\n});\n\nexport const ECOSYSTEM_TOOLS: EcosystemTool[] = [\n {\n name: 'ecosystem_status',\n description: 'List the optional ruvnet packages agentic-flow integrates, whether each is installed, and what it powers. Every integration has a built-in fallback.',\n parameters: statusParams,\n execute: async (raw) => {\n statusParams.parse(raw ?? {});\n return json({\n packages: ECOSYSTEM_PACKAGES.map(({ pkg, probe, powers }) => ({ package: pkg, installed: isOptionalInstalled(probe), powers })),\n promptInjection: { engine: promptInjectionEngine(), policy: getInjectionPolicy() },\n embeddings: { modelCached: onnxWasmModelCached(), downloadAllowed: onnxWasmDownloadAllowed() },\n install: 'npm install agentic-flow (optional packages install by default; --omit=optional skips them)',\n });\n },\n },\n {\n name: 'swarm_partition_tasks',\n description: 'Split a task-dependency graph into two groups with the least coupling (exact global minimum cut) — the seam to hand work to two agent teams. Uses @ruvector/mincut-wasm, built-in Stoer-Wagner otherwise.',\n parameters: partitionParams,\n execute: async (raw) => {\n const a = partitionParams.parse(raw);\n return json(await partitionTaskGraph(a.tasks, a.dependencies as TaskDependency[]));\n },\n },\n {\n name: 'sublinear_solve',\n description: 'Solve Mx = b for a diagonally dominant or symmetric positive definite matrix. Uses @ruvnet/sublinear-core (Gauss-Seidel / conjugate gradient), verifies the residual max|Mx-b|, and falls back to a built-in Gauss-Seidel. Returns solution, residual, iterations, method and engine.',\n parameters: solveParams,\n execute: async (raw) => {\n const a = solveParams.parse(raw);\n return json(await solveLinearSystem(a.matrix as MatrixInput, a.vector, { tolerance: a.tolerance, maxIterations: a.maxIterations, method: a.method }));\n },\n },\n {\n name: 'sublinear_pagerank',\n description: 'PageRank over a directed graph (agents, files, tasks), or personalized PageRank around seeds (what matters to these nodes). Uses @ruvnet/sublinear-core power iteration, or local forward push with approximate: true; results are verified, built-in Gauss-Seidel fallback. Returns scores, a ranking and the engine.',\n parameters: pagerankParams,\n execute: async (raw) => {\n const a = pagerankParams.parse(raw);\n return json(await pageRank(a.edges as PageRankEdge[], {\n damping: a.damping,\n nodes: a.nodes,\n seeds: a.seeds as string[] | Record<string, number> | undefined,\n approximate: a.approximate,\n epsilon: a.epsilon,\n top: a.top,\n }));\n },\n },\n {\n name: 'prompt_injection_scan',\n description: 'Scan text for prompt-injection attempts (instruction override, role switching, prompt exfiltration, jailbreaks) with aidefence, built-in patterns otherwise. Returns threats and the policy decision (allow/warn/block).',\n parameters: scanParams,\n execute: async (raw) => {\n const a = scanParams.parse(raw);\n return json(scanPromptInjection(a.text, a.policy));\n },\n },\n];\n\nexport const ECOSYSTEM_TOOL_NAMES = ECOSYSTEM_TOOLS.map((t) => t.name);\n\nexport function registerEcosystemTools(server: { addTool: (tool: EcosystemTool) => void }): void {\n for (const tool of ECOSYSTEM_TOOLS) server.addTool(tool);\n}\n"]}
|
|
@@ -122,7 +122,7 @@ export declare class ConfigurationTuning {
|
|
|
122
122
|
entries: number;
|
|
123
123
|
};
|
|
124
124
|
topology: {
|
|
125
|
-
mode: "
|
|
125
|
+
mode: "hierarchical" | "mesh" | "ring" | "star" | "auto";
|
|
126
126
|
changes: number;
|
|
127
127
|
improvement: string;
|
|
128
128
|
};
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Semantic Router - HNSW-Powered Intent Matching
|
|
3
3
|
*
|
|
4
|
-
*
|
|
4
|
+
* Uses @ruvector/router's native HNSW index (VectorDb) when the package and
|
|
5
|
+
* its platform binary are installed, and an exact brute-force cosine scan
|
|
6
|
+
* otherwise. Both return the same ranking contract: similarity in [-1, 1],
|
|
7
|
+
* highest first.
|
|
5
8
|
*
|
|
6
9
|
* Features:
|
|
7
10
|
* - HNSW (Hierarchical Navigable Small World) index
|
|
@@ -17,6 +20,7 @@
|
|
|
17
20
|
* - O(log N) search complexity
|
|
18
21
|
*/
|
|
19
22
|
import type { EmbeddingService } from 'agentdb';
|
|
23
|
+
export type SemanticIndexBackend = 'ruvector-router' | 'brute-force';
|
|
20
24
|
export interface AgentIntent {
|
|
21
25
|
/** Agent type identifier */
|
|
22
26
|
agentType: string;
|
|
@@ -73,8 +77,17 @@ export declare class SemanticRouter {
|
|
|
73
77
|
private agentIntents;
|
|
74
78
|
private intentEmbeddings;
|
|
75
79
|
private indexBuilt;
|
|
80
|
+
private nativeIndex;
|
|
81
|
+
private backend;
|
|
82
|
+
private readonly useNative;
|
|
76
83
|
private routingStats;
|
|
77
|
-
|
|
84
|
+
/**
|
|
85
|
+
* @param embedder - Embedding service for intents and tasks
|
|
86
|
+
* @param options.native - Use @ruvector/router when installed (default true)
|
|
87
|
+
*/
|
|
88
|
+
constructor(embedder: EmbeddingService, options?: {
|
|
89
|
+
native?: boolean;
|
|
90
|
+
});
|
|
78
91
|
/**
|
|
79
92
|
* Register agent intent for routing
|
|
80
93
|
*
|
|
@@ -88,12 +101,15 @@ export declare class SemanticRouter {
|
|
|
88
101
|
*/
|
|
89
102
|
registerAgents(intents: AgentIntent[]): Promise<void>;
|
|
90
103
|
/**
|
|
91
|
-
* Build
|
|
104
|
+
* Build the routing index.
|
|
92
105
|
*
|
|
93
|
-
*
|
|
94
|
-
*
|
|
106
|
+
* Loads @ruvector/router's native HNSW (VectorDb, cosine metric) when it is
|
|
107
|
+
* installed; otherwise routing uses an exact brute-force scan, which is
|
|
108
|
+
* still fast at the ~66-agent scale.
|
|
95
109
|
*/
|
|
96
110
|
buildIndex(): void;
|
|
111
|
+
/** Which index answered the last build: native HNSW or brute force. */
|
|
112
|
+
getIndexBackend(): SemanticIndexBackend;
|
|
97
113
|
/**
|
|
98
114
|
* Route task to best agent using semantic similarity
|
|
99
115
|
*
|
|
@@ -130,14 +146,14 @@ export declare class SemanticRouter {
|
|
|
130
146
|
*/
|
|
131
147
|
getRegisteredAgents(): AgentIntent[];
|
|
132
148
|
/**
|
|
133
|
-
* Search
|
|
149
|
+
* Search the index for nearest neighbours.
|
|
134
150
|
*
|
|
135
|
-
*
|
|
136
|
-
*
|
|
151
|
+
* @ruvector/router reports cosine *distance* (0 = identical), so it is
|
|
152
|
+
* converted to similarity (1 - distance) to keep "higher is better".
|
|
137
153
|
*
|
|
138
154
|
* @param queryEmbedding - Query vector
|
|
139
155
|
* @param k - Number of results
|
|
140
|
-
* @returns Top k candidates with similarity scores
|
|
156
|
+
* @returns Top k candidates with similarity scores, highest first
|
|
141
157
|
*/
|
|
142
158
|
private searchHNSW;
|
|
143
159
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SemanticRouter.d.ts","sourceRoot":"","sources":["../../src/routing/SemanticRouter.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"SemanticRouter.d.ts","sourceRoot":"","sources":["../../src/routing/SemanticRouter.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Semantic Router - HNSW-Powered Intent Matching
|
|
3
3
|
*
|
|
4
|
-
*
|
|
4
|
+
* Uses @ruvector/router's native HNSW index (VectorDb) when the package and
|
|
5
|
+
* its platform binary are installed, and an exact brute-force cosine scan
|
|
6
|
+
* otherwise. Both return the same ranking contract: similarity in [-1, 1],
|
|
7
|
+
* highest first.
|
|
5
8
|
*
|
|
6
9
|
* Features:
|
|
7
10
|
* - HNSW (Hierarchical Navigable Small World) index
|
|
@@ -16,6 +19,7 @@
|
|
|
16
19
|
* - Support for 66+ agent types
|
|
17
20
|
* - O(log N) search complexity
|
|
18
21
|
*/
|
|
22
|
+
import { requireOptional } from '../integrations/optional.js';
|
|
19
23
|
/**
|
|
20
24
|
* Semantic Router
|
|
21
25
|
*
|
|
@@ -30,12 +34,20 @@ export class SemanticRouter {
|
|
|
30
34
|
// Agent registry
|
|
31
35
|
agentIntents;
|
|
32
36
|
intentEmbeddings;
|
|
33
|
-
// HNSW index
|
|
37
|
+
// Native HNSW index (@ruvector/router) or null for the brute-force scan
|
|
34
38
|
indexBuilt = false;
|
|
39
|
+
nativeIndex = null;
|
|
40
|
+
backend = 'brute-force';
|
|
41
|
+
useNative;
|
|
35
42
|
// Performance tracking
|
|
36
43
|
routingStats;
|
|
37
|
-
|
|
44
|
+
/**
|
|
45
|
+
* @param embedder - Embedding service for intents and tasks
|
|
46
|
+
* @param options.native - Use @ruvector/router when installed (default true)
|
|
47
|
+
*/
|
|
48
|
+
constructor(embedder, options = {}) {
|
|
38
49
|
this.embedder = embedder;
|
|
50
|
+
this.useNative = options.native ?? true;
|
|
39
51
|
this.agentIntents = new Map();
|
|
40
52
|
this.intentEmbeddings = new Map();
|
|
41
53
|
this.routingStats = {
|
|
@@ -71,16 +83,43 @@ export class SemanticRouter {
|
|
|
71
83
|
await Promise.all(intents.map(intent => this.registerAgent(intent)));
|
|
72
84
|
}
|
|
73
85
|
/**
|
|
74
|
-
* Build
|
|
86
|
+
* Build the routing index.
|
|
75
87
|
*
|
|
76
|
-
*
|
|
77
|
-
*
|
|
88
|
+
* Loads @ruvector/router's native HNSW (VectorDb, cosine metric) when it is
|
|
89
|
+
* installed; otherwise routing uses an exact brute-force scan, which is
|
|
90
|
+
* still fast at the ~66-agent scale.
|
|
78
91
|
*/
|
|
79
92
|
buildIndex() {
|
|
80
|
-
|
|
81
|
-
|
|
93
|
+
this.nativeIndex = null;
|
|
94
|
+
this.backend = 'brute-force';
|
|
95
|
+
const first = this.intentEmbeddings.values().next().value;
|
|
96
|
+
const router = this.useNative && first
|
|
97
|
+
? requireOptional('@ruvector/router')
|
|
98
|
+
: null;
|
|
99
|
+
if (router && first) {
|
|
100
|
+
try {
|
|
101
|
+
const db = new router.VectorDb({
|
|
102
|
+
dimensions: first.length,
|
|
103
|
+
distanceMetric: router.DistanceMetric.Cosine,
|
|
104
|
+
});
|
|
105
|
+
for (const [agentType, embedding] of Array.from(this.intentEmbeddings.entries())) {
|
|
106
|
+
db.insert(agentType, embedding instanceof Float32Array ? embedding : Float32Array.from(embedding));
|
|
107
|
+
}
|
|
108
|
+
this.nativeIndex = db;
|
|
109
|
+
this.backend = 'ruvector-router';
|
|
110
|
+
}
|
|
111
|
+
catch {
|
|
112
|
+
// Native binary missing for this platform, or a dimension mismatch:
|
|
113
|
+
// keep the exact brute-force path.
|
|
114
|
+
this.nativeIndex = null;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
82
117
|
this.indexBuilt = true;
|
|
83
118
|
}
|
|
119
|
+
/** Which index answered the last build: native HNSW or brute force. */
|
|
120
|
+
getIndexBackend() {
|
|
121
|
+
return this.backend;
|
|
122
|
+
}
|
|
84
123
|
/**
|
|
85
124
|
* Route task to best agent using semantic similarity
|
|
86
125
|
*
|
|
@@ -194,16 +233,28 @@ export class SemanticRouter {
|
|
|
194
233
|
// Private Helper Methods
|
|
195
234
|
// ========================================================================
|
|
196
235
|
/**
|
|
197
|
-
* Search
|
|
236
|
+
* Search the index for nearest neighbours.
|
|
198
237
|
*
|
|
199
|
-
*
|
|
200
|
-
*
|
|
238
|
+
* @ruvector/router reports cosine *distance* (0 = identical), so it is
|
|
239
|
+
* converted to similarity (1 - distance) to keep "higher is better".
|
|
201
240
|
*
|
|
202
241
|
* @param queryEmbedding - Query vector
|
|
203
242
|
* @param k - Number of results
|
|
204
|
-
* @returns Top k candidates with similarity scores
|
|
243
|
+
* @returns Top k candidates with similarity scores, highest first
|
|
205
244
|
*/
|
|
206
245
|
searchHNSW(queryEmbedding, k) {
|
|
246
|
+
if (this.nativeIndex) {
|
|
247
|
+
try {
|
|
248
|
+
const query = queryEmbedding instanceof Float32Array ? queryEmbedding : Float32Array.from(queryEmbedding);
|
|
249
|
+
return this.nativeIndex
|
|
250
|
+
.search(query, Math.min(k, this.intentEmbeddings.size))
|
|
251
|
+
.map((r) => ({ agentType: r.id, similarity: 1 - r.score }))
|
|
252
|
+
.sort((a, b) => b.similarity - a.similarity);
|
|
253
|
+
}
|
|
254
|
+
catch {
|
|
255
|
+
// fall through to the exact scan
|
|
256
|
+
}
|
|
257
|
+
}
|
|
207
258
|
const candidates = [];
|
|
208
259
|
for (const [agentType, embedding] of Array.from(this.intentEmbeddings.entries())) {
|
|
209
260
|
const similarity = this.cosineSimilarity(queryEmbedding, embedding);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SemanticRouter.js","sourceRoot":"","sources":["../../src/routing/SemanticRouter.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Semantic Router - HNSW-Powered Intent Matching\n *\n * Integrates @ruvector/router for sub-10ms semantic routing.\n *\n * Features:\n * - HNSW (Hierarchical Navigable Small World) index\n * - Intent classification for 66+ agents\n * - Sub-10ms routing latency\n * - Automatic intent embedding and indexing\n * - Multi-intent detection\n *\n * Performance:\n * - <10ms routing time\n * - >85% routing accuracy\n * - Support for 66+ agent types\n * - O(log N) search complexity\n */\n\n// Import from agentdb package\nimport type { EmbeddingService } from 'agentdb';\n\nexport interface AgentIntent {\n /** Agent type identifier */\n agentType: string;\n /** Natural language description of agent capabilities */\n description: string;\n /** Example tasks for this agent */\n examples: string[];\n /** Agent specialty tags */\n tags: string[];\n}\n\nexport interface RoutingResult {\n /** Primary agent selection */\n primaryAgent: string;\n /** Confidence score (0-1) */\n confidence: number;\n /** Secondary agent suggestions */\n alternatives: Array<{\n agentType: string;\n confidence: number;\n }>;\n /** Matched intent descriptions */\n matchedIntents: string[];\n /** Routing metrics */\n metrics: {\n routingTimeMs: number;\n embeddingTimeMs: number;\n searchTimeMs: number;\n candidatesEvaluated: number;\n };\n}\n\nexport interface MultiIntentResult {\n /** Detected intents in order of confidence */\n intents: Array<{\n agentType: string;\n confidence: number;\n matchedText: string;\n }>;\n /** Whether task requires multiple agents */\n requiresMultiAgent: boolean;\n /** Suggested execution order */\n executionOrder: string[];\n}\n\n/**\n * Semantic Router\n *\n * Provides intent-based agent routing:\n * 1. Register agent intents with descriptions\n * 2. Build HNSW index for fast semantic search\n * 3. Route tasks to agents based on intent similarity\n * 4. Support multi-intent detection for complex tasks\n */\nexport class SemanticRouter {\n private embedder: EmbeddingService;\n\n // Agent registry\n private agentIntents: Map<string, AgentIntent>;\n private intentEmbeddings: Map<string, Float32Array>;\n\n // HNSW index simulation (production would use @ruvector/router)\n private indexBuilt: boolean = false;\n\n // Performance tracking\n private routingStats: {\n totalRoutes: number;\n avgRoutingTimeMs: number;\n accuracyRate: number; // Requires feedback\n };\n\n constructor(embedder: EmbeddingService) {\n this.embedder = embedder;\n this.agentIntents = new Map();\n this.intentEmbeddings = new Map();\n this.routingStats = {\n totalRoutes: 0,\n avgRoutingTimeMs: 0,\n accuracyRate: 0,\n };\n }\n\n /**\n * Register agent intent for routing\n *\n * @param intent - Agent intent configuration\n */\n async registerAgent(intent: AgentIntent): Promise<void> {\n this.agentIntents.set(intent.agentType, intent);\n\n // Generate embedding from description + examples\n const intentText = [\n intent.description,\n ...intent.examples,\n ...intent.tags,\n ].join(' ');\n\n const embedding = await this.embedder.embed(intentText);\n this.intentEmbeddings.set(intent.agentType, embedding);\n\n // Mark index as needing rebuild\n this.indexBuilt = false;\n }\n\n /**\n * Register multiple agents in batch\n *\n * @param intents - Array of agent intents\n */\n async registerAgents(intents: AgentIntent[]): Promise<void> {\n await Promise.all(intents.map(intent => this.registerAgent(intent)));\n }\n\n /**\n * Build HNSW index for fast routing\n *\n * In production, this would use @ruvector/router's native HNSW.\n * For this implementation, we use a simplified version.\n */\n buildIndex(): void {\n // In production: Initialize HNSW with intentEmbeddings\n // For now, we'll use brute-force search (still fast for 66 agents)\n this.indexBuilt = true;\n }\n\n /**\n * Route task to best agent using semantic similarity\n *\n * Process:\n * 1. Embed task description\n * 2. Search HNSW index for nearest intents\n * 3. Return top matches with confidence scores\n *\n * @param taskDescription - Natural language task description\n * @param k - Number of alternatives to return (default: 3)\n * @returns Routing result with primary agent and alternatives\n */\n async route(taskDescription: string, k: number = 3): Promise<RoutingResult> {\n const overallStartTime = performance.now();\n\n if (!this.indexBuilt) {\n this.buildIndex();\n }\n\n // Step 1: Embed task\n const embeddingStartTime = performance.now();\n const taskEmbedding = await this.embedder.embed(taskDescription);\n const embeddingTimeMs = performance.now() - embeddingStartTime;\n\n // Step 2: Search HNSW index\n const searchStartTime = performance.now();\n const candidates = this.searchHNSW(taskEmbedding, k + 1);\n const searchTimeMs = performance.now() - searchStartTime;\n\n if (candidates.length === 0) {\n throw new Error('No agents registered for routing');\n }\n\n // Step 3: Extract results\n const primaryAgent = candidates[0].agentType;\n const confidence = candidates[0].similarity;\n const alternatives = candidates.slice(1, k + 1).map(c => ({\n agentType: c.agentType,\n confidence: c.similarity,\n }));\n\n const matchedIntents = candidates\n .slice(0, k + 1)\n .map(c => this.agentIntents.get(c.agentType)?.description ?? '');\n\n const routingTimeMs = performance.now() - overallStartTime;\n\n // Update stats\n this.updateStats(routingTimeMs);\n\n return {\n primaryAgent,\n confidence,\n alternatives,\n matchedIntents,\n metrics: {\n routingTimeMs,\n embeddingTimeMs,\n searchTimeMs,\n candidatesEvaluated: this.agentIntents.size,\n },\n };\n }\n\n /**\n * Detect multiple intents in complex task\n *\n * Useful for tasks requiring coordination of multiple agents.\n *\n * @param taskDescription - Task that may require multiple agents\n * @param threshold - Minimum confidence for intent detection (default: 0.6)\n * @returns Multi-intent result with suggested execution order\n */\n async detectMultiIntent(\n taskDescription: string,\n threshold: number = 0.6\n ): Promise<MultiIntentResult> {\n // Split task into sentences or clauses\n const segments = this.segmentTask(taskDescription);\n\n // Route each segment\n const segmentResults = await Promise.all(\n segments.map(async segment => {\n const result = await this.route(segment.text, 1);\n return {\n ...result,\n matchedText: segment.text,\n };\n })\n );\n\n // Collect high-confidence intents\n const intents = segmentResults\n .filter(r => r.confidence >= threshold)\n .map(r => ({\n agentType: r.primaryAgent,\n confidence: r.confidence,\n matchedText: r.matchedText,\n }));\n\n // Deduplicate and order by confidence\n const uniqueIntents = this.deduplicateIntents(intents);\n const requiresMultiAgent = uniqueIntents.length > 1;\n\n // Suggest execution order based on dependencies\n const executionOrder = this.inferExecutionOrder(uniqueIntents, taskDescription);\n\n return {\n intents: uniqueIntents,\n requiresMultiAgent,\n executionOrder,\n };\n }\n\n /**\n * Get routing statistics\n *\n * @returns Cumulative routing metrics\n */\n getStats(): typeof this.routingStats {\n return { ...this.routingStats };\n }\n\n /**\n * Get all registered agents\n *\n * @returns Array of registered agent intents\n */\n getRegisteredAgents(): AgentIntent[] {\n return Array.from(this.agentIntents.values());\n }\n\n // ========================================================================\n // Private Helper Methods\n // ========================================================================\n\n /**\n * Search HNSW index for nearest neighbors\n *\n * In production, this would use @ruvector/router's native HNSW.\n * For this implementation, we use brute-force cosine similarity.\n *\n * @param queryEmbedding - Query vector\n * @param k - Number of results\n * @returns Top k candidates with similarity scores\n */\n private searchHNSW(queryEmbedding: Float32Array, k: number): Array<{\n agentType: string;\n similarity: number;\n }> {\n const candidates: Array<{ agentType: string; similarity: number }> = [];\n\n for (const [agentType, embedding] of Array.from(this.intentEmbeddings.entries())) {\n const similarity = this.cosineSimilarity(queryEmbedding, embedding);\n candidates.push({ agentType, similarity });\n }\n\n // Sort by similarity (descending)\n candidates.sort((a, b) => b.similarity - a.similarity);\n\n return candidates.slice(0, k);\n }\n\n /**\n * Calculate cosine similarity\n */\n private cosineSimilarity(a: Float32Array, b: Float32Array): number {\n if (a.length !== b.length) {\n throw new Error('Vectors must have same length');\n }\n\n let dotProduct = 0;\n let normA = 0;\n let normB = 0;\n\n for (let i = 0; i < a.length; i++) {\n dotProduct += a[i] * b[i];\n normA += a[i] * a[i];\n normB += b[i] * b[i];\n }\n\n const denom = Math.sqrt(normA) * Math.sqrt(normB);\n return denom === 0 ? 0 : dotProduct / denom;\n }\n\n /**\n * Segment task into independent clauses\n */\n private segmentTask(taskDescription: string): Array<{ text: string; index: number }> {\n // Split by sentences and coordination conjunctions\n const sentences = taskDescription.split(/[.!?]+/).filter(s => s.trim());\n\n const segments: Array<{ text: string; index: number }> = [];\n\n sentences.forEach((sentence, idx) => {\n // Further split by \"and\", \"then\", etc.\n const subSegments = sentence.split(/\\b(and|then|after|before)\\b/i);\n\n subSegments\n .filter((_, i) => i % 2 === 0) // Skip conjunctions\n .forEach(segment => {\n const trimmed = segment.trim();\n if (trimmed) {\n segments.push({ text: trimmed, index: idx });\n }\n });\n });\n\n return segments.length > 0 ? segments : [{ text: taskDescription, index: 0 }];\n }\n\n /**\n * Deduplicate intents by agent type\n */\n private deduplicateIntents(\n intents: Array<{ agentType: string; confidence: number; matchedText: string }>\n ): Array<{ agentType: string; confidence: number; matchedText: string }> {\n const seen = new Map<string, typeof intents[0]>();\n\n for (const intent of intents) {\n const existing = seen.get(intent.agentType);\n if (!existing || intent.confidence > existing.confidence) {\n seen.set(intent.agentType, intent);\n }\n }\n\n return Array.from(seen.values()).sort((a, b) => b.confidence - a.confidence);\n }\n\n /**\n * Infer execution order from intents and task description\n */\n private inferExecutionOrder(\n intents: Array<{ agentType: string; confidence: number; matchedText: string }>,\n taskDescription: string\n ): string[] {\n // Simple heuristic: order by position in original text\n const taskLower = taskDescription.toLowerCase();\n\n const withPositions = intents.map(intent => {\n const position = taskLower.indexOf(intent.matchedText.toLowerCase());\n return { ...intent, position };\n });\n\n withPositions.sort((a, b) => a.position - b.position);\n\n return withPositions.map(i => i.agentType);\n }\n\n /**\n * Update routing statistics\n */\n private updateStats(routingTimeMs: number): void {\n this.routingStats.totalRoutes++;\n\n const alpha = 0.1; // EMA smoothing\n this.routingStats.avgRoutingTimeMs =\n this.routingStats.avgRoutingTimeMs * (1 - alpha) + routingTimeMs * alpha;\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"SemanticRouter.js","sourceRoot":"","sources":["../../src/routing/SemanticRouter.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Semantic Router - HNSW-Powered Intent Matching\n *\n * Uses @ruvector/router's native HNSW index (VectorDb) when the package and\n * its platform binary are installed, and an exact brute-force cosine scan\n * otherwise. Both return the same ranking contract: similarity in [-1, 1],\n * highest first.\n *\n * Features:\n * - HNSW (Hierarchical Navigable Small World) index\n * - Intent classification for 66+ agents\n * - Sub-10ms routing latency\n * - Automatic intent embedding and indexing\n * - Multi-intent detection\n *\n * Performance:\n * - <10ms routing time\n * - >85% routing accuracy\n * - Support for 66+ agent types\n * - O(log N) search complexity\n */\n\n// Import from agentdb package\nimport type { EmbeddingService } from 'agentdb';\nimport { requireOptional } from '../integrations/optional.js';\n\n/** Structural subset of @ruvector/router's native VectorDb. */\ninterface NativeVectorDb {\n insert(id: string, vector: Float32Array): string;\n search(query: Float32Array, k: number): Array<{ id: string; score: number }>;\n}\ninterface RuvectorRouterModule {\n VectorDb: new (options: { dimensions: number; distanceMetric?: number }) => NativeVectorDb;\n DistanceMetric: { Cosine: number };\n}\n\nexport type SemanticIndexBackend = 'ruvector-router' | 'brute-force';\n\nexport interface AgentIntent {\n /** Agent type identifier */\n agentType: string;\n /** Natural language description of agent capabilities */\n description: string;\n /** Example tasks for this agent */\n examples: string[];\n /** Agent specialty tags */\n tags: string[];\n}\n\nexport interface RoutingResult {\n /** Primary agent selection */\n primaryAgent: string;\n /** Confidence score (0-1) */\n confidence: number;\n /** Secondary agent suggestions */\n alternatives: Array<{\n agentType: string;\n confidence: number;\n }>;\n /** Matched intent descriptions */\n matchedIntents: string[];\n /** Routing metrics */\n metrics: {\n routingTimeMs: number;\n embeddingTimeMs: number;\n searchTimeMs: number;\n candidatesEvaluated: number;\n };\n}\n\nexport interface MultiIntentResult {\n /** Detected intents in order of confidence */\n intents: Array<{\n agentType: string;\n confidence: number;\n matchedText: string;\n }>;\n /** Whether task requires multiple agents */\n requiresMultiAgent: boolean;\n /** Suggested execution order */\n executionOrder: string[];\n}\n\n/**\n * Semantic Router\n *\n * Provides intent-based agent routing:\n * 1. Register agent intents with descriptions\n * 2. Build HNSW index for fast semantic search\n * 3. Route tasks to agents based on intent similarity\n * 4. Support multi-intent detection for complex tasks\n */\nexport class SemanticRouter {\n private embedder: EmbeddingService;\n\n // Agent registry\n private agentIntents: Map<string, AgentIntent>;\n private intentEmbeddings: Map<string, Float32Array>;\n\n // Native HNSW index (@ruvector/router) or null for the brute-force scan\n private indexBuilt: boolean = false;\n private nativeIndex: NativeVectorDb | null = null;\n private backend: SemanticIndexBackend = 'brute-force';\n private readonly useNative: boolean;\n\n // Performance tracking\n private routingStats: {\n totalRoutes: number;\n avgRoutingTimeMs: number;\n accuracyRate: number; // Requires feedback\n };\n\n /**\n * @param embedder - Embedding service for intents and tasks\n * @param options.native - Use @ruvector/router when installed (default true)\n */\n constructor(embedder: EmbeddingService, options: { native?: boolean } = {}) {\n this.embedder = embedder;\n this.useNative = options.native ?? true;\n this.agentIntents = new Map();\n this.intentEmbeddings = new Map();\n this.routingStats = {\n totalRoutes: 0,\n avgRoutingTimeMs: 0,\n accuracyRate: 0,\n };\n }\n\n /**\n * Register agent intent for routing\n *\n * @param intent - Agent intent configuration\n */\n async registerAgent(intent: AgentIntent): Promise<void> {\n this.agentIntents.set(intent.agentType, intent);\n\n // Generate embedding from description + examples\n const intentText = [\n intent.description,\n ...intent.examples,\n ...intent.tags,\n ].join(' ');\n\n const embedding = await this.embedder.embed(intentText);\n this.intentEmbeddings.set(intent.agentType, embedding);\n\n // Mark index as needing rebuild\n this.indexBuilt = false;\n }\n\n /**\n * Register multiple agents in batch\n *\n * @param intents - Array of agent intents\n */\n async registerAgents(intents: AgentIntent[]): Promise<void> {\n await Promise.all(intents.map(intent => this.registerAgent(intent)));\n }\n\n /**\n * Build the routing index.\n *\n * Loads @ruvector/router's native HNSW (VectorDb, cosine metric) when it is\n * installed; otherwise routing uses an exact brute-force scan, which is\n * still fast at the ~66-agent scale.\n */\n buildIndex(): void {\n this.nativeIndex = null;\n this.backend = 'brute-force';\n const first = this.intentEmbeddings.values().next().value as Float32Array | undefined;\n const router = this.useNative && first\n ? requireOptional<RuvectorRouterModule>('@ruvector/router')\n : null;\n if (router && first) {\n try {\n const db = new router.VectorDb({\n dimensions: first.length,\n distanceMetric: router.DistanceMetric.Cosine,\n });\n for (const [agentType, embedding] of Array.from(this.intentEmbeddings.entries())) {\n db.insert(agentType, embedding instanceof Float32Array ? embedding : Float32Array.from(embedding));\n }\n this.nativeIndex = db;\n this.backend = 'ruvector-router';\n } catch {\n // Native binary missing for this platform, or a dimension mismatch:\n // keep the exact brute-force path.\n this.nativeIndex = null;\n }\n }\n this.indexBuilt = true;\n }\n\n /** Which index answered the last build: native HNSW or brute force. */\n getIndexBackend(): SemanticIndexBackend {\n return this.backend;\n }\n\n /**\n * Route task to best agent using semantic similarity\n *\n * Process:\n * 1. Embed task description\n * 2. Search HNSW index for nearest intents\n * 3. Return top matches with confidence scores\n *\n * @param taskDescription - Natural language task description\n * @param k - Number of alternatives to return (default: 3)\n * @returns Routing result with primary agent and alternatives\n */\n async route(taskDescription: string, k: number = 3): Promise<RoutingResult> {\n const overallStartTime = performance.now();\n\n if (!this.indexBuilt) {\n this.buildIndex();\n }\n\n // Step 1: Embed task\n const embeddingStartTime = performance.now();\n const taskEmbedding = await this.embedder.embed(taskDescription);\n const embeddingTimeMs = performance.now() - embeddingStartTime;\n\n // Step 2: Search HNSW index\n const searchStartTime = performance.now();\n const candidates = this.searchHNSW(taskEmbedding, k + 1);\n const searchTimeMs = performance.now() - searchStartTime;\n\n if (candidates.length === 0) {\n throw new Error('No agents registered for routing');\n }\n\n // Step 3: Extract results\n const primaryAgent = candidates[0].agentType;\n const confidence = candidates[0].similarity;\n const alternatives = candidates.slice(1, k + 1).map(c => ({\n agentType: c.agentType,\n confidence: c.similarity,\n }));\n\n const matchedIntents = candidates\n .slice(0, k + 1)\n .map(c => this.agentIntents.get(c.agentType)?.description ?? '');\n\n const routingTimeMs = performance.now() - overallStartTime;\n\n // Update stats\n this.updateStats(routingTimeMs);\n\n return {\n primaryAgent,\n confidence,\n alternatives,\n matchedIntents,\n metrics: {\n routingTimeMs,\n embeddingTimeMs,\n searchTimeMs,\n candidatesEvaluated: this.agentIntents.size,\n },\n };\n }\n\n /**\n * Detect multiple intents in complex task\n *\n * Useful for tasks requiring coordination of multiple agents.\n *\n * @param taskDescription - Task that may require multiple agents\n * @param threshold - Minimum confidence for intent detection (default: 0.6)\n * @returns Multi-intent result with suggested execution order\n */\n async detectMultiIntent(\n taskDescription: string,\n threshold: number = 0.6\n ): Promise<MultiIntentResult> {\n // Split task into sentences or clauses\n const segments = this.segmentTask(taskDescription);\n\n // Route each segment\n const segmentResults = await Promise.all(\n segments.map(async segment => {\n const result = await this.route(segment.text, 1);\n return {\n ...result,\n matchedText: segment.text,\n };\n })\n );\n\n // Collect high-confidence intents\n const intents = segmentResults\n .filter(r => r.confidence >= threshold)\n .map(r => ({\n agentType: r.primaryAgent,\n confidence: r.confidence,\n matchedText: r.matchedText,\n }));\n\n // Deduplicate and order by confidence\n const uniqueIntents = this.deduplicateIntents(intents);\n const requiresMultiAgent = uniqueIntents.length > 1;\n\n // Suggest execution order based on dependencies\n const executionOrder = this.inferExecutionOrder(uniqueIntents, taskDescription);\n\n return {\n intents: uniqueIntents,\n requiresMultiAgent,\n executionOrder,\n };\n }\n\n /**\n * Get routing statistics\n *\n * @returns Cumulative routing metrics\n */\n getStats(): typeof this.routingStats {\n return { ...this.routingStats };\n }\n\n /**\n * Get all registered agents\n *\n * @returns Array of registered agent intents\n */\n getRegisteredAgents(): AgentIntent[] {\n return Array.from(this.agentIntents.values());\n }\n\n // ========================================================================\n // Private Helper Methods\n // ========================================================================\n\n /**\n * Search the index for nearest neighbours.\n *\n * @ruvector/router reports cosine *distance* (0 = identical), so it is\n * converted to similarity (1 - distance) to keep \"higher is better\".\n *\n * @param queryEmbedding - Query vector\n * @param k - Number of results\n * @returns Top k candidates with similarity scores, highest first\n */\n private searchHNSW(queryEmbedding: Float32Array, k: number): Array<{\n agentType: string;\n similarity: number;\n }> {\n if (this.nativeIndex) {\n try {\n const query = queryEmbedding instanceof Float32Array ? queryEmbedding : Float32Array.from(queryEmbedding);\n return this.nativeIndex\n .search(query, Math.min(k, this.intentEmbeddings.size))\n .map((r) => ({ agentType: r.id, similarity: 1 - r.score }))\n .sort((a, b) => b.similarity - a.similarity);\n } catch {\n // fall through to the exact scan\n }\n }\n\n const candidates: Array<{ agentType: string; similarity: number }> = [];\n\n for (const [agentType, embedding] of Array.from(this.intentEmbeddings.entries())) {\n const similarity = this.cosineSimilarity(queryEmbedding, embedding);\n candidates.push({ agentType, similarity });\n }\n\n // Sort by similarity (descending)\n candidates.sort((a, b) => b.similarity - a.similarity);\n\n return candidates.slice(0, k);\n }\n\n /**\n * Calculate cosine similarity\n */\n private cosineSimilarity(a: Float32Array, b: Float32Array): number {\n if (a.length !== b.length) {\n throw new Error('Vectors must have same length');\n }\n\n let dotProduct = 0;\n let normA = 0;\n let normB = 0;\n\n for (let i = 0; i < a.length; i++) {\n dotProduct += a[i] * b[i];\n normA += a[i] * a[i];\n normB += b[i] * b[i];\n }\n\n const denom = Math.sqrt(normA) * Math.sqrt(normB);\n return denom === 0 ? 0 : dotProduct / denom;\n }\n\n /**\n * Segment task into independent clauses\n */\n private segmentTask(taskDescription: string): Array<{ text: string; index: number }> {\n // Split by sentences and coordination conjunctions\n const sentences = taskDescription.split(/[.!?]+/).filter(s => s.trim());\n\n const segments: Array<{ text: string; index: number }> = [];\n\n sentences.forEach((sentence, idx) => {\n // Further split by \"and\", \"then\", etc.\n const subSegments = sentence.split(/\\b(and|then|after|before)\\b/i);\n\n subSegments\n .filter((_, i) => i % 2 === 0) // Skip conjunctions\n .forEach(segment => {\n const trimmed = segment.trim();\n if (trimmed) {\n segments.push({ text: trimmed, index: idx });\n }\n });\n });\n\n return segments.length > 0 ? segments : [{ text: taskDescription, index: 0 }];\n }\n\n /**\n * Deduplicate intents by agent type\n */\n private deduplicateIntents(\n intents: Array<{ agentType: string; confidence: number; matchedText: string }>\n ): Array<{ agentType: string; confidence: number; matchedText: string }> {\n const seen = new Map<string, typeof intents[0]>();\n\n for (const intent of intents) {\n const existing = seen.get(intent.agentType);\n if (!existing || intent.confidence > existing.confidence) {\n seen.set(intent.agentType, intent);\n }\n }\n\n return Array.from(seen.values()).sort((a, b) => b.confidence - a.confidence);\n }\n\n /**\n * Infer execution order from intents and task description\n */\n private inferExecutionOrder(\n intents: Array<{ agentType: string; confidence: number; matchedText: string }>,\n taskDescription: string\n ): string[] {\n // Simple heuristic: order by position in original text\n const taskLower = taskDescription.toLowerCase();\n\n const withPositions = intents.map(intent => {\n const position = taskLower.indexOf(intent.matchedText.toLowerCase());\n return { ...intent, position };\n });\n\n withPositions.sort((a, b) => a.position - b.position);\n\n return withPositions.map(i => i.agentType);\n }\n\n /**\n * Update routing statistics\n */\n private updateStats(routingTimeMs: number): void {\n this.routingStats.totalRoutes++;\n\n const alpha = 0.1; // EMA smoothing\n this.routingStats.avgRoutingTimeMs =\n this.routingStats.avgRoutingTimeMs * (1 - alpha) + routingTimeMs * alpha;\n }\n}\n"]}
|
|
@@ -9,6 +9,20 @@ export declare class SonaUnavailableError extends Error {
|
|
|
9
9
|
constructor(cause: unknown);
|
|
10
10
|
}
|
|
11
11
|
export declare function isSonaAvailable(): boolean;
|
|
12
|
-
/**
|
|
12
|
+
/**
|
|
13
|
+
* Validate LoRA inputs before they reach the native engine.
|
|
14
|
+
*
|
|
15
|
+
* The vector given to applyMicroLora / applyBaseLora must have exactly
|
|
16
|
+
* hiddenDim entries. @ruvector/sona <= 0.1.8 asserted that in Rust, so a
|
|
17
|
+
* mismatch panicked across the NAPI boundary and aborted the whole Node
|
|
18
|
+
* process; 0.1.9+ throws. The package range requires a fixed release, and the
|
|
19
|
+
* check here keeps the error the same (a RangeError naming hiddenDim) even if
|
|
20
|
+
* an older copy is resolved, e.g. one nested under another dependency.
|
|
21
|
+
*/
|
|
22
|
+
export declare function guardSonaEngine<T extends object>(engine: T, hiddenDim: number): T;
|
|
23
|
+
/**
|
|
24
|
+
* The SonaEngine class (instances validated by guardSonaEngine), or a
|
|
25
|
+
* SonaUnavailableError if it could not be loaded.
|
|
26
|
+
*/
|
|
13
27
|
export declare function requireSonaEngine(): any;
|
|
14
28
|
//# sourceMappingURL=sona-loader.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sona-loader.d.ts","sourceRoot":"","sources":["../../src/services/sona-loader.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAWH,qBAAa,oBAAqB,SAAQ,KAAK;gBACjC,KAAK,EAAE,OAAO;CAS3B;AAED,wBAAgB,eAAe,IAAI,OAAO,CAEzC;AAED,
|
|
1
|
+
{"version":3,"file":"sona-loader.d.ts","sourceRoot":"","sources":["../../src/services/sona-loader.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAWH,qBAAa,oBAAqB,SAAQ,KAAK;gBACjC,KAAK,EAAE,OAAO;CAS3B;AAED,wBAAgB,eAAe,IAAI,OAAO,CAEzC;AAED;;;;;;;;;GASG;AACH,wBAAgB,eAAe,CAAC,CAAC,SAAS,MAAM,EAAE,MAAM,EAAE,CAAC,EAAE,SAAS,EAAE,MAAM,GAAG,CAAC,CA0BjF;AAcD;;;GAGG;AACH,wBAAgB,iBAAiB,IAAI,GAAG,CAMvC"}
|
|
@@ -25,11 +25,63 @@ export class SonaUnavailableError extends Error {
|
|
|
25
25
|
export function isSonaAvailable() {
|
|
26
26
|
return sonaEngineClass !== null;
|
|
27
27
|
}
|
|
28
|
-
/**
|
|
28
|
+
/**
|
|
29
|
+
* Validate LoRA inputs before they reach the native engine.
|
|
30
|
+
*
|
|
31
|
+
* The vector given to applyMicroLora / applyBaseLora must have exactly
|
|
32
|
+
* hiddenDim entries. @ruvector/sona <= 0.1.8 asserted that in Rust, so a
|
|
33
|
+
* mismatch panicked across the NAPI boundary and aborted the whole Node
|
|
34
|
+
* process; 0.1.9+ throws. The package range requires a fixed release, and the
|
|
35
|
+
* check here keeps the error the same (a RangeError naming hiddenDim) even if
|
|
36
|
+
* an older copy is resolved, e.g. one nested under another dependency.
|
|
37
|
+
*/
|
|
38
|
+
export function guardSonaEngine(engine, hiddenDim) {
|
|
39
|
+
const e = engine;
|
|
40
|
+
if (!e || !Number.isInteger(hiddenDim) || hiddenDim <= 0)
|
|
41
|
+
return engine;
|
|
42
|
+
const check = (method, input) => {
|
|
43
|
+
if (!Array.isArray(input) && !ArrayBuffer.isView(input)) {
|
|
44
|
+
throw new TypeError(`SonaEngine.${method}: input must be an array of numbers`);
|
|
45
|
+
}
|
|
46
|
+
const length = input.length;
|
|
47
|
+
if (length !== hiddenDim) {
|
|
48
|
+
throw new RangeError(`SonaEngine.${method}: input has ${length} values, the engine's hiddenDim is ${hiddenDim}`);
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
for (const method of ['applyMicroLora', 'applyBaseLora']) {
|
|
52
|
+
const original = e[method];
|
|
53
|
+
if (typeof original !== 'function')
|
|
54
|
+
continue;
|
|
55
|
+
const inputAt = method === 'applyBaseLora' ? 1 : 0;
|
|
56
|
+
Object.defineProperty(e, method, {
|
|
57
|
+
configurable: true,
|
|
58
|
+
writable: true,
|
|
59
|
+
value: (...args) => {
|
|
60
|
+
check(method, args[inputAt]);
|
|
61
|
+
return original.apply(e, args);
|
|
62
|
+
},
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
return engine;
|
|
66
|
+
}
|
|
67
|
+
let guardedClass = null;
|
|
68
|
+
function guardedSonaEngineClass(Native) {
|
|
69
|
+
const Guarded = function SonaEngine(hiddenDim) {
|
|
70
|
+
return guardSonaEngine(new Native(hiddenDim), hiddenDim);
|
|
71
|
+
};
|
|
72
|
+
Guarded.withConfig = (config) => guardSonaEngine(Native.withConfig(config), config?.hiddenDim);
|
|
73
|
+
Guarded.native = Native;
|
|
74
|
+
return Guarded;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* The SonaEngine class (instances validated by guardSonaEngine), or a
|
|
78
|
+
* SonaUnavailableError if it could not be loaded.
|
|
79
|
+
*/
|
|
29
80
|
export function requireSonaEngine() {
|
|
30
81
|
if (!sonaEngineClass) {
|
|
31
82
|
throw new SonaUnavailableError(loadError ?? 'module did not export SonaEngine');
|
|
32
83
|
}
|
|
33
|
-
|
|
84
|
+
guardedClass ??= guardedSonaEngineClass(sonaEngineClass);
|
|
85
|
+
return guardedClass;
|
|
34
86
|
}
|
|
35
87
|
//# sourceMappingURL=sona-loader.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sona-loader.js","sourceRoot":"","sources":["../../src/services/sona-loader.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,IAAI,eAAe,GAAQ,IAAI,CAAC;AAChC,IAAI,SAAS,GAAY,IAAI,CAAC;AAE9B,IAAI,CAAC;IACH,CAAC,EAAE,UAAU,EAAE,eAAe,EAAE,GAAG,MAAM,MAAM,CAAC,gBAAgB,CAAC,CAAC,CAAC;AACrE,CAAC;AAAC,OAAO,KAAK,EAAE,CAAC;IACf,SAAS,GAAG,KAAK,CAAC;AACpB,CAAC;AAED,MAAM,OAAO,oBAAqB,SAAQ,KAAK;IAC7C,YAAY,KAAc;QACxB,MAAM,MAAM,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACtE,KAAK,CACH,kEAAkE;YAChE,8EAA8E;YAC9E,gBAAgB,MAAM,GAAG,CAC5B,CAAC;QACF,IAAI,CAAC,IAAI,GAAG,sBAAsB,CAAC;IACrC,CAAC;CACF;AAED,MAAM,UAAU,eAAe;IAC7B,OAAO,eAAe,KAAK,IAAI,CAAC;AAClC,CAAC;AAED,
|
|
1
|
+
{"version":3,"file":"sona-loader.js","sourceRoot":"","sources":["../../src/services/sona-loader.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Loader for the optional @ruvector/sona native engine.\n *\n * @ruvector/sona is an optionalDependency, so importing the SONA services must\n * not fail when it is absent. Constructing an engine without it throws a\n * SonaUnavailableError that says how to install it.\n */\n\nlet sonaEngineClass: any = null;\nlet loadError: unknown = null;\n\ntry {\n ({ SonaEngine: sonaEngineClass } = await import('@ruvector/sona'));\n} catch (error) {\n loadError = error;\n}\n\nexport class SonaUnavailableError extends Error {\n constructor(cause: unknown) {\n const detail = cause instanceof Error ? cause.message : String(cause);\n super(\n '@ruvector/sona is not available, so SONA features are disabled. ' +\n 'It is an optional dependency; install it with `npm install @ruvector/sona`. ' +\n `(load error: ${detail})`\n );\n this.name = 'SonaUnavailableError';\n }\n}\n\nexport function isSonaAvailable(): boolean {\n return sonaEngineClass !== null;\n}\n\n/**\n * Validate LoRA inputs before they reach the native engine.\n *\n * The vector given to applyMicroLora / applyBaseLora must have exactly\n * hiddenDim entries. @ruvector/sona <= 0.1.8 asserted that in Rust, so a\n * mismatch panicked across the NAPI boundary and aborted the whole Node\n * process; 0.1.9+ throws. The package range requires a fixed release, and the\n * check here keeps the error the same (a RangeError naming hiddenDim) even if\n * an older copy is resolved, e.g. one nested under another dependency.\n */\nexport function guardSonaEngine<T extends object>(engine: T, hiddenDim: number): T {\n const e = engine as any;\n if (!e || !Number.isInteger(hiddenDim) || hiddenDim <= 0) return engine;\n const check = (method: string, input: unknown) => {\n if (!Array.isArray(input) && !ArrayBuffer.isView(input)) {\n throw new TypeError(`SonaEngine.${method}: input must be an array of numbers`);\n }\n const length = (input as ArrayLike<number>).length;\n if (length !== hiddenDim) {\n throw new RangeError(`SonaEngine.${method}: input has ${length} values, the engine's hiddenDim is ${hiddenDim}`);\n }\n };\n for (const method of ['applyMicroLora', 'applyBaseLora'] as const) {\n const original = e[method];\n if (typeof original !== 'function') continue;\n const inputAt = method === 'applyBaseLora' ? 1 : 0;\n Object.defineProperty(e, method, {\n configurable: true,\n writable: true,\n value: (...args: unknown[]) => {\n check(method, args[inputAt]);\n return original.apply(e, args);\n },\n });\n }\n return engine;\n}\n\nlet guardedClass: any = null;\n\nfunction guardedSonaEngineClass(Native: any): any {\n const Guarded: any = function SonaEngine(hiddenDim: number) {\n return guardSonaEngine(new Native(hiddenDim), hiddenDim);\n };\n Guarded.withConfig = (config: { hiddenDim: number }) =>\n guardSonaEngine(Native.withConfig(config), config?.hiddenDim);\n Guarded.native = Native;\n return Guarded;\n}\n\n/**\n * The SonaEngine class (instances validated by guardSonaEngine), or a\n * SonaUnavailableError if it could not be loaded.\n */\nexport function requireSonaEngine(): any {\n if (!sonaEngineClass) {\n throw new SonaUnavailableError(loadError ?? 'module did not export SonaEngine');\n }\n guardedClass ??= guardedSonaEngineClass(sonaEngineClass);\n return guardedClass;\n}\n"]}
|
|
@@ -4,9 +4,10 @@
|
|
|
4
4
|
* Provides secure input validation for RuVector integration:
|
|
5
5
|
* - Task description validation
|
|
6
6
|
* - Configuration validation
|
|
7
|
-
* - Injection attack prevention
|
|
7
|
+
* - Injection attack prevention (prompt injection via aidefence when installed)
|
|
8
8
|
* - Resource exhaustion prevention
|
|
9
9
|
*/
|
|
10
|
+
import { type InjectionScan } from '../integrations/prompt-injection.js';
|
|
10
11
|
export interface ValidationOptions {
|
|
11
12
|
maxLength?: number;
|
|
12
13
|
minLength?: number;
|
|
@@ -17,16 +18,23 @@ export declare class ValidationError extends Error {
|
|
|
17
18
|
field?: string;
|
|
18
19
|
constructor(message: string, field?: string);
|
|
19
20
|
}
|
|
21
|
+
/** Thrown when task text is rejected by the prompt-injection policy. */
|
|
22
|
+
export declare class PromptInjectionError extends ValidationError {
|
|
23
|
+
scan: InjectionScan;
|
|
24
|
+
constructor(scan: InjectionScan, field?: string);
|
|
25
|
+
}
|
|
20
26
|
/**
|
|
21
27
|
* Input Validator
|
|
22
28
|
*
|
|
23
29
|
* Validates all external inputs to prevent:
|
|
24
|
-
* - Injection attacks (XSS, SQL injection, prompt injection
|
|
30
|
+
* - Injection attacks (XSS, SQL injection, and prompt injection — the latter
|
|
31
|
+
* through `scanPromptInjection`, see integrations/prompt-injection.ts)
|
|
25
32
|
* - Resource exhaustion (excessive length, recursion)
|
|
26
33
|
* - Malicious content (scripts, control characters)
|
|
27
34
|
*/
|
|
28
35
|
export declare class InputValidator {
|
|
29
36
|
private static readonly SUSPICIOUS_PATTERNS;
|
|
37
|
+
private static readonly warnedInjections;
|
|
30
38
|
private static readonly CONTROL_CHARS_REGEX;
|
|
31
39
|
/**
|
|
32
40
|
* Validate task description
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"input-validator.d.ts","sourceRoot":"","sources":["../../src/utils/input-validator.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,MAAM,WAAW,iBAAiB;IAChC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,qBAAa,eAAgB,SAAQ,KAAK;IACJ,KAAK,CAAC,EAAE,MAAM;gBAAtC,OAAO,EAAE,MAAM,EAAS,KAAK,CAAC,EAAE,MAAM;CAInD;AAED
|
|
1
|
+
{"version":3,"file":"input-validator.d.ts","sourceRoot":"","sources":["../../src/utils/input-validator.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAuB,KAAK,aAAa,EAAE,MAAM,qCAAqC,CAAC;AAE9F,MAAM,WAAW,iBAAiB;IAChC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,qBAAa,eAAgB,SAAQ,KAAK;IACJ,KAAK,CAAC,EAAE,MAAM;gBAAtC,OAAO,EAAE,MAAM,EAAS,KAAK,CAAC,EAAE,MAAM;CAInD;AAED,wEAAwE;AACxE,qBAAa,oBAAqB,SAAQ,eAAe;IACpC,IAAI,EAAE,aAAa;gBAAnB,IAAI,EAAE,aAAa,EAAE,KAAK,SAAoB;CASlE;AAED;;;;;;;;GAQG;AACH,qBAAa,cAAc;IAEzB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,mBAAmB,CAUzC;IAEF,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,gBAAgB,CAAqB;IAG7D,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,mBAAmB,CAAsB;IAEjE;;;;;;;OAOG;IACH,MAAM,CAAC,uBAAuB,CAC5B,eAAe,EAAE,MAAM,EACvB,OAAO,CAAC,EAAE,iBAAiB,GAC1B,MAAM;IA6ET;;;;;;OAMG;IACH,MAAM,CAAC,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM;IAuBnD;;;;;;OAMG;IACH,MAAM,CAAC,kBAAkB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM;IAmBrD;;;;;;;;OAQG;IACH,MAAM,CAAC,eAAe,CACpB,OAAO,EAAE,MAAM,EACf,GAAG,GAAE,MAAY,EACjB,GAAG,GAAE,MAAe,GACnB,MAAM;IAuBT;;;;;;;;;OASG;IACH,MAAM,CAAC,mBAAmB,CACxB,KAAK,EAAE,OAAO,EACd,SAAS,EAAE,MAAM,EACjB,QAAQ,GAAE,MAAY,EACtB,SAAS,GAAE,MAAa,GACvB,MAAM,EAAE;IAoCX;;;;;;;OAOG;IACH,MAAM,CAAC,cAAc,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EACjD,MAAM,EAAE,OAAO,EACf,MAAM,EAAE;SACL,CAAC,IAAI,MAAM,CAAC,GAAG;YACd,IAAI,EAAE,QAAQ,GAAG,QAAQ,GAAG,SAAS,GAAG,QAAQ,CAAC;YACjD,QAAQ,CAAC,EAAE,OAAO,CAAC;YACnB,GAAG,CAAC,EAAE,MAAM,CAAC;YACb,GAAG,CAAC,EAAE,MAAM,CAAC;YACb,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,KAAK,OAAO,CAAC;SACrC;KACF,GACA,CAAC;IAmEJ;;;;;OAKG;IACH,MAAM,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;IAezC;;;;;;OAMG;IACH,MAAM,CAAC,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM;CAiB5C;AAED;;;;GAIG;AACH,wBAAgB,0BAA0B,CACxC,SAAS,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,IAE/B,KAAK,GAAG,EAAE,KAAK,GAAG,EAAE,MAAM,GAAG,mBAmB5C"}
|
|
@@ -4,9 +4,10 @@
|
|
|
4
4
|
* Provides secure input validation for RuVector integration:
|
|
5
5
|
* - Task description validation
|
|
6
6
|
* - Configuration validation
|
|
7
|
-
* - Injection attack prevention
|
|
7
|
+
* - Injection attack prevention (prompt injection via aidefence when installed)
|
|
8
8
|
* - Resource exhaustion prevention
|
|
9
9
|
*/
|
|
10
|
+
import { scanPromptInjection } from '../integrations/prompt-injection.js';
|
|
10
11
|
export class ValidationError extends Error {
|
|
11
12
|
field;
|
|
12
13
|
constructor(message, field) {
|
|
@@ -15,11 +16,23 @@ export class ValidationError extends Error {
|
|
|
15
16
|
this.name = 'ValidationError';
|
|
16
17
|
}
|
|
17
18
|
}
|
|
19
|
+
/** Thrown when task text is rejected by the prompt-injection policy. */
|
|
20
|
+
export class PromptInjectionError extends ValidationError {
|
|
21
|
+
scan;
|
|
22
|
+
constructor(scan, field = 'taskDescription') {
|
|
23
|
+
const top = scan.threats[0];
|
|
24
|
+
super(`Task description rejected: possible prompt injection (${scan.maxSeverity}` +
|
|
25
|
+
(top ? `, ${top.type}` : '') + `; engine ${scan.engine})`, field);
|
|
26
|
+
this.scan = scan;
|
|
27
|
+
this.name = 'PromptInjectionError';
|
|
28
|
+
}
|
|
29
|
+
}
|
|
18
30
|
/**
|
|
19
31
|
* Input Validator
|
|
20
32
|
*
|
|
21
33
|
* Validates all external inputs to prevent:
|
|
22
|
-
* - Injection attacks (XSS, SQL injection, prompt injection
|
|
34
|
+
* - Injection attacks (XSS, SQL injection, and prompt injection — the latter
|
|
35
|
+
* through `scanPromptInjection`, see integrations/prompt-injection.ts)
|
|
23
36
|
* - Resource exhaustion (excessive length, recursion)
|
|
24
37
|
* - Malicious content (scripts, control characters)
|
|
25
38
|
*/
|
|
@@ -36,6 +49,7 @@ export class InputValidator {
|
|
|
36
49
|
/\.\.\//, // Path traversal
|
|
37
50
|
/[;\x00]/, // SQL injection chars
|
|
38
51
|
];
|
|
52
|
+
static warnedInjections = new Set();
|
|
39
53
|
// Control characters that should be removed
|
|
40
54
|
static CONTROL_CHARS_REGEX = /[\x00-\x1F\x7F]/g;
|
|
41
55
|
/**
|
|
@@ -83,6 +97,20 @@ export class InputValidator {
|
|
|
83
97
|
throw new ValidationError('Task description contains suspicious content', 'taskDescription');
|
|
84
98
|
}
|
|
85
99
|
}
|
|
100
|
+
// Prompt injection (aidefence when installed, built-in patterns otherwise)
|
|
101
|
+
const scan = scanPromptInjection(sanitized);
|
|
102
|
+
if (scan.decision === 'block') {
|
|
103
|
+
throw new PromptInjectionError(scan);
|
|
104
|
+
}
|
|
105
|
+
if (scan.decision === 'warn') {
|
|
106
|
+
const message = `possible prompt injection in task description (${scan.maxSeverity}: ` +
|
|
107
|
+
`${scan.threats.map((t) => t.type).join(', ')}; engine ${scan.engine})`;
|
|
108
|
+
// Once per distinct finding: an orchestrator loop would otherwise repeat it.
|
|
109
|
+
if (!InputValidator.warnedInjections.has(message)) {
|
|
110
|
+
InputValidator.warnedInjections.add(message);
|
|
111
|
+
process.emitWarning(message, { code: 'AGENTIC_FLOW_PROMPT_INJECTION' });
|
|
112
|
+
}
|
|
113
|
+
}
|
|
86
114
|
}
|
|
87
115
|
return sanitized.trim();
|
|
88
116
|
}
|