chat-flow-ardymalihi 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (152) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +266 -0
  3. package/dist/adapters/db/InMemorySessionRepository.js +15 -0
  4. package/dist/adapters/db/RedisSessionRepository.js +41 -0
  5. package/dist/adapters/intent/IntentMatcher.d.ts +25 -0
  6. package/dist/adapters/intent/IntentMatcher.d.ts.map +1 -0
  7. package/dist/adapters/intent/IntentMatcher.js +89 -0
  8. package/dist/adapters/intent/IntentMatcher.js.map +1 -0
  9. package/dist/adapters/intent/IntentService.d.ts +27 -0
  10. package/dist/adapters/intent/IntentService.d.ts.map +1 -0
  11. package/dist/adapters/intent/IntentService.js +59 -0
  12. package/dist/adapters/intent/IntentService.js.map +1 -0
  13. package/dist/adapters/intent/MockIntentAdapter.js +29 -0
  14. package/dist/adapters/llm/GeminiLLMAdapter.d.ts +10 -0
  15. package/dist/adapters/llm/GeminiLLMAdapter.d.ts.map +1 -0
  16. package/dist/adapters/llm/GeminiLLMAdapter.js +102 -0
  17. package/dist/adapters/llm/GeminiLLMAdapter.js.map +1 -0
  18. package/dist/adapters/llm/MockLLMAdapter.d.ts +5 -0
  19. package/dist/adapters/llm/MockLLMAdapter.d.ts.map +1 -0
  20. package/dist/adapters/llm/MockLLMAdapter.js +31 -0
  21. package/dist/adapters/llm/MockLLMAdapter.js.map +1 -0
  22. package/dist/adapters/memory/InMemorySessionRepository.js +15 -0
  23. package/dist/adapters/redis/RedisSessionRepository.js +41 -0
  24. package/dist/adapters/repository/InMemoryRepository.d.ts +15 -0
  25. package/dist/adapters/repository/InMemoryRepository.d.ts.map +1 -0
  26. package/dist/adapters/repository/InMemoryRepository.js +41 -0
  27. package/dist/adapters/repository/InMemoryRepository.js.map +1 -0
  28. package/dist/adapters/repository/IntentRepository.d.ts +15 -0
  29. package/dist/adapters/repository/IntentRepository.d.ts.map +1 -0
  30. package/dist/adapters/repository/IntentRepository.js +28 -0
  31. package/dist/adapters/repository/IntentRepository.js.map +1 -0
  32. package/dist/adapters/repository/RedisRepository.d.ts +16 -0
  33. package/dist/adapters/repository/RedisRepository.d.ts.map +1 -0
  34. package/dist/adapters/repository/RedisRepository.js +87 -0
  35. package/dist/adapters/repository/RedisRepository.js.map +1 -0
  36. package/dist/adapters/workflow/MockWorkflowAdapter.d.ts +5 -0
  37. package/dist/adapters/workflow/MockWorkflowAdapter.d.ts.map +1 -0
  38. package/dist/adapters/workflow/MockWorkflowAdapter.js +162 -0
  39. package/dist/adapters/workflow/MockWorkflowAdapter.js.map +1 -0
  40. package/dist/application/ConversationSession.d.ts +23 -0
  41. package/dist/application/ConversationSession.d.ts.map +1 -0
  42. package/dist/application/ConversationSession.js +83 -0
  43. package/dist/application/ConversationSession.js.map +1 -0
  44. package/dist/application/Message.d.ts +11 -0
  45. package/dist/application/Message.d.ts.map +1 -0
  46. package/dist/application/Message.js +30 -0
  47. package/dist/application/Message.js.map +1 -0
  48. package/dist/application/Orchestrator.d.ts +18 -0
  49. package/dist/application/Orchestrator.d.ts.map +1 -0
  50. package/dist/application/Orchestrator.js +80 -0
  51. package/dist/application/Orchestrator.js.map +1 -0
  52. package/dist/application/SessionState.js +2 -0
  53. package/dist/application/usecases/CreateSession.js +20 -0
  54. package/dist/application/usecases/HandleUserMessage.js +69 -0
  55. package/dist/config/ChatFlowConfig.d.ts +59 -0
  56. package/dist/config/ChatFlowConfig.d.ts.map +1 -0
  57. package/dist/config/ChatFlowConfig.js +49 -0
  58. package/dist/config/ChatFlowConfig.js.map +1 -0
  59. package/dist/config/index.d.ts +2 -0
  60. package/dist/config/index.d.ts.map +1 -0
  61. package/dist/config/index.js +7 -0
  62. package/dist/config/index.js.map +1 -0
  63. package/dist/core/entities/ConversationSession.d.ts +23 -0
  64. package/dist/core/entities/ConversationSession.d.ts.map +1 -0
  65. package/dist/core/entities/ConversationSession.js +83 -0
  66. package/dist/core/entities/ConversationSession.js.map +1 -0
  67. package/dist/core/entities/Message.d.ts +11 -0
  68. package/dist/core/entities/Message.d.ts.map +1 -0
  69. package/dist/core/entities/Message.js +30 -0
  70. package/dist/core/entities/Message.js.map +1 -0
  71. package/dist/core/errors/ChatFlowError.d.ts +71 -0
  72. package/dist/core/errors/ChatFlowError.d.ts.map +1 -0
  73. package/dist/core/errors/ChatFlowError.js +108 -0
  74. package/dist/core/errors/ChatFlowError.js.map +1 -0
  75. package/dist/core/errors/index.d.ts +2 -0
  76. package/dist/core/errors/index.d.ts.map +1 -0
  77. package/dist/core/errors/index.js +15 -0
  78. package/dist/core/errors/index.js.map +1 -0
  79. package/dist/db/InMemoryRepository.d.ts +15 -0
  80. package/dist/db/InMemoryRepository.d.ts.map +1 -0
  81. package/dist/db/InMemoryRepository.js +41 -0
  82. package/dist/db/InMemoryRepository.js.map +1 -0
  83. package/dist/db/RedisRepository.d.ts +16 -0
  84. package/dist/db/RedisRepository.d.ts.map +1 -0
  85. package/dist/db/RedisRepository.js +87 -0
  86. package/dist/db/RedisRepository.js.map +1 -0
  87. package/dist/demo/cli-demo.d.ts +2 -0
  88. package/dist/demo/cli-demo.d.ts.map +1 -0
  89. package/dist/demo/cli-demo.js +142 -0
  90. package/dist/demo/cli-demo.js.map +1 -0
  91. package/dist/demo/console-chat.d.ts +2 -0
  92. package/dist/demo/console-chat.d.ts.map +1 -0
  93. package/dist/demo/console-chat.js +144 -0
  94. package/dist/demo/console-chat.js.map +1 -0
  95. package/dist/domain/conversation/ConversationSession.js +82 -0
  96. package/dist/domain/conversation/Message.js +33 -0
  97. package/dist/domain/conversation/SessionState.js +10 -0
  98. package/dist/index.d.ts +22 -0
  99. package/dist/index.d.ts.map +1 -0
  100. package/dist/index.js +61 -0
  101. package/dist/index.js.map +1 -0
  102. package/dist/intent/IntentService.d.ts +17 -0
  103. package/dist/intent/IntentService.d.ts.map +1 -0
  104. package/dist/intent/IntentService.js +51 -0
  105. package/dist/intent/IntentService.js.map +1 -0
  106. package/dist/intent/MockIntentService.d.ts +6 -0
  107. package/dist/intent/MockIntentService.d.ts.map +1 -0
  108. package/dist/intent/MockIntentService.js +30 -0
  109. package/dist/intent/MockIntentService.js.map +1 -0
  110. package/dist/interfaces.d.ts +108 -0
  111. package/dist/interfaces.d.ts.map +1 -0
  112. package/dist/interfaces.js +18 -0
  113. package/dist/interfaces.js.map +1 -0
  114. package/dist/llm/GeminiLLMAdapter.d.ts +10 -0
  115. package/dist/llm/GeminiLLMAdapter.d.ts.map +1 -0
  116. package/dist/llm/GeminiLLMAdapter.js +102 -0
  117. package/dist/llm/GeminiLLMAdapter.js.map +1 -0
  118. package/dist/llm/MockLLMAdapter.d.ts +5 -0
  119. package/dist/llm/MockLLMAdapter.d.ts.map +1 -0
  120. package/dist/llm/MockLLMAdapter.js +31 -0
  121. package/dist/llm/MockLLMAdapter.js.map +1 -0
  122. package/dist/orchestrator/Orchestrator.d.ts +18 -0
  123. package/dist/orchestrator/Orchestrator.d.ts.map +1 -0
  124. package/dist/orchestrator/Orchestrator.js +80 -0
  125. package/dist/orchestrator/Orchestrator.js.map +1 -0
  126. package/dist/ports/IIntentRepository.d.ts +27 -0
  127. package/dist/ports/IIntentRepository.d.ts.map +1 -0
  128. package/dist/ports/IIntentRepository.js +3 -0
  129. package/dist/ports/IIntentRepository.js.map +1 -0
  130. package/dist/ports/IntentPort.js +2 -0
  131. package/dist/ports/LLMPort.js +2 -0
  132. package/dist/ports/SessionRepository.js +2 -0
  133. package/dist/ports/WorkflowPort.js +2 -0
  134. package/dist/scripts/debug-redis.d.ts +2 -0
  135. package/dist/scripts/debug-redis.d.ts.map +1 -0
  136. package/dist/scripts/debug-redis.js +55 -0
  137. package/dist/scripts/debug-redis.js.map +1 -0
  138. package/dist/scripts/verify_memory_intents.d.ts +2 -0
  139. package/dist/scripts/verify_memory_intents.d.ts.map +1 -0
  140. package/dist/scripts/verify_memory_intents.js +45 -0
  141. package/dist/scripts/verify_memory_intents.js.map +1 -0
  142. package/dist/scripts/verify_redis_intents.d.ts +2 -0
  143. package/dist/scripts/verify_redis_intents.d.ts.map +1 -0
  144. package/dist/scripts/verify_redis_intents.js +50 -0
  145. package/dist/scripts/verify_redis_intents.js.map +1 -0
  146. package/dist/verify_memory_intents.js +44 -0
  147. package/dist/verify_redis_intents.js +49 -0
  148. package/dist/workflow/MockWorkflowAdapter.d.ts +5 -0
  149. package/dist/workflow/MockWorkflowAdapter.d.ts.map +1 -0
  150. package/dist/workflow/MockWorkflowAdapter.js +162 -0
  151. package/dist/workflow/MockWorkflowAdapter.js.map +1 -0
  152. package/package.json +78 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 [Your Organization]
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,266 @@
1
+ # Chat-Flow
2
+
3
+ A production-ready conversation orchestration library with intent detection and workflow integration.
4
+
5
+ [![npm version](https://img.shields.io/npm/v/@your-org/chat-flow.svg)](https://www.npmjs.com/package/@your-org/chat-flow)
6
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
7
+
8
+ ## Features
9
+
10
+ - 🎯 **Intent Detection** - AI-powered intent classification with confidence scoring
11
+ - 💬 **Session Management** - Persistent conversation sessions with Redis or in-memory storage
12
+ - 🔄 **Workflow Integration** - Seamless integration with workflow engines (Zapier, N8N, etc.)
13
+ - 🤖 **LLM Adapters** - Support for multiple LLM providers (Gemini, OpenAI, etc.)
14
+ - 🏗️ **Clean Architecture** - Ports & Adapters pattern for maximum flexibility
15
+ - 📊 **Type-Safe** - Full TypeScript support with comprehensive type definitions
16
+ - ✅ **Well-Tested** - Comprehensive test coverage
17
+ - 🔧 **Configurable** - Flexible configuration system
18
+
19
+ ## Installation
20
+
21
+ ```bash
22
+ npm install @your-org/chat-flow
23
+ ```
24
+
25
+ ## Quick Start
26
+
27
+ ```typescript
28
+ import {
29
+ Orchestrator,
30
+ GeminiLLMAdapter,
31
+ RedisRepository,
32
+ IntentService,
33
+ IntentRepository,
34
+ IntentMatcher,
35
+ MockWorkflowAdapter
36
+ } from '@your-org/chat-flow';
37
+
38
+ // Initialize adapters
39
+ const llm = new GeminiLLMAdapter(process.env.GOOGLE_AI_API_KEY!);
40
+ const repository = new RedisRepository('redis://localhost:6379');
41
+ const intentRepo = new IntentRepository(repository);
42
+ const intentMatcher = new IntentMatcher(llm);
43
+ const intentService = new IntentService(intentRepo, intentMatcher);
44
+ const workflow = new MockWorkflowAdapter();
45
+
46
+ // Create orchestrator with custom config
47
+ const orchestrator = new Orchestrator(
48
+ repository,
49
+ llm,
50
+ intentService,
51
+ workflow,
52
+ {
53
+ intent: {
54
+ confidenceThreshold: 0.7,
55
+ maxIntents: 5,
56
+ cacheTTL: 300
57
+ }
58
+ }
59
+ );
60
+
61
+ // Create a session
62
+ const session = await orchestrator.createSession(
63
+ 'session-123',
64
+ 'TEXT',
65
+ 'You are a helpful travel assistant'
66
+ );
67
+
68
+ // Handle user messages
69
+ const { messages, metadata } = await orchestrator.handleMessage(
70
+ session.sessionId,
71
+ 'I want to book a flight to Paris'
72
+ );
73
+
74
+ console.log('Assistant:', messages[0].content);
75
+ console.log('Intent detected:', metadata.intent);
76
+ console.log('Confidence:', metadata.confidence);
77
+ ```
78
+
79
+ ## Core Concepts
80
+
81
+ ### Session Management
82
+
83
+ Sessions maintain conversation state and history:
84
+
85
+ ```typescript
86
+ const session = await orchestrator.createSession(
87
+ 'unique-session-id',
88
+ 'TEXT', // or 'VOICE'
89
+ 'Your agent prompt here'
90
+ );
91
+ ```
92
+
93
+ ### Intent Detection
94
+
95
+ Automatically detect user intents with confidence scoring:
96
+
97
+ ```typescript
98
+ // Define intents
99
+ const intents = [
100
+ {
101
+ name: 'BOOK_FLIGHT',
102
+ description: 'User wants to book a flight',
103
+ required_fields: [
104
+ { name: 'destination', type: 'string' },
105
+ { name: 'date', type: 'string' }
106
+ ]
107
+ }
108
+ ];
109
+
110
+ await intentRepo.upsertIntents(intents);
111
+ ```
112
+
113
+ ### Workflow Integration
114
+
115
+ Execute workflows when intents are detected:
116
+
117
+ ```typescript
118
+ class CustomWorkflowAdapter implements IWorkflowAdapter {
119
+ async executeWorkflow(workflowId: string, context: any): Promise<WorkflowResult> {
120
+ // Your workflow execution logic
121
+ return {
122
+ success: true,
123
+ data: { /* workflow results */ }
124
+ };
125
+ }
126
+ }
127
+ ```
128
+
129
+ ## Configuration
130
+
131
+ Customize behavior with configuration options:
132
+
133
+ ```typescript
134
+ const config = {
135
+ session: {
136
+ ttl: 3600, // Session TTL in seconds
137
+ maxHistoryLength: 100 // Max messages to keep
138
+ },
139
+ intent: {
140
+ confidenceThreshold: 0.6, // Minimum confidence (0-1)
141
+ maxIntents: 5, // Max intents to return
142
+ cacheTTL: 300 // Cache TTL in seconds
143
+ },
144
+ llm: {
145
+ model: 'gemini-2.0-flash-lite',
146
+ temperature: 0.7,
147
+ maxTokens: 1000,
148
+ timeout: 30000
149
+ },
150
+ workflow: {
151
+ timeout: 60000,
152
+ retries: 3,
153
+ retryDelay: 1000
154
+ },
155
+ logging: {
156
+ enabled: true,
157
+ level: 'info',
158
+ timestamps: true
159
+ }
160
+ };
161
+
162
+ const orchestrator = new Orchestrator(repo, llm, intent, workflow, config);
163
+ ```
164
+
165
+ ## Error Handling
166
+
167
+ Chat-Flow provides typed errors for better error handling:
168
+
169
+ ```typescript
170
+ import {
171
+ SessionNotFoundError,
172
+ IntentDetectionError,
173
+ WorkflowExecutionError,
174
+ LLMError
175
+ } from '@your-org/chat-flow';
176
+
177
+ try {
178
+ await orchestrator.handleMessage(sessionId, message);
179
+ } catch (error) {
180
+ if (error instanceof SessionNotFoundError) {
181
+ console.error('Session not found:', error.details.sessionId);
182
+ } else if (error instanceof IntentDetectionError) {
183
+ console.error('Intent detection failed:', error.message);
184
+ }
185
+ }
186
+ ```
187
+
188
+ ## Architecture
189
+
190
+ Chat-Flow follows Clean Architecture principles:
191
+
192
+ ```
193
+ ┌─────────────────────────────────────────┐
194
+ │ Application Layer │
195
+ │ (Orchestrator, ConversationSession) │
196
+ └─────────────────────────────────────────┘
197
+
198
+ ┌─────────────────────────────────────────┐
199
+ │ Ports (Interfaces) │
200
+ │ (IRepository, ILLMAdapter, etc.) │
201
+ └─────────────────────────────────────────┘
202
+
203
+ ┌─────────────────────────────────────────┐
204
+ │ Adapters (Implementations) │
205
+ │ (RedisRepository, GeminiLLMAdapter) │
206
+ └─────────────────────────────────────────┘
207
+ ```
208
+
209
+ ## Testing
210
+
211
+ ```bash
212
+ # Run tests
213
+ npm test
214
+
215
+ # Run tests with coverage
216
+ npm run test:coverage
217
+
218
+ # Run tests in watch mode
219
+ npm run test:watch
220
+ ```
221
+
222
+ ## Development
223
+
224
+ ```bash
225
+ # Install dependencies
226
+ npm install
227
+
228
+ # Build
229
+ npm run build
230
+
231
+ # Run linter
232
+ npm run lint
233
+
234
+ # Format code
235
+ npm run format
236
+
237
+ # Run demo
238
+ npm run demo
239
+ ```
240
+
241
+ ## Examples
242
+
243
+ See the `/examples` directory for more usage examples:
244
+
245
+ - Basic chat implementation
246
+ - Custom intent detection
247
+ - Workflow integration
248
+ - Custom adapters
249
+
250
+ ## API Documentation
251
+
252
+ For detailed API documentation, see [API.md](./docs/API.md).
253
+
254
+ ## Contributing
255
+
256
+ Contributions are welcome! Please read [CONTRIBUTING.md](./CONTRIBUTING.md) for details.
257
+
258
+ ## License
259
+
260
+ MIT © [Your Organization]
261
+
262
+ ## Support
263
+
264
+ - 📧 Email: support@your-org.com
265
+ - 💬 Discord: [Join our community](https://discord.gg/your-server)
266
+ - 🐛 Issues: [GitHub Issues](https://github.com/your-org/chat-flow/issues)
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.InMemorySessionRepository = void 0;
4
+ class InMemorySessionRepository {
5
+ constructor() {
6
+ this.sessions = new Map();
7
+ }
8
+ async save(session) {
9
+ this.sessions.set(session.sessionId, session);
10
+ }
11
+ async findById(sessionId) {
12
+ return this.sessions.get(sessionId) || null;
13
+ }
14
+ }
15
+ exports.InMemorySessionRepository = InMemorySessionRepository;
@@ -0,0 +1,41 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.RedisSessionRepository = void 0;
7
+ const ioredis_1 = __importDefault(require("ioredis"));
8
+ const ConversationSession_1 = require("../../domain/conversation/ConversationSession");
9
+ class RedisSessionRepository {
10
+ constructor(connectionString = 'redis://localhost:6379') {
11
+ this.TTL_SECONDS = 3600; // 1 Hour Expiry
12
+ this.client = new ioredis_1.default(connectionString);
13
+ this.client.on('error', (err) => {
14
+ console.error('[Redis Error]', err);
15
+ });
16
+ }
17
+ async save(session) {
18
+ const key = `session:${session.sessionId}`;
19
+ const data = JSON.stringify(session.toSnapshot());
20
+ await this.client.set(key, data, 'EX', this.TTL_SECONDS);
21
+ }
22
+ async findById(sessionId) {
23
+ const key = `session:${sessionId}`;
24
+ const data = await this.client.get(key);
25
+ if (!data)
26
+ return null;
27
+ try {
28
+ const parsed = JSON.parse(data);
29
+ return ConversationSession_1.ConversationSession.reconstitute(parsed);
30
+ }
31
+ catch (err) {
32
+ console.error(`Failed to reconstitute session ${sessionId}`, err);
33
+ return null;
34
+ }
35
+ }
36
+ // Helper to close connection
37
+ async disconnect() {
38
+ await this.client.quit();
39
+ }
40
+ }
41
+ exports.RedisSessionRepository = RedisSessionRepository;
@@ -0,0 +1,25 @@
1
+ import { ILLMAdapter, Intent, MatchedIntent, Message } from '../../interfaces';
2
+ /**
3
+ * Intent matcher that uses LLM to match user context against known intents
4
+ */
5
+ export declare class IntentMatcher {
6
+ private llm;
7
+ constructor(llm: ILLMAdapter);
8
+ /**
9
+ * Match user context against a list of intents
10
+ * @param context User context (string or object)
11
+ * @param intents Available intents to match against
12
+ * @param confidenceThreshold Minimum confidence threshold (0-100)
13
+ * @returns Array of matched intents above threshold
14
+ */
15
+ matchIntents(context: string | object, intents: Intent[], confidenceThreshold?: number): Promise<MatchedIntent[]>;
16
+ /**
17
+ * Detect intent from conversation history
18
+ * @param history Conversation history
19
+ * @param intents Available intents
20
+ * @param confidenceThreshold Minimum confidence threshold (0-100)
21
+ * @returns Best matched intent or null
22
+ */
23
+ detectFromHistory(history: Message[], intents: Intent[], confidenceThreshold?: number): Promise<MatchedIntent | null>;
24
+ }
25
+ //# sourceMappingURL=IntentMatcher.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"IntentMatcher.d.ts","sourceRoot":"","sources":["../../../src/adapters/intent/IntentMatcher.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAG/E;;GAEG;AACH,qBAAa,aAAa;IACV,OAAO,CAAC,GAAG;gBAAH,GAAG,EAAE,WAAW;IAEpC;;;;;;OAMG;IACG,YAAY,CACd,OAAO,EAAE,MAAM,GAAG,MAAM,EACxB,OAAO,EAAE,MAAM,EAAE,EACjB,mBAAmB,GAAE,MAAW,GACjC,OAAO,CAAC,aAAa,EAAE,CAAC;IA2D3B;;;;;;OAMG;IACG,iBAAiB,CACnB,OAAO,EAAE,OAAO,EAAE,EAClB,OAAO,EAAE,MAAM,EAAE,EACjB,mBAAmB,GAAE,MAAW,GACjC,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC;CASnC"}
@@ -0,0 +1,89 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.IntentMatcher = void 0;
4
+ const errors_1 = require("../../core/errors");
5
+ /**
6
+ * Intent matcher that uses LLM to match user context against known intents
7
+ */
8
+ class IntentMatcher {
9
+ constructor(llm) {
10
+ this.llm = llm;
11
+ }
12
+ /**
13
+ * Match user context against a list of intents
14
+ * @param context User context (string or object)
15
+ * @param intents Available intents to match against
16
+ * @param confidenceThreshold Minimum confidence threshold (0-100)
17
+ * @returns Array of matched intents above threshold
18
+ */
19
+ async matchIntents(context, intents, confidenceThreshold = 70) {
20
+ if (intents.length === 0)
21
+ return [];
22
+ const contextStr = typeof context === "string" ? context : JSON.stringify(context);
23
+ const prompt = `
24
+ You are a strict known intent classifier.
25
+ Analyze the Context and determine if it strictly matches one of the provided Intents.
26
+
27
+ CRITICAL RULES:
28
+ 1. Determine if the user's INTENTION matches one of the provided Intents.
29
+ 2. If the user is strictly greeting, asking about capabilities, or chatting off-topic, return an EMPTY array [].
30
+ 3. For a matched intent, extract EXPECTED values from the context.
31
+ 4. If a required field is missing, you MUST still return the intent if the user's goal is clearly to perform that action (e.g. "Book a flight" -> BOOK_FLIGHT, even if date is missing).
32
+ 5. Do NOT hallucinate values. If a value is not in the text, return null or omit it.
33
+
34
+ Filter conditions:
35
+ - Confidence >= ${confidenceThreshold}
36
+
37
+ Return JSON with the format:
38
+ [
39
+ {
40
+ "intentName": string,
41
+ "confidence": number (0-100),
42
+ "required_values": { ... },
43
+ "optional_values": { ... }
44
+ }
45
+ ]
46
+
47
+ Intents: ${JSON.stringify(intents, null, 2)}
48
+ Context: ${contextStr}
49
+ `;
50
+ try {
51
+ const text = await this.llm.generateContent(prompt);
52
+ const parsed = JSON.parse(text.replace(/^```json\s*/, '').replace(/```$/, '').trim());
53
+ const results = [];
54
+ for (const match of parsed) {
55
+ if (match.confidence < confidenceThreshold)
56
+ continue;
57
+ const intent = intents.find(i => i.name === match.intentName);
58
+ if (!intent)
59
+ continue;
60
+ results.push({
61
+ intent,
62
+ confidence: match.confidence,
63
+ required_values: match.required_values,
64
+ optional_values: match.optional_values,
65
+ });
66
+ }
67
+ return results;
68
+ }
69
+ catch (err) {
70
+ throw new errors_1.IntentDetectionError('Failed to parse LLM output', { error: err instanceof Error ? err.message : String(err), context: contextStr });
71
+ }
72
+ }
73
+ /**
74
+ * Detect intent from conversation history
75
+ * @param history Conversation history
76
+ * @param intents Available intents
77
+ * @param confidenceThreshold Minimum confidence threshold (0-100)
78
+ * @returns Best matched intent or null
79
+ */
80
+ async detectFromHistory(history, intents, confidenceThreshold = 70) {
81
+ // Use last 3 messages to capture context (e.g. slots across turns)
82
+ const recentHistory = history.slice(-3);
83
+ const contextStr = recentHistory.map(m => `${m.role}: ${m.content}`).join('\n');
84
+ const matches = await this.matchIntents(contextStr, intents, confidenceThreshold);
85
+ return matches.length > 0 ? matches[0] : null;
86
+ }
87
+ }
88
+ exports.IntentMatcher = IntentMatcher;
89
+ //# sourceMappingURL=IntentMatcher.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"IntentMatcher.js","sourceRoot":"","sources":["../../../src/adapters/intent/IntentMatcher.ts"],"names":[],"mappings":";;;AACA,8CAAyD;AAEzD;;GAEG;AACH,MAAa,aAAa;IACtB,YAAoB,GAAgB;QAAhB,QAAG,GAAH,GAAG,CAAa;IAAI,CAAC;IAEzC;;;;;;OAMG;IACH,KAAK,CAAC,YAAY,CACd,OAAwB,EACxB,OAAiB,EACjB,sBAA8B,EAAE;QAEhC,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,EAAE,CAAC;QAEpC,MAAM,UAAU,GAAG,OAAO,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;QAEnF,MAAM,MAAM,GAAG;;;;;;;;;;;;oBAYH,mBAAmB;;;;;;;;;;;;WAY5B,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;WAChC,UAAU;CACpB,CAAC;QAEM,IAAI,CAAC;YACD,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,eAAgB,CAAC,MAAM,CAAC,CAAC;YACrD,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,aAAa,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;YACtF,MAAM,OAAO,GAAoB,EAAE,CAAC;YAEpC,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;gBACzB,IAAI,KAAK,CAAC,UAAU,GAAG,mBAAmB;oBAAE,SAAS;gBACrD,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,KAAK,CAAC,UAAU,CAAC,CAAC;gBAC9D,IAAI,CAAC,MAAM;oBAAE,SAAS;gBAEtB,OAAO,CAAC,IAAI,CAAC;oBACT,MAAM;oBACN,UAAU,EAAE,KAAK,CAAC,UAAU;oBAC5B,eAAe,EAAE,KAAK,CAAC,eAAe;oBACtC,eAAe,EAAE,KAAK,CAAC,eAAe;iBACzC,CAAC,CAAC;YACP,CAAC;YACD,OAAO,OAAO,CAAC;QACnB,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACX,MAAM,IAAI,6BAAoB,CAC1B,4BAA4B,EAC5B,EAAE,KAAK,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,OAAO,EAAE,UAAU,EAAE,CACnF,CAAC;QACN,CAAC;IACL,CAAC;IAED;;;;;;OAMG;IACH,KAAK,CAAC,iBAAiB,CACnB,OAAkB,EAClB,OAAiB,EACjB,sBAA8B,EAAE;QAEhC,mEAAmE;QACnE,MAAM,aAAa,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QACxC,MAAM,UAAU,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAEhF,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,UAAU,EAAE,OAAO,EAAE,mBAAmB,CAAC,CAAC;QAElF,OAAO,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAClD,CAAC;CACJ;AA7FD,sCA6FC"}
@@ -0,0 +1,27 @@
1
+ import { IIntentService, IntentResult, Message, Intent, MatchedIntent } from '../../interfaces';
2
+ import { IIntentRepository } from '../../ports/IIntentRepository';
3
+ import { IntentMatcher } from './IntentMatcher';
4
+ /**
5
+ * Refactored Intent Service with proper separation of concerns
6
+ * - Uses IIntentRepository for data access
7
+ * - Uses IntentMatcher for matching logic
8
+ */
9
+ export declare class IntentService implements IIntentService {
10
+ private repository;
11
+ private matcher;
12
+ private confidenceThreshold;
13
+ constructor(repository: IIntentRepository, matcher: IntentMatcher, confidenceThreshold?: number);
14
+ /**
15
+ * Detect intent from conversation history
16
+ */
17
+ detectIntent(history: Message[], systemPrompt: string): Promise<IntentResult>;
18
+ /**
19
+ * Upsert multiple intents
20
+ */
21
+ upsertIntents(intents: Intent[]): Promise<void>;
22
+ /**
23
+ * Match intents against context
24
+ */
25
+ matchIntents(context: string | object, confidenceThreshold?: number): Promise<MatchedIntent[]>;
26
+ }
27
+ //# sourceMappingURL=IntentService.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"IntentService.d.ts","sourceRoot":"","sources":["../../../src/adapters/intent/IntentService.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAChG,OAAO,EAAE,iBAAiB,EAAE,MAAM,+BAA+B,CAAC;AAClE,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAEhD;;;;GAIG;AACH,qBAAa,aAAc,YAAW,cAAc;IAE5C,OAAO,CAAC,UAAU;IAClB,OAAO,CAAC,OAAO;IACf,OAAO,CAAC,mBAAmB;gBAFnB,UAAU,EAAE,iBAAiB,EAC7B,OAAO,EAAE,aAAa,EACtB,mBAAmB,GAAE,MAAW;IAG5C;;OAEG;IACG,YAAY,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;IAmCnF;;OAEG;IACG,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAIrD;;OAEG;IACG,YAAY,CACd,OAAO,EAAE,MAAM,GAAG,MAAM,EACxB,mBAAmB,CAAC,EAAE,MAAM,GAC7B,OAAO,CAAC,aAAa,EAAE,CAAC;CAQ9B"}
@@ -0,0 +1,59 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.IntentService = void 0;
4
+ /**
5
+ * Refactored Intent Service with proper separation of concerns
6
+ * - Uses IIntentRepository for data access
7
+ * - Uses IntentMatcher for matching logic
8
+ */
9
+ class IntentService {
10
+ constructor(repository, matcher, confidenceThreshold = 70) {
11
+ this.repository = repository;
12
+ this.matcher = matcher;
13
+ this.confidenceThreshold = confidenceThreshold;
14
+ }
15
+ /**
16
+ * Detect intent from conversation history
17
+ */
18
+ async detectIntent(history, systemPrompt) {
19
+ const allIntents = await this.repository.getAllIntents();
20
+ if (allIntents.length === 0) {
21
+ return {
22
+ intentName: null,
23
+ confidence: 0,
24
+ payload: {}
25
+ };
26
+ }
27
+ const match = await this.matcher.detectFromHistory(history, allIntents, this.confidenceThreshold);
28
+ if (match) {
29
+ return {
30
+ intentName: match.intent.name,
31
+ confidence: match.confidence / 100, // Convert 0-100 to 0-1
32
+ payload: {
33
+ ...match.required_values,
34
+ ...match.optional_values
35
+ }
36
+ };
37
+ }
38
+ return {
39
+ intentName: null,
40
+ confidence: 0,
41
+ payload: {}
42
+ };
43
+ }
44
+ /**
45
+ * Upsert multiple intents
46
+ */
47
+ async upsertIntents(intents) {
48
+ return this.repository.upsertIntents(intents);
49
+ }
50
+ /**
51
+ * Match intents against context
52
+ */
53
+ async matchIntents(context, confidenceThreshold) {
54
+ const allIntents = await this.repository.getAllIntents();
55
+ return this.matcher.matchIntents(context, allIntents, confidenceThreshold ?? this.confidenceThreshold);
56
+ }
57
+ }
58
+ exports.IntentService = IntentService;
59
+ //# sourceMappingURL=IntentService.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"IntentService.js","sourceRoot":"","sources":["../../../src/adapters/intent/IntentService.ts"],"names":[],"mappings":";;;AAIA;;;;GAIG;AACH,MAAa,aAAa;IACtB,YACY,UAA6B,EAC7B,OAAsB,EACtB,sBAA8B,EAAE;QAFhC,eAAU,GAAV,UAAU,CAAmB;QAC7B,YAAO,GAAP,OAAO,CAAe;QACtB,wBAAmB,GAAnB,mBAAmB,CAAa;IACxC,CAAC;IAEL;;OAEG;IACH,KAAK,CAAC,YAAY,CAAC,OAAkB,EAAE,YAAoB;QACvD,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,aAAa,EAAE,CAAC;QAEzD,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC1B,OAAO;gBACH,UAAU,EAAE,IAAI;gBAChB,UAAU,EAAE,CAAC;gBACb,OAAO,EAAE,EAAE;aACd,CAAC;QACN,CAAC;QAED,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,iBAAiB,CAC9C,OAAO,EACP,UAAU,EACV,IAAI,CAAC,mBAAmB,CAC3B,CAAC;QAEF,IAAI,KAAK,EAAE,CAAC;YACR,OAAO;gBACH,UAAU,EAAE,KAAK,CAAC,MAAM,CAAC,IAAI;gBAC7B,UAAU,EAAE,KAAK,CAAC,UAAU,GAAG,GAAG,EAAE,uBAAuB;gBAC3D,OAAO,EAAE;oBACL,GAAG,KAAK,CAAC,eAAe;oBACxB,GAAG,KAAK,CAAC,eAAe;iBAC3B;aACJ,CAAC;QACN,CAAC;QAED,OAAO;YACH,UAAU,EAAE,IAAI;YAChB,UAAU,EAAE,CAAC;YACb,OAAO,EAAE,EAAE;SACd,CAAC;IACN,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,aAAa,CAAC,OAAiB;QACjC,OAAO,IAAI,CAAC,UAAU,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;IAClD,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,YAAY,CACd,OAAwB,EACxB,mBAA4B;QAE5B,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,aAAa,EAAE,CAAC;QACzD,OAAO,IAAI,CAAC,OAAO,CAAC,YAAY,CAC5B,OAAO,EACP,UAAU,EACV,mBAAmB,IAAI,IAAI,CAAC,mBAAmB,CAClD,CAAC;IACN,CAAC;CACJ;AAlED,sCAkEC"}
@@ -0,0 +1,29 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MockIntentAdapter = void 0;
4
+ class MockIntentAdapter {
5
+ async detectIntent(history, systemPrompt) {
6
+ const lastMsg = history[history.length - 1].content.toLowerCase();
7
+ // Simple keyword detection for demo
8
+ if (lastMsg.includes('book') || lastMsg.includes('flight') || lastMsg.includes('paris')) {
9
+ return {
10
+ intentName: 'USER_WANTS_FLIGHT',
11
+ confidence: 0.95,
12
+ payload: { destination: 'Paris' }
13
+ };
14
+ }
15
+ if (lastMsg.includes('morning') || lastMsg.includes('10 am')) {
16
+ return {
17
+ intentName: 'USER_SELECT_FLIGHT',
18
+ confidence: 0.9,
19
+ payload: { chosen_flight: 'AC123 (10:00 AM)' }
20
+ };
21
+ }
22
+ return {
23
+ intentName: null,
24
+ confidence: 0,
25
+ payload: {}
26
+ };
27
+ }
28
+ }
29
+ exports.MockIntentAdapter = MockIntentAdapter;
@@ -0,0 +1,10 @@
1
+ import { ILLMAdapter, LLMResponse, Message } from '../../interfaces';
2
+ export declare class GeminiLLMAdapter implements ILLMAdapter {
3
+ private genAI;
4
+ private model;
5
+ private embeddingModel;
6
+ constructor(apiKey: string);
7
+ generateResponse(systemPrompt: string, history: Message[]): Promise<LLMResponse>;
8
+ generateContent(prompt: string): Promise<string>;
9
+ }
10
+ //# sourceMappingURL=GeminiLLMAdapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GeminiLLMAdapter.d.ts","sourceRoot":"","sources":["../../../src/adapters/llm/GeminiLLMAdapter.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,OAAO,EAAQ,MAAM,kBAAkB,CAAC;AAE3E,qBAAa,gBAAiB,YAAW,WAAW;IAChD,OAAO,CAAC,KAAK,CAAqB;IAClC,OAAO,CAAC,KAAK,CAAM;IACnB,OAAO,CAAC,cAAc,CAAM;gBAEhB,MAAM,EAAE,MAAM;IAKpB,gBAAgB,CAAC,YAAY,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,WAAW,CAAC;IAqGhF,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;CAIzD"}