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.
- package/CHANGELOG.md +29 -0
- package/README.md +34 -3
- package/package.json +3 -2
- package/src/ab-testing.js +698 -0
- package/src/advanced-scheduler.js +577 -0
- package/src/ai-features.js +459 -0
- package/src/ai-integration.js +2 -1
- package/src/analytics-manager.js +458 -0
- package/src/business-manager.js +362 -0
- package/src/client.js +447 -39
- package/src/console-logger.js +256 -0
- package/src/core.js +28 -3
- package/src/cross-platform.js +538 -0
- package/src/database-manager.js +766 -0
- package/src/device-manager.js +1 -1
- package/src/easy-bot-fixed.js +341 -0
- package/src/easy-bot.js +503 -22
- package/src/error-handler.js +230 -0
- package/src/gaming-manager.js +842 -0
- package/src/http-client.js +1 -1
- package/src/index.js +15 -0
- package/src/message.js +197 -94
- package/src/multi-client.js +26 -12
- package/src/plugin-manager.js +59 -10
- package/src/prefix-manager.js +48 -1
- package/src/qr-terminal-fix.js +239 -0
- package/src/qr.js +170 -27
- package/src/quick-bot.js +63 -0
- package/src/reporting-manager.js +867 -0
- package/src/scheduler.js +14 -1
- package/src/security-manager.js +678 -0
- package/src/session-manager-old.js +314 -0
- package/src/session-manager.js +429 -24
- package/src/storage.js +254 -194
- package/src/ui-components.js +560 -0
|
@@ -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
|
+
}
|
package/src/ai-integration.js
CHANGED
|
@@ -9,8 +9,9 @@ export class AIIntegration {
|
|
|
9
9
|
this.enabled = !!this.apiKey;
|
|
10
10
|
|
|
11
11
|
if (!this.enabled) {
|
|
12
|
-
|
|
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
|
}
|