waengine 1.7.3 → 1.7.4

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,459 @@
1
+ import { getStorage } from "./storage.js";
2
+
3
+ export class AIFeatures {
4
+ constructor(client) {
5
+ this.client = client;
6
+ this.storage = getStorage();
7
+ this.intentClassifier = new IntentClassifier();
8
+ this.sentimentAnalyzer = new SentimentAnalyzer();
9
+ this.memoryManager = new MemoryManager(this.storage);
10
+ this.conversationContext = new Map();
11
+ }
12
+
13
+ // ===== INTENT RECOGNITION =====
14
+
15
+ /**
16
+ * Analyze user intent from message
17
+ */
18
+ async analyzeIntent(message) {
19
+ const text = message.text || '';
20
+ const intent = await this.intentClassifier.classify(text);
21
+
22
+ // Store intent for analytics
23
+ this.storage.write.in("ai").increment(`intents.${intent.name}`, 1);
24
+ this.storage.write.in("ai").set(`users.${message.from}.lastIntent`, {
25
+ intent: intent.name,
26
+ confidence: intent.confidence,
27
+ timestamp: Date.now()
28
+ });
29
+
30
+ return intent;
31
+ }
32
+
33
+ /**
34
+ * Get user's intent history
35
+ */
36
+ getUserIntentHistory(userId, limit = 10) {
37
+ const history = this.storage.read.from("ai").get(`users.${userId}.intentHistory`) || [];
38
+ return history.slice(-limit);
39
+ }
40
+
41
+ // ===== SENTIMENT ANALYSIS =====
42
+
43
+ /**
44
+ * Analyze message sentiment
45
+ */
46
+ async analyzeSentiment(message) {
47
+ const text = message.text || '';
48
+ const sentiment = await this.sentimentAnalyzer.analyze(text);
49
+
50
+ // Store sentiment for analytics
51
+ this.storage.write.in("ai").increment(`sentiment.${sentiment.label}`, 1);
52
+ this.storage.write.in("ai").set(`users.${message.from}.lastSentiment`, {
53
+ sentiment: sentiment.label,
54
+ score: sentiment.score,
55
+ timestamp: Date.now()
56
+ });
57
+
58
+ return sentiment;
59
+ }
60
+
61
+ /**
62
+ * Get user's sentiment trend
63
+ */
64
+ getUserSentimentTrend(userId, days = 7) {
65
+ const cutoff = Date.now() - (days * 24 * 60 * 60 * 1000);
66
+ const sentiments = this.storage.read.from("ai").get(`users.${userId}.sentimentHistory`) || [];
67
+
68
+ return sentiments
69
+ .filter(s => s.timestamp > cutoff)
70
+ .map(s => ({
71
+ sentiment: s.sentiment,
72
+ score: s.score,
73
+ date: new Date(s.timestamp).toISOString().split('T')[0]
74
+ }));
75
+ }
76
+
77
+ // ===== CONVERSATION MEMORY =====
78
+
79
+ /**
80
+ * Store conversation context
81
+ */
82
+ storeContext(userId, context) {
83
+ const existing = this.conversationContext.get(userId) || [];
84
+ existing.push({
85
+ ...context,
86
+ timestamp: Date.now()
87
+ });
88
+
89
+ // Keep only last 50 context entries
90
+ if (existing.length > 50) {
91
+ existing.shift();
92
+ }
93
+
94
+ this.conversationContext.set(userId, existing);
95
+ this.storage.write.in("ai").set(`context.${userId}`, existing);
96
+
97
+ return context;
98
+ }
99
+
100
+ /**
101
+ * Get conversation context
102
+ */
103
+ getContext(userId, limit = 10) {
104
+ const context = this.conversationContext.get(userId) ||
105
+ this.storage.read.from("ai").get(`context.${userId}`) || [];
106
+
107
+ return context.slice(-limit);
108
+ }
109
+
110
+ /**
111
+ * Clear conversation context
112
+ */
113
+ clearContext(userId) {
114
+ this.conversationContext.delete(userId);
115
+ this.storage.delete.from("ai").key(`context.${userId}`);
116
+ return true;
117
+ }
118
+
119
+ // ===== SMART RESPONSES =====
120
+
121
+ /**
122
+ * Generate contextual response
123
+ */
124
+ async generateResponse(message, options = {}) {
125
+ const intent = await this.analyzeIntent(message);
126
+ const sentiment = await this.analyzeSentiment(message);
127
+ const context = this.getContext(message.from, 5);
128
+
129
+ // Store current message in context
130
+ this.storeContext(message.from, {
131
+ text: message.text,
132
+ intent: intent.name,
133
+ sentiment: sentiment.label,
134
+ type: 'user_message'
135
+ });
136
+
137
+ // Generate response based on intent and sentiment
138
+ let response = await this.generateIntentBasedResponse(intent, sentiment, context, options);
139
+
140
+ // Store bot response in context
141
+ this.storeContext(message.from, {
142
+ text: response,
143
+ type: 'bot_response'
144
+ });
145
+
146
+ return response;
147
+ }
148
+
149
+ /**
150
+ * Generate response based on intent
151
+ */
152
+ async generateIntentBasedResponse(intent, sentiment, context, options) {
153
+ const responses = {
154
+ greeting: this.getGreetingResponse(sentiment),
155
+ question: this.getQuestionResponse(context),
156
+ complaint: this.getComplaintResponse(sentiment),
157
+ compliment: this.getComplimentResponse(),
158
+ goodbye: this.getGoodbyeResponse(),
159
+ help: this.getHelpResponse(),
160
+ unknown: this.getUnknownResponse()
161
+ };
162
+
163
+ return responses[intent.name] || responses.unknown;
164
+ }
165
+
166
+ // ===== RESPONSE GENERATORS =====
167
+
168
+ getGreetingResponse(sentiment) {
169
+ const positive = [
170
+ "Hallo! 😊 Schön dich zu sehen!",
171
+ "Hi! 👋 Wie kann ich dir helfen?",
172
+ "Hey! 🌟 Was kann ich für dich tun?"
173
+ ];
174
+
175
+ const neutral = [
176
+ "Hallo! Wie geht es dir?",
177
+ "Hi! Was gibt's?",
178
+ "Hey! Wie kann ich helfen?"
179
+ ];
180
+
181
+ const responses = sentiment.score > 0.1 ? positive : neutral;
182
+ return responses[Math.floor(Math.random() * responses.length)];
183
+ }
184
+
185
+ getQuestionResponse(context) {
186
+ const hasRecentQuestions = context.some(c => c.intent === 'question');
187
+
188
+ if (hasRecentQuestions) {
189
+ return "Ich sehe, du hast noch mehr Fragen! 🤔 Lass mich dir helfen.";
190
+ }
191
+
192
+ return "Das ist eine interessante Frage! 💭 Lass mich nachdenken...";
193
+ }
194
+
195
+ getComplaintResponse(sentiment) {
196
+ if (sentiment.score < -0.3) {
197
+ return "Es tut mir wirklich leid, dass du unzufrieden bist. 😔 Wie kann ich das Problem lösen?";
198
+ }
199
+
200
+ return "Ich verstehe deine Bedenken. 🤝 Lass uns das gemeinsam klären.";
201
+ }
202
+
203
+ getComplimentResponse() {
204
+ const responses = [
205
+ "Vielen Dank! 😊 Das freut mich sehr!",
206
+ "Das ist sehr nett von dir! 🌟",
207
+ "Danke für die freundlichen Worte! 💖"
208
+ ];
209
+
210
+ return responses[Math.floor(Math.random() * responses.length)];
211
+ }
212
+
213
+ getGoodbyeResponse() {
214
+ const responses = [
215
+ "Tschüss! 👋 Bis bald!",
216
+ "Auf Wiedersehen! 🌟 Hab einen schönen Tag!",
217
+ "Bye! 😊 Melde dich gerne wieder!"
218
+ ];
219
+
220
+ return responses[Math.floor(Math.random() * responses.length)];
221
+ }
222
+
223
+ getHelpResponse() {
224
+ return "Gerne helfe ich dir! 🤖 Was genau brauchst du?";
225
+ }
226
+
227
+ getUnknownResponse() {
228
+ const responses = [
229
+ "Hmm, das verstehe ich nicht ganz. 🤔 Kannst du das anders formulieren?",
230
+ "Entschuldigung, ich bin mir nicht sicher was du meinst. 💭 Kannst du mir mehr Details geben?",
231
+ "Das ist interessant! 🧐 Erzähl mir mehr darüber."
232
+ ];
233
+
234
+ return responses[Math.floor(Math.random() * responses.length)];
235
+ }
236
+
237
+ // ===== AI STATISTICS =====
238
+
239
+ /**
240
+ * Get AI analytics
241
+ */
242
+ getAIStats() {
243
+ const intents = this.storage.read.from("ai").get("intents") || {};
244
+ const sentiments = this.storage.read.from("ai").get("sentiment") || {};
245
+ const users = this.storage.read.from("ai").get("users") || {};
246
+
247
+ return {
248
+ intents: {
249
+ total: Object.values(intents).reduce((sum, count) => sum + count, 0),
250
+ distribution: intents,
251
+ mostCommon: Object.entries(intents).sort(([,a], [,b]) => b - a)[0]?.[0] || 'none'
252
+ },
253
+ sentiment: {
254
+ total: Object.values(sentiments).reduce((sum, count) => sum + count, 0),
255
+ distribution: sentiments,
256
+ positiveRatio: (sentiments.positive || 0) / Object.values(sentiments).reduce((sum, count) => sum + count, 1)
257
+ },
258
+ users: {
259
+ total: Object.keys(users).length,
260
+ activeContexts: this.conversationContext.size
261
+ }
262
+ };
263
+ }
264
+ }
265
+
266
+ // ===== INTENT CLASSIFIER =====
267
+
268
+ class IntentClassifier {
269
+ constructor() {
270
+ this.patterns = {
271
+ greeting: [
272
+ /\b(hallo|hi|hey|guten\s+(tag|morgen|abend)|servus|moin)\b/i,
273
+ /\b(wie\s+geht.s|was\s+machst\s+du)\b/i
274
+ ],
275
+ question: [
276
+ /\b(was|wie|wann|wo|warum|wieso|weshalb|wer)\b/i,
277
+ /\?$/,
278
+ /\b(kannst\s+du|könntest\s+du|hilf\s+mir)\b/i
279
+ ],
280
+ complaint: [
281
+ /\b(problem|fehler|bug|kaputt|funktioniert\s+nicht|geht\s+nicht)\b/i,
282
+ /\b(schlecht|schrecklich|furchtbar|ärgerlich|nervig)\b/i
283
+ ],
284
+ compliment: [
285
+ /\b(toll|super|großartig|fantastisch|perfekt|danke|dankeschön)\b/i,
286
+ /\b(gut\s+gemacht|sehr\s+gut|ausgezeichnet)\b/i
287
+ ],
288
+ goodbye: [
289
+ /\b(tschüss|bye|auf\s+wiedersehen|bis\s+bald|ciao|adieu)\b/i,
290
+ /\b(gute\s+nacht|schlaf\s+gut)\b/i
291
+ ],
292
+ help: [
293
+ /\b(hilfe|help|unterstützung|support)\b/i,
294
+ /\b(was\s+kannst\s+du|befehle|commands)\b/i
295
+ ]
296
+ };
297
+ }
298
+
299
+ async classify(text) {
300
+ const normalizedText = text.toLowerCase();
301
+ let bestMatch = { name: 'unknown', confidence: 0 };
302
+
303
+ for (const [intent, patterns] of Object.entries(this.patterns)) {
304
+ let matches = 0;
305
+
306
+ for (const pattern of patterns) {
307
+ if (pattern.test(normalizedText)) {
308
+ matches++;
309
+ }
310
+ }
311
+
312
+ const confidence = matches / patterns.length;
313
+
314
+ if (confidence > bestMatch.confidence) {
315
+ bestMatch = { name: intent, confidence };
316
+ }
317
+ }
318
+
319
+ return bestMatch;
320
+ }
321
+ }
322
+
323
+ // ===== SENTIMENT ANALYZER =====
324
+
325
+ class SentimentAnalyzer {
326
+ constructor() {
327
+ this.positiveWords = [
328
+ 'gut', 'toll', 'super', 'fantastisch', 'großartig', 'perfekt', 'wunderbar',
329
+ 'ausgezeichnet', 'brilliant', 'amazing', 'love', 'liebe', 'freue', 'glücklich',
330
+ 'zufrieden', 'dankbar', 'begeistert', 'erfreut'
331
+ ];
332
+
333
+ this.negativeWords = [
334
+ 'schlecht', 'schrecklich', 'furchtbar', 'ärgerlich', 'nervig', 'problem',
335
+ 'fehler', 'kaputt', 'hate', 'hasse', 'traurig', 'wütend', 'enttäuscht',
336
+ 'frustriert', 'langweilig', 'dumm'
337
+ ];
338
+
339
+ this.intensifiers = [
340
+ 'sehr', 'extrem', 'total', 'komplett', 'absolut', 'wirklich', 'richtig'
341
+ ];
342
+ }
343
+
344
+ async analyze(text) {
345
+ const words = text.toLowerCase().split(/\s+/);
346
+ let score = 0;
347
+ let positiveCount = 0;
348
+ let negativeCount = 0;
349
+
350
+ for (let i = 0; i < words.length; i++) {
351
+ const word = words[i];
352
+ let multiplier = 1;
353
+
354
+ // Check for intensifiers
355
+ if (i > 0 && this.intensifiers.includes(words[i - 1])) {
356
+ multiplier = 1.5;
357
+ }
358
+
359
+ if (this.positiveWords.includes(word)) {
360
+ score += 1 * multiplier;
361
+ positiveCount++;
362
+ } else if (this.negativeWords.includes(word)) {
363
+ score -= 1 * multiplier;
364
+ negativeCount++;
365
+ }
366
+ }
367
+
368
+ // Normalize score
369
+ const totalWords = positiveCount + negativeCount;
370
+ if (totalWords > 0) {
371
+ score = score / totalWords;
372
+ }
373
+
374
+ // Determine label
375
+ let label = 'neutral';
376
+ if (score > 0.1) label = 'positive';
377
+ else if (score < -0.1) label = 'negative';
378
+
379
+ return {
380
+ score: Math.max(-1, Math.min(1, score)), // Clamp between -1 and 1
381
+ label,
382
+ confidence: Math.abs(score),
383
+ details: {
384
+ positiveWords: positiveCount,
385
+ negativeWords: negativeCount,
386
+ totalWords: words.length
387
+ }
388
+ };
389
+ }
390
+ }
391
+
392
+ // ===== MEMORY MANAGER =====
393
+
394
+ class MemoryManager {
395
+ constructor(storage) {
396
+ this.storage = storage;
397
+ }
398
+
399
+ /**
400
+ * Store user preference
401
+ */
402
+ storePreference(userId, key, value) {
403
+ this.storage.write.in("ai").set(`preferences.${userId}.${key}`, {
404
+ value,
405
+ timestamp: Date.now()
406
+ });
407
+ }
408
+
409
+ /**
410
+ * Get user preference
411
+ */
412
+ getPreference(userId, key) {
413
+ const pref = this.storage.read.from("ai").get(`preferences.${userId}.${key}`);
414
+ return pref ? pref.value : null;
415
+ }
416
+
417
+ /**
418
+ * Store user fact
419
+ */
420
+ storeFact(userId, fact) {
421
+ const facts = this.storage.read.from("ai").get(`facts.${userId}`) || [];
422
+ facts.push({
423
+ fact,
424
+ timestamp: Date.now()
425
+ });
426
+
427
+ // Keep only last 100 facts
428
+ if (facts.length > 100) {
429
+ facts.shift();
430
+ }
431
+
432
+ this.storage.write.in("ai").set(`facts.${userId}`, facts);
433
+ }
434
+
435
+ /**
436
+ * Get user facts
437
+ */
438
+ getFacts(userId) {
439
+ return this.storage.read.from("ai").get(`facts.${userId}`) || [];
440
+ }
441
+
442
+ /**
443
+ * Get user profile
444
+ */
445
+ getUserProfile(userId) {
446
+ const preferences = this.storage.read.from("ai").get(`preferences.${userId}`) || {};
447
+ const facts = this.getFacts(userId);
448
+ const context = this.storage.read.from("ai").get(`context.${userId}`) || [];
449
+
450
+ return {
451
+ preferences: Object.fromEntries(
452
+ Object.entries(preferences).map(([key, data]) => [key, data.value])
453
+ ),
454
+ facts: facts.map(f => f.fact),
455
+ lastInteraction: context.length > 0 ? context[context.length - 1].timestamp : null,
456
+ totalInteractions: context.length
457
+ };
458
+ }
459
+ }
@@ -9,8 +9,9 @@ export class AIIntegration {
9
9
  this.enabled = !!this.apiKey;
10
10
 
11
11
  if (!this.enabled) {
12
- console.log('⚠️ AI Integration deaktiviert - Kein API Key gefunden');
12
+ // Stille Deaktivierung - keine Console-Spam
13
13
  } else {
14
+ // Nur bei Aktivierung loggen
14
15
  console.log('🤖 AI Integration aktiviert');
15
16
  }
16
17
  }