@supernal/interface 1.0.6 → 1.0.7

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.
@@ -0,0 +1,79 @@
1
+ /**
2
+ * Generic AI Interface for Tool Command Processing
3
+ *
4
+ * Uses core abstractions:
5
+ * - ToolMatcher (pluggable matching strategies)
6
+ * - ParameterExtractor (declarative parameter extraction)
7
+ * - ToolExecutor (universal execution engine)
8
+ * - SuggestionEngine ("Did You Mean?" system)
9
+ *
10
+ * NO HARDCODED ROUTES - everything is inferred from NavigationGraph
11
+ */
12
+ import type { ToolMetadata } from "../decorators/Tool";
13
+ import { ToolMatcher } from "./ToolMatcher";
14
+ import { ParameterExtractor } from "./ParameterExtractor";
15
+ import { ToolExecutor } from "./ToolExecutor";
16
+ import { SuggestionEngine } from "./SuggestionEngine";
17
+ export interface AICommand {
18
+ query: string;
19
+ tool?: ToolMetadata;
20
+ confidence: number;
21
+ requiresApproval: boolean;
22
+ parameters?: unknown[];
23
+ parsedIntent?: {
24
+ action: string;
25
+ target?: string;
26
+ value?: string;
27
+ };
28
+ }
29
+ export interface AIResponse {
30
+ success: boolean;
31
+ message: string;
32
+ executedTool?: string;
33
+ timestamp: string;
34
+ }
35
+ /**
36
+ * Generic AI Interface - works for ANY app with ZERO configuration
37
+ * Container detection is INFERRED from NavigationGraph
38
+ *
39
+ * Supports pluggable matching strategies via ToolMatcher.
40
+ * For LLM-based matching, see @supernalintelligence/interface-enterprise
41
+ */
42
+ export declare class AIInterface {
43
+ protected matcher: ToolMatcher;
44
+ protected paramExtractor: ParameterExtractor;
45
+ protected executor: ToolExecutor;
46
+ protected suggestionEngine: SuggestionEngine;
47
+ constructor();
48
+ /**
49
+ * Register a custom matcher strategy (for BYOK LLM integration)
50
+ * @param strategy Custom matching strategy
51
+ */
52
+ registerMatcherStrategy(strategy: any): void;
53
+ /**
54
+ * Get current container - INFERRED from NavigationGraph
55
+ * NO HARDCODED ROUTE MAPPINGS
56
+ */
57
+ private getCurrentContext;
58
+ /**
59
+ * Find matching tools using ToolMatcher
60
+ */
61
+ findToolsForCommand(query: string): Promise<AICommand[]>;
62
+ /**
63
+ * Execute a command using ToolExecutor
64
+ */
65
+ executeCommand(commands: AICommand[], useFirstMatch?: boolean): Promise<AIResponse>;
66
+ /**
67
+ * CONVENIENCE: Process a text query end-to-end
68
+ */
69
+ processQuery(query: string): Promise<AIResponse>;
70
+ /**
71
+ * Get all available commands for help/autocomplete
72
+ */
73
+ getAvailableCommands(): string[];
74
+ /**
75
+ * Get suggestions for incomplete query (autocomplete)
76
+ */
77
+ getSuggestions(partialQuery: string): Promise<string[]>;
78
+ }
79
+ //# sourceMappingURL=AIInterface.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AIInterface.d.ts","sourceRoot":"","sources":["../../../../src/ai/AIInterface.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAGH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAEvD,OAAO,EAAE,WAAW,EAAqB,MAAM,eAAe,CAAC;AAC/D,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAEtD,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,YAAY,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,gBAAgB,EAAE,OAAO,CAAC;IAC1B,UAAU,CAAC,EAAE,OAAO,EAAE,CAAC;IACvB,YAAY,CAAC,EAAE;QACb,MAAM,EAAE,MAAM,CAAC;QACf,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,CAAC;CACH;AAED,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;GAMG;AACH,qBAAa,WAAW;IAEtB,SAAS,CAAC,OAAO,EAAE,WAAW,CAAC;IAC/B,SAAS,CAAC,cAAc,EAAE,kBAAkB,CAAC;IAC7C,SAAS,CAAC,QAAQ,EAAE,YAAY,CAAC;IACjC,SAAS,CAAC,gBAAgB,EAAE,gBAAgB,CAAC;;IAU7C;;;OAGG;IACI,uBAAuB,CAAC,QAAQ,EAAE,GAAG,GAAG,IAAI;IAInD;;;OAGG;IACH,OAAO,CAAC,iBAAiB;IAmBzB;;OAEG;IACG,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC;IAiD9D;;OAEG;IACG,cAAc,CAAC,QAAQ,EAAE,SAAS,EAAE,EAAE,aAAa,GAAE,OAAc,GAAG,OAAO,CAAC,UAAU,CAAC;IA6D/F;;OAEG;IACG,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;IAKtD;;OAEG;IACH,oBAAoB,IAAI,MAAM,EAAE;IAsBhC;;OAEG;IACG,cAAc,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;CAM9D"}
@@ -0,0 +1,179 @@
1
+ /**
2
+ * Generic AI Interface for Tool Command Processing
3
+ *
4
+ * Uses core abstractions:
5
+ * - ToolMatcher (pluggable matching strategies)
6
+ * - ParameterExtractor (declarative parameter extraction)
7
+ * - ToolExecutor (universal execution engine)
8
+ * - SuggestionEngine ("Did You Mean?" system)
9
+ *
10
+ * NO HARDCODED ROUTES - everything is inferred from NavigationGraph
11
+ */
12
+ import { ToolRegistry } from '../background/registry/ToolRegistry.js';
13
+ import { NavigationGraph } from '../background/navigation/NavigationGraph.js';
14
+ import { ToolMatcher } from './ToolMatcher.js';
15
+ import { ParameterExtractor } from './ParameterExtractor.js';
16
+ import { ToolExecutor } from './ToolExecutor.js';
17
+ import { SuggestionEngine } from './SuggestionEngine.js';
18
+ /**
19
+ * Generic AI Interface - works for ANY app with ZERO configuration
20
+ * Container detection is INFERRED from NavigationGraph
21
+ *
22
+ * Supports pluggable matching strategies via ToolMatcher.
23
+ * For LLM-based matching, see @supernalintelligence/interface-enterprise
24
+ */
25
+ export class AIInterface {
26
+ constructor() {
27
+ // Initialize core abstractions
28
+ this.matcher = new ToolMatcher();
29
+ this.paramExtractor = new ParameterExtractor();
30
+ this.executor = new ToolExecutor();
31
+ this.suggestionEngine = new SuggestionEngine();
32
+ }
33
+ /**
34
+ * Register a custom matcher strategy (for BYOK LLM integration)
35
+ * @param strategy Custom matching strategy
36
+ */
37
+ registerMatcherStrategy(strategy) {
38
+ this.matcher.registerStrategy(strategy);
39
+ }
40
+ /**
41
+ * Get current container - INFERRED from NavigationGraph
42
+ * NO HARDCODED ROUTE MAPPINGS
43
+ */
44
+ getCurrentContext() {
45
+ if (typeof window === 'undefined') {
46
+ return {
47
+ currentContainer: 'unknown',
48
+ currentPage: 'unknown'
49
+ };
50
+ }
51
+ // Use the context set by useContainer() hook, NOT route inference
52
+ // This ensures the context matches what the page component registered
53
+ const graph = NavigationGraph.getInstance();
54
+ const currentContainer = graph.getCurrentContext() || 'unknown';
55
+ return {
56
+ currentContainer,
57
+ currentPage: currentContainer
58
+ };
59
+ }
60
+ /**
61
+ * Find matching tools using ToolMatcher
62
+ */
63
+ async findToolsForCommand(query) {
64
+ console.log(`🔍 [AI] Finding tools for: "${query}"`);
65
+ // Get all available tools
66
+ const toolsMap = ToolRegistry.getAllTools();
67
+ const allTools = Array.from(toolsMap.values());
68
+ const context = this.getCurrentContext();
69
+ console.log(`📍 [AI] Current context:`, context);
70
+ // Filter tools by current container
71
+ // Priority: 1) Scoped to current container, 2) Global (no containerId), 3) Global navigation
72
+ const scopedTools = allTools.filter(tool => tool.containerId === context.currentContainer);
73
+ const globalTools = allTools.filter(tool => !tool.containerId);
74
+ const navigationTools = allTools.filter(tool => tool.containerId !== context.currentContainer && tool.category === 'navigation');
75
+ console.log(`📦 [AI] Scoped tools: ${scopedTools.length}, Global tools: ${globalTools.length}, Navigation tools: ${navigationTools.length}`);
76
+ // Combine: scoped first, then global, then navigation
77
+ const contextTools = [...scopedTools, ...globalTools, ...navigationTools];
78
+ console.log(`📦 [AI] Total filtered to ${contextTools.length} tools for context: ${context.currentContainer}`);
79
+ // Use ToolMatcher to find matches
80
+ const matches = await this.matcher.findMatches(query, contextTools, context, 5);
81
+ // Convert to AICommand format
82
+ const commands = matches.map(match => ({
83
+ query,
84
+ tool: match.tool,
85
+ confidence: match.confidence,
86
+ requiresApproval: match.tool.dangerLevel === 'dangerous' || match.tool.dangerLevel === 'destructive',
87
+ parameters: match.parameters || []
88
+ }));
89
+ console.log(`✅ [AI] Found ${commands.length} matching tools:`, commands.map(c => `${c.tool?.name} (${Math.round((c.confidence || 0) * 100)}%)`));
90
+ return commands;
91
+ }
92
+ /**
93
+ * Execute a command using ToolExecutor
94
+ */
95
+ async executeCommand(commands, useFirstMatch = true) {
96
+ if (commands.length === 0) {
97
+ // Use SuggestionEngine for helpful response
98
+ const toolsMap = ToolRegistry.getAllTools();
99
+ const allTools = Array.from(toolsMap.values());
100
+ const context = this.getCurrentContext();
101
+ // Get available commands for current context
102
+ const contextTools = allTools.filter(t => t.aiEnabled &&
103
+ (!t.containerId || t.containerId === context.currentContainer || t.category === 'navigation'));
104
+ const examples = contextTools.flatMap(t => t.examples || []).slice(0, 5);
105
+ return {
106
+ success: false,
107
+ message: `❓ No matching command found.\n\n💡 Try:\n${examples.map(ex => `• "${ex}"`).join('\n')}`,
108
+ timestamp: new Date().toISOString()
109
+ };
110
+ }
111
+ const command = commands[0]; // Use highest confidence match
112
+ if (!command.tool) {
113
+ return {
114
+ success: false,
115
+ message: `❌ No tool found for command`,
116
+ timestamp: new Date().toISOString()
117
+ };
118
+ }
119
+ console.log(`🎯 [AI] Executing: ${command.tool.name}`);
120
+ // Extract parameters using ParameterExtractor
121
+ const extraction = await this.paramExtractor.extract(command.query, command.tool);
122
+ const parameters = extraction.parameters.length > 0 ? extraction.parameters : command.parameters;
123
+ console.log(`📋 [AI] Parameters:`, parameters);
124
+ // Execute using ToolExecutor
125
+ try {
126
+ const result = await this.executor.execute(command.tool, parameters || []);
127
+ return {
128
+ success: result.success,
129
+ message: result.success ? `✅ ${result.message}` : `❌ ${result.message}`,
130
+ executedTool: command.tool.name,
131
+ timestamp: new Date().toISOString()
132
+ };
133
+ }
134
+ catch (error) {
135
+ const errorMsg = error instanceof Error ? error.message : String(error);
136
+ return {
137
+ success: false,
138
+ message: `❌ ${errorMsg}`,
139
+ timestamp: new Date().toISOString()
140
+ };
141
+ }
142
+ }
143
+ /**
144
+ * CONVENIENCE: Process a text query end-to-end
145
+ */
146
+ async processQuery(query) {
147
+ const commands = await this.findToolsForCommand(query);
148
+ return this.executeCommand(commands, true);
149
+ }
150
+ /**
151
+ * Get all available commands for help/autocomplete
152
+ */
153
+ getAvailableCommands() {
154
+ const toolsMap = ToolRegistry.getAllTools();
155
+ const allTools = Array.from(toolsMap.values());
156
+ const context = this.getCurrentContext();
157
+ // Filter by current context
158
+ const contextTools = allTools.filter(tool => !tool.containerId ||
159
+ tool.containerId === context.currentContainer ||
160
+ tool.category === 'navigation');
161
+ // Extract examples
162
+ const commands = [];
163
+ for (const tool of contextTools) {
164
+ const examples = tool.examples || [];
165
+ commands.push(...examples);
166
+ }
167
+ return commands;
168
+ }
169
+ /**
170
+ * Get suggestions for incomplete query (autocomplete)
171
+ */
172
+ async getSuggestions(partialQuery) {
173
+ const toolsMap = ToolRegistry.getAllTools();
174
+ const allTools = Array.from(toolsMap.values());
175
+ const suggestions = this.suggestionEngine.getSuggestions(partialQuery, allTools, 5);
176
+ return suggestions.map(s => s.text);
177
+ }
178
+ }
179
+ //# sourceMappingURL=AIInterface.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AIInterface.js","sourceRoot":"","sources":["../../../../src/ai/AIInterface.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,50 @@
1
+ /**
2
+ * ParameterExtractor - Extract parameters from natural language queries
3
+ *
4
+ * Supports multiple extraction strategies:
5
+ * - Pattern-based (using tool examples)
6
+ * - Entity extraction (dates, numbers, names)
7
+ * - LLM-based extraction (structured JSON)
8
+ */
9
+ import type { ToolMetadata } from '../decorators/Tool';
10
+ /**
11
+ * Extracted parameter with metadata
12
+ */
13
+ export interface ExtractedParameter {
14
+ value: any;
15
+ type: 'string' | 'number' | 'boolean' | 'date' | 'object';
16
+ confidence: number;
17
+ source: 'pattern' | 'entity' | 'llm';
18
+ }
19
+ /**
20
+ * Parameter extraction result
21
+ */
22
+ export interface ExtractionResult {
23
+ parameters: any[];
24
+ confidence: number;
25
+ reasoning?: string;
26
+ }
27
+ /**
28
+ * Base interface for extraction strategies
29
+ */
30
+ export interface ExtractorStrategy {
31
+ name: string;
32
+ priority: number;
33
+ extract(query: string, tool: ToolMetadata): Promise<ExtractionResult | null>;
34
+ }
35
+ /**
36
+ * Main ParameterExtractor orchestrator
37
+ */
38
+ export declare class ParameterExtractor {
39
+ private strategies;
40
+ constructor();
41
+ /**
42
+ * Register a new extraction strategy
43
+ */
44
+ registerStrategy(strategy: ExtractorStrategy): void;
45
+ /**
46
+ * Extract parameters from query for a specific tool
47
+ */
48
+ extract(query: string, tool: ToolMetadata): Promise<ExtractionResult>;
49
+ }
50
+ //# sourceMappingURL=ParameterExtractor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ParameterExtractor.d.ts","sourceRoot":"","sources":["../../../../src/ai/ParameterExtractor.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAEvD;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,GAAG,CAAC;IACX,IAAI,EAAE,QAAQ,GAAG,QAAQ,GAAG,SAAS,GAAG,MAAM,GAAG,QAAQ,CAAC;IAC1D,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,SAAS,GAAG,QAAQ,GAAG,KAAK,CAAC;CACtC;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,UAAU,EAAE,GAAG,EAAE,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IAEjB,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,YAAY,GAAG,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAAC;CAC9E;AAED;;GAEG;AACH,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,UAAU,CAA2B;;IAQ7C;;OAEG;IACH,gBAAgB,CAAC,QAAQ,EAAE,iBAAiB,GAAG,IAAI;IAKnD;;OAEG;IACG,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,YAAY,GAAG,OAAO,CAAC,gBAAgB,CAAC;CAqB5E"}
@@ -0,0 +1,136 @@
1
+ /**
2
+ * ParameterExtractor - Extract parameters from natural language queries
3
+ *
4
+ * Supports multiple extraction strategies:
5
+ * - Pattern-based (using tool examples)
6
+ * - Entity extraction (dates, numbers, names)
7
+ * - LLM-based extraction (structured JSON)
8
+ */
9
+ /**
10
+ * Main ParameterExtractor orchestrator
11
+ */
12
+ export class ParameterExtractor {
13
+ constructor() {
14
+ this.strategies = [];
15
+ // Register default strategies
16
+ this.registerStrategy(new PatternExtractor());
17
+ this.registerStrategy(new EntityExtractor());
18
+ }
19
+ /**
20
+ * Register a new extraction strategy
21
+ */
22
+ registerStrategy(strategy) {
23
+ this.strategies.push(strategy);
24
+ this.strategies.sort((a, b) => b.priority - a.priority);
25
+ }
26
+ /**
27
+ * Extract parameters from query for a specific tool
28
+ */
29
+ async extract(query, tool) {
30
+ // Try each strategy in priority order
31
+ for (const strategy of this.strategies) {
32
+ try {
33
+ const result = await strategy.extract(query, tool);
34
+ if (result && result.confidence >= 60) {
35
+ console.log(`✅ [ParamExtract] Used strategy: ${strategy.name}`, result);
36
+ return result;
37
+ }
38
+ }
39
+ catch (error) {
40
+ console.warn(`[ParamExtract] Strategy ${strategy.name} failed:`, error);
41
+ }
42
+ }
43
+ // No successful extraction
44
+ return {
45
+ parameters: [],
46
+ confidence: 0,
47
+ reasoning: 'No extraction strategy succeeded'
48
+ };
49
+ }
50
+ }
51
+ /**
52
+ * Pattern-based extraction using tool examples
53
+ */
54
+ class PatternExtractor {
55
+ constructor() {
56
+ this.name = 'pattern';
57
+ this.priority = 80;
58
+ }
59
+ async extract(query, tool) {
60
+ const examples = tool.examples || [];
61
+ if (examples.length === 0) {
62
+ return null;
63
+ }
64
+ const lowerQuery = query.toLowerCase().trim();
65
+ // Try to match each example pattern
66
+ for (const example of examples) {
67
+ const pattern = example.toLowerCase();
68
+ // Check if query starts with the pattern
69
+ if (lowerQuery.startsWith(pattern)) {
70
+ // Extract trailing text as parameter
71
+ const trailing = query.substring(example.length).trim();
72
+ if (trailing) {
73
+ console.log(`🔍 [PatternExtract] Matched: "${example}" → param: "${trailing}"`);
74
+ return {
75
+ parameters: [trailing],
76
+ confidence: 90,
77
+ reasoning: `Matched pattern: "${example}"`
78
+ };
79
+ }
80
+ }
81
+ // Check if pattern contains a placeholder (e.g., "open blog {title}")
82
+ const placeholderMatch = pattern.match(/\{(\w+)\}/);
83
+ if (placeholderMatch) {
84
+ // Create a regex from the pattern
85
+ const regexPattern = pattern.replace(/\{(\w+)\}/g, '(.+?)');
86
+ const regex = new RegExp(`^${regexPattern}$`, 'i');
87
+ const match = lowerQuery.match(regex);
88
+ if (match && match[1]) {
89
+ console.log(`🔍 [PatternExtract] Placeholder match: "${example}" → param: "${match[1]}"`);
90
+ return {
91
+ parameters: [match[1].trim()],
92
+ confidence: 95,
93
+ reasoning: `Matched placeholder in: "${example}"`
94
+ };
95
+ }
96
+ }
97
+ }
98
+ return null;
99
+ }
100
+ }
101
+ /**
102
+ * Entity extraction for common types (numbers, dates, etc.)
103
+ */
104
+ class EntityExtractor {
105
+ constructor() {
106
+ this.name = 'entity';
107
+ this.priority = 60;
108
+ }
109
+ async extract(query, tool) {
110
+ const parameters = [];
111
+ // Extract numbers
112
+ const numberMatch = query.match(/\d+/);
113
+ if (numberMatch) {
114
+ parameters.push(parseInt(numberMatch[0], 10));
115
+ }
116
+ // Extract quoted strings
117
+ const quotedMatch = query.match(/"([^"]+)"/);
118
+ if (quotedMatch) {
119
+ parameters.push(quotedMatch[1]);
120
+ }
121
+ // Extract common entities (colors, themes, etc.)
122
+ const colorMatch = query.match(/\b(red|blue|green|dark|light|black|white)\b/i);
123
+ if (colorMatch) {
124
+ parameters.push(colorMatch[1].toLowerCase());
125
+ }
126
+ if (parameters.length > 0) {
127
+ return {
128
+ parameters,
129
+ confidence: 70,
130
+ reasoning: `Extracted ${parameters.length} entities`
131
+ };
132
+ }
133
+ return null;
134
+ }
135
+ }
136
+ //# sourceMappingURL=ParameterExtractor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ParameterExtractor.js","sourceRoot":"","sources":["../../../../src/ai/ParameterExtractor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,43 @@
1
+ /**
2
+ * SuggestionEngine - "Did You Mean?" system for invalid queries
3
+ *
4
+ * Provides helpful suggestions when user queries don't match any tools:
5
+ * - Typo detection (Levenshtein distance)
6
+ * - Similar command suggestions
7
+ * - Available command list
8
+ */
9
+ import type { ToolMetadata } from '../decorators/Tool';
10
+ /**
11
+ * Suggestion with confidence
12
+ */
13
+ export interface Suggestion {
14
+ text: string;
15
+ confidence: number;
16
+ type: 'typo' | 'similar' | 'example' | 'category';
17
+ tool?: ToolMetadata;
18
+ }
19
+ /**
20
+ * SuggestionEngine for generating "Did You Mean?" prompts
21
+ */
22
+ export declare class SuggestionEngine {
23
+ /**
24
+ * Generate suggestions for an invalid/ambiguous query
25
+ * @param query User's query
26
+ * @param tools Available tools
27
+ * @param maxSuggestions Maximum number of suggestions to return
28
+ */
29
+ getSuggestions(query: string, tools: ToolMetadata[], maxSuggestions?: number): Suggestion[];
30
+ /**
31
+ * Format suggestions into a user-friendly message
32
+ */
33
+ formatSuggestions(suggestions: Suggestion[]): string;
34
+ /**
35
+ * Match query to a category
36
+ */
37
+ private matchCategory;
38
+ /**
39
+ * Calculate Levenshtein distance between two strings
40
+ */
41
+ private levenshtein;
42
+ }
43
+ //# sourceMappingURL=SuggestionEngine.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SuggestionEngine.d.ts","sourceRoot":"","sources":["../../../../src/ai/SuggestionEngine.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAEvD;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS,GAAG,UAAU,CAAC;IAClD,IAAI,CAAC,EAAE,YAAY,CAAC;CACrB;AAED;;GAEG;AACH,qBAAa,gBAAgB;IAC3B;;;;;OAKG;IACH,cAAc,CACZ,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,YAAY,EAAE,EACrB,cAAc,GAAE,MAAU,GACzB,UAAU,EAAE;IAgFf;;OAEG;IACH,iBAAiB,CAAC,WAAW,EAAE,UAAU,EAAE,GAAG,MAAM;IA4BpD;;OAEG;IACH,OAAO,CAAC,aAAa;IAkBrB;;OAEG;IACH,OAAO,CAAC,WAAW;CA2BpB"}
@@ -0,0 +1,153 @@
1
+ /**
2
+ * SuggestionEngine - "Did You Mean?" system for invalid queries
3
+ *
4
+ * Provides helpful suggestions when user queries don't match any tools:
5
+ * - Typo detection (Levenshtein distance)
6
+ * - Similar command suggestions
7
+ * - Available command list
8
+ */
9
+ /**
10
+ * SuggestionEngine for generating "Did You Mean?" prompts
11
+ */
12
+ export class SuggestionEngine {
13
+ /**
14
+ * Generate suggestions for an invalid/ambiguous query
15
+ * @param query User's query
16
+ * @param tools Available tools
17
+ * @param maxSuggestions Maximum number of suggestions to return
18
+ */
19
+ getSuggestions(query, tools, maxSuggestions = 5) {
20
+ const suggestions = [];
21
+ const lowerQuery = query.toLowerCase().trim();
22
+ // 1. Check for typos (Levenshtein distance ≤ 3)
23
+ for (const tool of tools) {
24
+ const examples = tool.examples || [];
25
+ const allPhrases = [tool.name, ...examples];
26
+ for (const phrase of allPhrases) {
27
+ const distance = this.levenshtein(lowerQuery, phrase.toLowerCase());
28
+ if (distance <= 3 && distance > 0) {
29
+ const confidence = Math.round((1 - distance / Math.max(lowerQuery.length, phrase.length)) * 100);
30
+ suggestions.push({
31
+ text: phrase,
32
+ confidence,
33
+ type: 'typo',
34
+ tool
35
+ });
36
+ }
37
+ }
38
+ }
39
+ // 2. Find similar commands (keyword overlap)
40
+ const queryWords = lowerQuery.split(/\s+/);
41
+ for (const tool of tools) {
42
+ const examples = tool.examples || [];
43
+ const toolWords = [
44
+ ...tool.name.toLowerCase().split(/\s+/),
45
+ ...(tool.description?.toLowerCase().split(/\s+/) || []),
46
+ ...examples.flatMap((e) => e.toLowerCase().split(/\s+/))
47
+ ];
48
+ const overlap = queryWords.filter(w => toolWords.includes(w)).length;
49
+ if (overlap > 0) {
50
+ const confidence = Math.round((overlap / queryWords.length) * 100);
51
+ // Use first example if available, otherwise tool name
52
+ const text = examples[0] || tool.name;
53
+ suggestions.push({
54
+ text,
55
+ confidence,
56
+ type: 'similar',
57
+ tool
58
+ });
59
+ }
60
+ }
61
+ // 3. Category-based suggestions
62
+ const categoryMatch = this.matchCategory(lowerQuery);
63
+ if (categoryMatch) {
64
+ const categoryTools = tools.filter(t => t.category === categoryMatch);
65
+ for (const tool of categoryTools.slice(0, 3)) {
66
+ const examples = tool.examples || [];
67
+ const text = examples[0] || tool.name;
68
+ suggestions.push({
69
+ text,
70
+ confidence: 60,
71
+ type: 'category',
72
+ tool
73
+ });
74
+ }
75
+ }
76
+ // Sort by confidence and deduplicate
77
+ const sorted = suggestions
78
+ .sort((a, b) => b.confidence - a.confidence)
79
+ .filter((s, i, arr) =>
80
+ // Remove duplicates (same text)
81
+ i === arr.findIndex(other => other.text === s.text))
82
+ .slice(0, maxSuggestions);
83
+ return sorted;
84
+ }
85
+ /**
86
+ * Format suggestions into a user-friendly message
87
+ */
88
+ formatSuggestions(suggestions) {
89
+ if (suggestions.length === 0) {
90
+ return 'No suggestions available. Try typing "help" to see all commands.';
91
+ }
92
+ const typos = suggestions.filter(s => s.type === 'typo');
93
+ const similar = suggestions.filter(s => s.type === 'similar' || s.type === 'category');
94
+ let message = '';
95
+ if (typos.length > 0) {
96
+ message += '❓ Did you mean?\n';
97
+ for (const typo of typos.slice(0, 3)) {
98
+ message += ` • "${typo.text}"\n`;
99
+ }
100
+ }
101
+ if (similar.length > 0) {
102
+ if (message)
103
+ message += '\n';
104
+ message += '💡 Similar commands:\n';
105
+ for (const sim of similar.slice(0, 3)) {
106
+ message += ` • "${sim.text}"\n`;
107
+ }
108
+ }
109
+ return message.trim();
110
+ }
111
+ /**
112
+ * Match query to a category
113
+ */
114
+ matchCategory(query) {
115
+ const categories = {
116
+ 'navigation': ['go', 'open', 'navigate', 'show', 'view', 'page'],
117
+ 'theme': ['theme', 'color', 'dark', 'light', 'appearance'],
118
+ 'data': ['load', 'fetch', 'get', 'data', 'retrieve'],
119
+ 'form': ['submit', 'save', 'form', 'input', 'enter'],
120
+ 'state': ['set', 'change', 'update', 'modify', 'status']
121
+ };
122
+ for (const [category, keywords] of Object.entries(categories)) {
123
+ if (keywords.some(kw => query.includes(kw))) {
124
+ return category;
125
+ }
126
+ }
127
+ return null;
128
+ }
129
+ /**
130
+ * Calculate Levenshtein distance between two strings
131
+ */
132
+ levenshtein(a, b) {
133
+ const matrix = [];
134
+ for (let i = 0; i <= b.length; i++) {
135
+ matrix[i] = [i];
136
+ }
137
+ for (let j = 0; j <= a.length; j++) {
138
+ matrix[0][j] = j;
139
+ }
140
+ for (let i = 1; i <= b.length; i++) {
141
+ for (let j = 1; j <= a.length; j++) {
142
+ if (b.charAt(i - 1) === a.charAt(j - 1)) {
143
+ matrix[i][j] = matrix[i - 1][j - 1];
144
+ }
145
+ else {
146
+ matrix[i][j] = Math.min(matrix[i - 1][j - 1] + 1, matrix[i][j - 1] + 1, matrix[i - 1][j] + 1);
147
+ }
148
+ }
149
+ }
150
+ return matrix[b.length][a.length];
151
+ }
152
+ }
153
+ //# sourceMappingURL=SuggestionEngine.js.map