@fidusia/question-engine-dynamic 1.0.4 → 1.0.5
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/dist/engine-types.d.ts +40 -0
- package/dist/engine-types.d.ts.map +1 -0
- package/dist/engine-types.js +25 -0
- package/dist/engine.d.ts +21 -4
- package/dist/engine.d.ts.map +1 -1
- package/dist/engine.js +161 -49
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { ChatbotConfig } from './config-loader';
|
|
2
|
+
/**
|
|
3
|
+
* Types de moteurs disponibles
|
|
4
|
+
*/
|
|
5
|
+
export type EngineType = 'simple' | 'advanced' | 'custom';
|
|
6
|
+
/**
|
|
7
|
+
* Configuration d'un moteur
|
|
8
|
+
*/
|
|
9
|
+
export interface EngineConfig {
|
|
10
|
+
type: EngineType;
|
|
11
|
+
customConfig?: Record<string, any>;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Configuration pour le moteur simple
|
|
15
|
+
* Aucune logique spéciale, juste une suite de questions dans l'ordre
|
|
16
|
+
*/
|
|
17
|
+
export interface SimpleEngineConfig {
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Configuration pour le moteur avancé
|
|
21
|
+
* Utilise toute la logique actuelle (priorités, triggers, etc.)
|
|
22
|
+
*/
|
|
23
|
+
export interface AdvancedEngineConfig extends ChatbotConfig {
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Configuration pour le moteur personnalisé
|
|
27
|
+
* Permet de définir une configuration complètement personnalisée
|
|
28
|
+
*/
|
|
29
|
+
export interface CustomEngineConfig {
|
|
30
|
+
[key: string]: any;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Vérifie si un type de moteur est valide
|
|
34
|
+
*/
|
|
35
|
+
export declare function isValidEngineType(type: string): type is EngineType;
|
|
36
|
+
/**
|
|
37
|
+
* Obtient la configuration par défaut selon le type de moteur
|
|
38
|
+
*/
|
|
39
|
+
export declare function getDefaultEngineConfig(type: EngineType): EngineConfig;
|
|
40
|
+
//# sourceMappingURL=engine-types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"engine-types.d.ts","sourceRoot":"","sources":["../src/engine-types.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAErD;;GAEG;AACH,MAAM,MAAM,UAAU,GAAG,QAAQ,GAAG,UAAU,GAAG,QAAQ,CAAC;AAE1D;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,UAAU,CAAC;IAIjB,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CACpC;AAED;;;GAGG;AACH,MAAM,WAAW,kBAAkB;CAGlC;AAED;;;GAGG;AACH,MAAM,WAAW,oBAAqB,SAAQ,aAAa;CAO1D;AAED;;;GAGG;AACH,MAAM,WAAW,kBAAkB;IAEjC,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;CACpB;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,IAAI,UAAU,CAElE;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,UAAU,GAAG,YAAY,CAWrE"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
// =====================================================
|
|
2
|
+
// TYPES DE MOTEURS DE CHATBOT
|
|
3
|
+
// Définit les différents types de moteurs disponibles
|
|
4
|
+
// =====================================================
|
|
5
|
+
/**
|
|
6
|
+
* Vérifie si un type de moteur est valide
|
|
7
|
+
*/
|
|
8
|
+
export function isValidEngineType(type) {
|
|
9
|
+
return ['simple', 'advanced', 'custom'].includes(type);
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Obtient la configuration par défaut selon le type de moteur
|
|
13
|
+
*/
|
|
14
|
+
export function getDefaultEngineConfig(type) {
|
|
15
|
+
switch (type) {
|
|
16
|
+
case 'simple':
|
|
17
|
+
return { type: 'simple' };
|
|
18
|
+
case 'advanced':
|
|
19
|
+
return { type: 'advanced' };
|
|
20
|
+
case 'custom':
|
|
21
|
+
return { type: 'custom', customConfig: {} };
|
|
22
|
+
default:
|
|
23
|
+
return { type: 'advanced' };
|
|
24
|
+
}
|
|
25
|
+
}
|
package/dist/engine.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { QuestionModule, ModuleQuestion, QueueState, AnsweredQuestion, UserPriority, I18nFunctions } from "./types";
|
|
2
2
|
import type { ChatbotConfig } from './config-loader';
|
|
3
|
+
import type { EngineType, EngineConfig } from './engine-types';
|
|
3
4
|
export declare class QuestionEngine {
|
|
4
5
|
private modules;
|
|
5
6
|
private state;
|
|
@@ -9,11 +10,26 @@ export declare class QuestionEngine {
|
|
|
9
10
|
private config;
|
|
10
11
|
private i18n;
|
|
11
12
|
private chatbotId;
|
|
13
|
+
private engineType;
|
|
12
14
|
constructor(i18n: I18nFunctions);
|
|
13
15
|
/**
|
|
14
16
|
* Définit l'ID du chatbot pour filtrer les questions IA
|
|
15
17
|
*/
|
|
16
18
|
setChatbotId(chatbotId: string | undefined): void;
|
|
19
|
+
/**
|
|
20
|
+
* Définit le type de moteur et sa configuration
|
|
21
|
+
* @param type - Type de moteur ('simple', 'advanced', 'custom')
|
|
22
|
+
* @param config - Configuration optionnelle du moteur
|
|
23
|
+
*/
|
|
24
|
+
setEngineType(type: EngineType, config?: EngineConfig): void;
|
|
25
|
+
/**
|
|
26
|
+
* Retourne le type de moteur actuel
|
|
27
|
+
*/
|
|
28
|
+
getEngineType(): EngineType;
|
|
29
|
+
/**
|
|
30
|
+
* Vérifie si le moteur est de type simple
|
|
31
|
+
*/
|
|
32
|
+
private isSimpleEngine;
|
|
17
33
|
private createInitialState;
|
|
18
34
|
registerModule(module: QuestionModule): void;
|
|
19
35
|
registerModules(modules: QuestionModule[]): void;
|
|
@@ -28,13 +44,14 @@ export declare class QuestionEngine {
|
|
|
28
44
|
private buildQueue;
|
|
29
45
|
private buildModuleQuestions;
|
|
30
46
|
/**
|
|
31
|
-
* Charge toutes les questions
|
|
32
|
-
*
|
|
33
|
-
*
|
|
47
|
+
* Charge toutes les questions avec conditions depuis les modules déjà chargés
|
|
48
|
+
* Les questions sont maintenant dans la table unifiée et chargées par le module-loader
|
|
49
|
+
* Cette fonction extrait simplement les questions avec conditions depuis les modules
|
|
34
50
|
*/
|
|
35
51
|
private loadAllAIQuestions;
|
|
36
52
|
/**
|
|
37
|
-
* Extrait les questions
|
|
53
|
+
* Extrait les questions avec conditions depuis les modules déjà chargés
|
|
54
|
+
* Les questions sont maintenant dans la table unifiée avec des métadonnées
|
|
38
55
|
* Retourne une Map<sectorId, AIQuestion[]>
|
|
39
56
|
*/
|
|
40
57
|
private extractAIQuestionsFromModules;
|
package/dist/engine.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../src/engine.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EACV,cAAc,EACd,cAAc,EACd,UAAU,EAGV,gBAAgB,EAChB,YAAY,EAIZ,aAAa,EACd,MAAM,SAAS,CAAA;AAGhB,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAA;
|
|
1
|
+
{"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../src/engine.ts"],"names":[],"mappings":"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"}
|
package/dist/engine.js
CHANGED
|
@@ -44,6 +44,7 @@ export class QuestionEngine {
|
|
|
44
44
|
this.aiQuestionsCache = new Map(); // Cache de toutes les questions IA chargées
|
|
45
45
|
this.config = {}; // Configuration du chatbot
|
|
46
46
|
this.chatbotId = undefined; // ID du chatbot pour filtrer les questions IA
|
|
47
|
+
this.engineType = 'advanced'; // Type de moteur (simple, advanced, custom)
|
|
47
48
|
this.i18n = i18n;
|
|
48
49
|
this.state = this.createInitialState();
|
|
49
50
|
}
|
|
@@ -53,6 +54,30 @@ export class QuestionEngine {
|
|
|
53
54
|
setChatbotId(chatbotId) {
|
|
54
55
|
this.chatbotId = chatbotId;
|
|
55
56
|
}
|
|
57
|
+
/**
|
|
58
|
+
* Définit le type de moteur et sa configuration
|
|
59
|
+
* @param type - Type de moteur ('simple', 'advanced', 'custom')
|
|
60
|
+
* @param config - Configuration optionnelle du moteur
|
|
61
|
+
*/
|
|
62
|
+
setEngineType(type, config) {
|
|
63
|
+
this.engineType = type;
|
|
64
|
+
// Si une configuration est fournie, l'appliquer
|
|
65
|
+
if (config && config.type === 'advanced') {
|
|
66
|
+
this.setConfig(config);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Retourne le type de moteur actuel
|
|
71
|
+
*/
|
|
72
|
+
getEngineType() {
|
|
73
|
+
return this.engineType;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Vérifie si le moteur est de type simple
|
|
77
|
+
*/
|
|
78
|
+
isSimpleEngine() {
|
|
79
|
+
return this.engineType === 'simple';
|
|
80
|
+
}
|
|
56
81
|
// =====================================================
|
|
57
82
|
// INITIALISATION
|
|
58
83
|
// =====================================================
|
|
@@ -162,10 +187,16 @@ export class QuestionEngine {
|
|
|
162
187
|
this.state.queue = queuedModules;
|
|
163
188
|
}
|
|
164
189
|
buildModuleQuestions(module) {
|
|
165
|
-
//
|
|
166
|
-
//
|
|
190
|
+
// Inclure toutes les questions sans conditions dans la construction initiale
|
|
191
|
+
// Les questions avec conditions seront injectées dynamiquement
|
|
167
192
|
return module.questions
|
|
168
|
-
.filter((q) =>
|
|
193
|
+
.filter((q) => {
|
|
194
|
+
var _a;
|
|
195
|
+
// Exclure les questions avec conditions (elles seront injectées dynamiquement)
|
|
196
|
+
const hasConditions = ((_a = q.aiQuestionMetadata) === null || _a === void 0 ? void 0 : _a.conditions)
|
|
197
|
+
&& Object.keys(q.aiQuestionMetadata.conditions).length > 0;
|
|
198
|
+
return !hasConditions;
|
|
199
|
+
})
|
|
169
200
|
.map((q) => ({
|
|
170
201
|
questionId: q.id,
|
|
171
202
|
moduleId: module.id,
|
|
@@ -175,21 +206,21 @@ export class QuestionEngine {
|
|
|
175
206
|
}));
|
|
176
207
|
}
|
|
177
208
|
/**
|
|
178
|
-
* Charge toutes les questions
|
|
179
|
-
*
|
|
180
|
-
*
|
|
209
|
+
* Charge toutes les questions avec conditions depuis les modules déjà chargés
|
|
210
|
+
* Les questions sont maintenant dans la table unifiée et chargées par le module-loader
|
|
211
|
+
* Cette fonction extrait simplement les questions avec conditions depuis les modules
|
|
181
212
|
*/
|
|
182
213
|
async loadAllAIQuestions() {
|
|
183
|
-
//
|
|
214
|
+
// Extraire les questions avec conditions depuis les modules déjà chargés
|
|
184
215
|
const aiQuestionsFromMetadata = this.extractAIQuestionsFromModules();
|
|
185
216
|
if (aiQuestionsFromMetadata.size > 0) {
|
|
186
|
-
// Utiliser les questions
|
|
217
|
+
// Utiliser les questions extraites depuis les métadonnées
|
|
187
218
|
aiQuestionsFromMetadata.forEach((questions, sectorId) => {
|
|
188
219
|
this.aiQuestionsCache.set(sectorId, questions);
|
|
189
220
|
});
|
|
190
221
|
return;
|
|
191
222
|
}
|
|
192
|
-
//
|
|
223
|
+
// Fallback : Si pas de métadonnées, essayer de charger depuis l'API (pour rétrocompatibilité)
|
|
193
224
|
// Essayer de charger la version serveur (disponible uniquement côté serveur)
|
|
194
225
|
const serverLoader = await getServerLoader();
|
|
195
226
|
// Parcourir tous les modules dans la queue pour charger leurs questions IA
|
|
@@ -203,7 +234,8 @@ export class QuestionEngine {
|
|
|
203
234
|
await Promise.all(loadPromises);
|
|
204
235
|
}
|
|
205
236
|
/**
|
|
206
|
-
* Extrait les questions
|
|
237
|
+
* Extrait les questions avec conditions depuis les modules déjà chargés
|
|
238
|
+
* Les questions sont maintenant dans la table unifiée avec des métadonnées
|
|
207
239
|
* Retourne une Map<sectorId, AIQuestion[]>
|
|
208
240
|
*/
|
|
209
241
|
extractAIQuestionsFromModules() {
|
|
@@ -213,24 +245,29 @@ export class QuestionEngine {
|
|
|
213
245
|
const aiQuestions = [];
|
|
214
246
|
// Parcourir toutes les questions du module
|
|
215
247
|
for (const question of module.questions) {
|
|
216
|
-
// Si la question a des métadonnées
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
248
|
+
// Si la question a des métadonnées (conditions ou parent_question_id), l'extraire
|
|
249
|
+
const metadata = question.aiQuestionMetadata;
|
|
250
|
+
if (metadata) {
|
|
251
|
+
// Vérifier si la question a des conditions ou un parent (nécessite injection dynamique)
|
|
252
|
+
const hasConditions = metadata.conditions && Object.keys(metadata.conditions).length > 0;
|
|
253
|
+
const hasParent = metadata.parentQuestionId;
|
|
254
|
+
if (hasConditions || hasParent) {
|
|
255
|
+
aiQuestions.push({
|
|
256
|
+
id: question.id,
|
|
257
|
+
sectorId: metadata.sectorId || moduleId,
|
|
258
|
+
questionId: question.id,
|
|
259
|
+
questionText: question.text,
|
|
260
|
+
questionType: question.type,
|
|
261
|
+
options: question.options || null,
|
|
262
|
+
placeholder: question.placeholder || null,
|
|
263
|
+
minValue: question.min || null,
|
|
264
|
+
maxValue: question.max || null,
|
|
265
|
+
conditions: metadata.conditions || null,
|
|
266
|
+
isActive: metadata.isActive !== false,
|
|
267
|
+
parentQuestionId: metadata.parentQuestionId || null,
|
|
268
|
+
nextQuestionId: metadata.nextQuestionId || null,
|
|
269
|
+
});
|
|
270
|
+
}
|
|
234
271
|
}
|
|
235
272
|
}
|
|
236
273
|
if (aiQuestions.length > 0) {
|
|
@@ -295,9 +332,10 @@ export class QuestionEngine {
|
|
|
295
332
|
};
|
|
296
333
|
// Si parentQuestionId est défini, injecter après cette question
|
|
297
334
|
if (aiQuestion.parentQuestionId) {
|
|
298
|
-
// Chercher dans la queue ET dans le module (pour les questions statiques)
|
|
335
|
+
// Chercher dans la queue (même si complétée) ET dans le module (pour les questions statiques)
|
|
299
336
|
const queuedParentIndex = queuedModule.questions.findIndex(q => q.questionId === aiQuestion.parentQuestionId);
|
|
300
337
|
// Si pas trouvé dans la queue, chercher dans le module (question statique)
|
|
338
|
+
// IMPORTANT: Chercher le parent même s'il est complété
|
|
301
339
|
if (queuedParentIndex < 0) {
|
|
302
340
|
const parentInModule = module.questions.find(q => q.id === aiQuestion.parentQuestionId);
|
|
303
341
|
if (parentInModule) {
|
|
@@ -382,14 +420,39 @@ export class QuestionEngine {
|
|
|
382
420
|
}
|
|
383
421
|
}
|
|
384
422
|
else {
|
|
385
|
-
// Parent trouvé dans la queue, insérer après
|
|
386
|
-
|
|
387
|
-
|
|
423
|
+
// Parent trouvé dans la queue (même s'il est complété), insérer après
|
|
424
|
+
// Vérifier s'il y a déjà une question IA injectée après le parent
|
|
425
|
+
let insertIndex = queuedParentIndex + 1;
|
|
426
|
+
// Si le parent est complété, chercher la dernière question injectée après lui
|
|
427
|
+
const parentQueuedQuestion = queuedModule.questions[queuedParentIndex];
|
|
428
|
+
if (parentQueuedQuestion && parentQueuedQuestion.status === "completed") {
|
|
429
|
+
// Chercher toutes les questions après le parent jusqu'à la prochaine question standard
|
|
430
|
+
// ou jusqu'à la fin du module
|
|
431
|
+
for (let i = queuedParentIndex + 1; i < queuedModule.questions.length; i++) {
|
|
432
|
+
const q = queuedModule.questions[i];
|
|
433
|
+
const qInModule = module.questions.find(mq => mq.id === q.questionId);
|
|
434
|
+
// Si c'est une question standard (pas IA), arrêter ici
|
|
435
|
+
if (qInModule && !allAIQuestions.find(aq => aq.questionId === q.questionId)) {
|
|
436
|
+
insertIndex = i;
|
|
437
|
+
break;
|
|
438
|
+
}
|
|
439
|
+
// Sinon, continuer jusqu'à la fin
|
|
440
|
+
insertIndex = i + 1;
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
queuedModule.questions.splice(insertIndex, 0, queuedQuestion);
|
|
444
|
+
// Modifier le nextInModule de la question parente seulement si elle n'est pas encore complétée
|
|
445
|
+
// (sinon la modification n'aura pas d'effet car getNextQuestionId a déjà été appelé)
|
|
388
446
|
const parentQuestionInModule = module.questions.find(q => q.id === aiQuestion.parentQuestionId);
|
|
389
447
|
if (parentQuestionInModule && parentQuestionInModule.nextInModule !== aiQuestion.questionId) {
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
448
|
+
// Si le parent est complété, on ne peut plus modifier son nextInModule
|
|
449
|
+
// mais la question IA est déjà injectée dans la queue, donc elle sera proposée
|
|
450
|
+
// via la vérification dans advanceToNextModule ou getNextQuestionId
|
|
451
|
+
if (queuedParentIndex >= 0 && queuedModule.questions[queuedParentIndex].status !== "completed") {
|
|
452
|
+
const originalNextInModule = parentQuestionInModule.nextInModule;
|
|
453
|
+
parentQuestionInModule.nextInModule = aiQuestion.questionId;
|
|
454
|
+
moduleQuestion.nextInModule = originalNextInModule;
|
|
455
|
+
}
|
|
393
456
|
}
|
|
394
457
|
}
|
|
395
458
|
}
|
|
@@ -471,7 +534,8 @@ export class QuestionEngine {
|
|
|
471
534
|
const systemIds = getSystemIds(this.config);
|
|
472
535
|
const behaviors = getSpecialBehaviors(this.config);
|
|
473
536
|
// Pour la question budget_priority, filtrer les options en fonction des prestataires déjà réservés
|
|
474
|
-
|
|
537
|
+
// (Uniquement pour le moteur avancé)
|
|
538
|
+
if (!this.isSimpleEngine() && question.id === systemIds.budgetPriorityQuestionId && behaviors.budgetPriority.enabled) {
|
|
475
539
|
// Les options du module sont maintenant des clés i18n (ex: "intro_options.budget_priority_venue")
|
|
476
540
|
const loadedOptions = question.options && question.options.length > 0
|
|
477
541
|
? question.options
|
|
@@ -515,7 +579,8 @@ export class QuestionEngine {
|
|
|
515
579
|
}
|
|
516
580
|
}
|
|
517
581
|
// Pour la question contact_correction, déterminer dynamiquement le type (email ou phone)
|
|
518
|
-
|
|
582
|
+
// (Uniquement pour le moteur avancé)
|
|
583
|
+
if (!this.isSimpleEngine() && question.id === systemIds.contactCorrectionQuestionId && behaviors.contactCorrection.enabled) {
|
|
519
584
|
const contactIntro = this.state.formData.contact_intro;
|
|
520
585
|
const contactEmail = this.state.formData.contact_email;
|
|
521
586
|
const detectEmailFrom = behaviors.contactCorrection.detectEmailFrom;
|
|
@@ -535,7 +600,12 @@ export class QuestionEngine {
|
|
|
535
600
|
}
|
|
536
601
|
// Vérifie si une question has_* doit être sautée (on a déjà l'info depuis l'intro)
|
|
537
602
|
// Retourne: { shouldSkip: boolean, isBooked: boolean }
|
|
603
|
+
// (Uniquement pour le moteur avancé)
|
|
538
604
|
checkHasQuestionSkip(questionId, moduleId) {
|
|
605
|
+
// Pour le moteur simple, ne jamais sauter de questions
|
|
606
|
+
if (this.isSimpleEngine()) {
|
|
607
|
+
return { shouldSkip: false, isBooked: false };
|
|
608
|
+
}
|
|
539
609
|
// Vérifier si on a posé la question booked_providers
|
|
540
610
|
const bookedProviders = this.state.formData.booked_providers;
|
|
541
611
|
// Si booked_providers n'a pas encore été répondu, ne pas sauter
|
|
@@ -580,7 +650,8 @@ export class QuestionEngine {
|
|
|
580
650
|
const systemIds = getSystemIds(this.config);
|
|
581
651
|
const behaviors = getSpecialBehaviors(this.config);
|
|
582
652
|
// Si c'est la question contact_correction, mettre à jour contact_email ou contact_phone selon le mode
|
|
583
|
-
|
|
653
|
+
// (Uniquement pour le moteur avancé)
|
|
654
|
+
if (!this.isSimpleEngine() && currentQuestion.id === systemIds.contactCorrectionQuestionId && behaviors.contactCorrection.enabled) {
|
|
584
655
|
const contactIntro = this.state.formData.contact_intro;
|
|
585
656
|
const contactEmail = this.state.formData.contact_email;
|
|
586
657
|
const detectEmailFrom = behaviors.contactCorrection.detectEmailFrom;
|
|
@@ -594,10 +665,8 @@ export class QuestionEngine {
|
|
|
594
665
|
this.state.formData.contact_phone = answer;
|
|
595
666
|
}
|
|
596
667
|
}
|
|
597
|
-
//
|
|
598
|
-
//
|
|
599
|
-
this.injectAIQuestionsFromCache();
|
|
600
|
-
// Marquer la question comme complétée dans la queue
|
|
668
|
+
// Marquer la question comme complétée dans la queue AVANT l'injection
|
|
669
|
+
// (pour que l'injection puisse trouver le parent même s'il est complété)
|
|
601
670
|
const queuedModule = this.state.queue.find((m) => m.moduleId === currentModule.id);
|
|
602
671
|
if (queuedModule) {
|
|
603
672
|
const queuedQuestion = queuedModule.questions.find((q) => q.questionId === currentQuestion.id);
|
|
@@ -607,6 +676,10 @@ export class QuestionEngine {
|
|
|
607
676
|
queuedQuestion.answeredAt = new Date();
|
|
608
677
|
}
|
|
609
678
|
}
|
|
679
|
+
// Après avoir enregistré la réponse, injecter les questions IA depuis le cache
|
|
680
|
+
// qui pourraient maintenant correspondre aux nouvelles conditions
|
|
681
|
+
// IMPORTANT: Injection AVANT de déterminer la prochaine question
|
|
682
|
+
this.injectAIQuestionsFromCache();
|
|
610
683
|
// Ajouter aux questions répondues
|
|
611
684
|
this.state.answeredQuestions.push({
|
|
612
685
|
questionId: currentQuestion.id,
|
|
@@ -650,10 +723,26 @@ export class QuestionEngine {
|
|
|
650
723
|
return this.getCurrentQuestion();
|
|
651
724
|
}
|
|
652
725
|
// Sinon, déterminer la prochaine question normalement
|
|
653
|
-
|
|
726
|
+
// Vérifier d'abord s'il y a des questions IA injectées après la question actuelle
|
|
727
|
+
let nextQuestionId = this.getNextQuestionId(currentQuestion, answer);
|
|
728
|
+
// Si pas de nextInModule, vérifier s'il y a des questions IA injectées après cette question
|
|
729
|
+
if (nextQuestionId === null && queuedModule) {
|
|
730
|
+
const currentQuestionIndex = queuedModule.questions.findIndex(q => q.questionId === currentQuestion.id);
|
|
731
|
+
if (currentQuestionIndex >= 0) {
|
|
732
|
+
// Chercher la première question "pending" après la question actuelle
|
|
733
|
+
const nextPendingQuestion = queuedModule.questions
|
|
734
|
+
.slice(currentQuestionIndex + 1)
|
|
735
|
+
.find(q => q.status === "pending");
|
|
736
|
+
if (nextPendingQuestion) {
|
|
737
|
+
nextQuestionId = nextPendingQuestion.questionId;
|
|
738
|
+
}
|
|
739
|
+
}
|
|
740
|
+
}
|
|
654
741
|
if (nextQuestionId === null) {
|
|
655
742
|
// Fin du module - Si c'est la question de priorité, appliquer la réorganisation
|
|
656
|
-
|
|
743
|
+
// (Uniquement pour le moteur avancé)
|
|
744
|
+
if (!this.isSimpleEngine() &&
|
|
745
|
+
currentQuestion.id === systemIds.budgetPriorityQuestionId &&
|
|
657
746
|
Array.isArray(answer) &&
|
|
658
747
|
behaviors.budgetPriority.enabled) {
|
|
659
748
|
this.applyPriorityOrder(answer);
|
|
@@ -665,8 +754,9 @@ export class QuestionEngine {
|
|
|
665
754
|
this.notifyListeners();
|
|
666
755
|
}
|
|
667
756
|
// Si c'est la question continue_other_sectors_question et que la réponse est "non"
|
|
668
|
-
// Sauter directement au module final
|
|
669
|
-
if (
|
|
757
|
+
// Sauter directement au module final (Uniquement pour le moteur avancé)
|
|
758
|
+
if (!this.isSimpleEngine() &&
|
|
759
|
+
currentQuestion.id === systemIds.continueOtherSectorsQuestionId &&
|
|
670
760
|
behaviors.continueOtherSectors.enabled &&
|
|
671
761
|
behaviors.continueOtherSectors.skipToFinalOnNo) {
|
|
672
762
|
// Détecter la réponse "non" : boolean false, string "non" ou "false"
|
|
@@ -934,9 +1024,26 @@ export class QuestionEngine {
|
|
|
934
1024
|
var _a;
|
|
935
1025
|
// Récupérer le module actuel avant de le marquer comme complété
|
|
936
1026
|
const currentQueuedModule = this.state.queue.find((m) => m.moduleId === this.state.currentModuleId);
|
|
1027
|
+
// VÉRIFICATION CRITIQUE : Avant de passer au module suivant,
|
|
1028
|
+
// vérifier s'il y a des questions "pending" dans le module actuel
|
|
1029
|
+
// (y compris les questions IA injectées)
|
|
1030
|
+
if (currentQueuedModule) {
|
|
1031
|
+
const hasPendingQuestions = currentQueuedModule.questions.some(q => q.status === "pending");
|
|
1032
|
+
if (hasPendingQuestions) {
|
|
1033
|
+
// Il y a encore des questions en attente dans ce module
|
|
1034
|
+
// Trouver la première question "pending" et l'activer
|
|
1035
|
+
const nextPendingQuestion = currentQueuedModule.questions.find(q => q.status === "pending");
|
|
1036
|
+
if (nextPendingQuestion) {
|
|
1037
|
+
this.state.currentQuestionId = nextPendingQuestion.questionId;
|
|
1038
|
+
nextPendingQuestion.status = "active";
|
|
1039
|
+
this.notifyListeners();
|
|
1040
|
+
return this.getCurrentQuestion();
|
|
1041
|
+
}
|
|
1042
|
+
}
|
|
1043
|
+
}
|
|
937
1044
|
// Stocker l'ID du module qui se termine pour les messages de transition
|
|
938
1045
|
const completedModuleId = (currentQueuedModule === null || currentQueuedModule === void 0 ? void 0 : currentQueuedModule.moduleId) || null;
|
|
939
|
-
// Marquer le module actuel comme complété
|
|
1046
|
+
// Marquer le module actuel comme complété (seulement s'il n'y a plus de questions pending)
|
|
940
1047
|
if (currentQueuedModule) {
|
|
941
1048
|
currentQueuedModule.status = "completed";
|
|
942
1049
|
this.state.completedModules.push(currentQueuedModule.moduleId);
|
|
@@ -954,8 +1061,9 @@ export class QuestionEngine {
|
|
|
954
1061
|
const nextModule = this.state.queue.find((m) => m.status === "pending" && !this.state.hiddenModules.includes(m.moduleId));
|
|
955
1062
|
// Si on passe d'un module prioritaire (priorité < 0) à un module non prioritaire (priorité >= 0)
|
|
956
1063
|
// ET que le module continue_other_sectors n'a pas encore été complété
|
|
957
|
-
// Alors insérer le module continue_other_sectors
|
|
958
|
-
if (
|
|
1064
|
+
// Alors insérer le module continue_other_sectors (Uniquement pour le moteur avancé)
|
|
1065
|
+
if (!this.isSimpleEngine() &&
|
|
1066
|
+
nextModule &&
|
|
959
1067
|
currentPriority < 0 &&
|
|
960
1068
|
nextModule.effectivePriority >= 0 &&
|
|
961
1069
|
behaviors.continueOtherSectors.enabled &&
|
|
@@ -1119,6 +1227,10 @@ export class QuestionEngine {
|
|
|
1119
1227
|
// PRIORITÉ UTILISATEUR
|
|
1120
1228
|
// =====================================================
|
|
1121
1229
|
applyUserPriority(priority) {
|
|
1230
|
+
// Uniquement pour le moteur avancé
|
|
1231
|
+
if (this.isSimpleEngine()) {
|
|
1232
|
+
return;
|
|
1233
|
+
}
|
|
1122
1234
|
const priorityBoosts = getPriorityBoosts(this.config);
|
|
1123
1235
|
const boosts = priorityBoosts[priority];
|
|
1124
1236
|
if (!boosts)
|
package/dist/index.d.ts
CHANGED
|
@@ -4,6 +4,8 @@ export type { QuestionType, ModuleCategory, ModuleQuestion, SubQuestionTemplate,
|
|
|
4
4
|
export { PRIORITY_TO_MODULES, PRIORITY_BOOSTS, BOOKED_PROVIDER_TO_MODULE, PRIORITY_TO_BOOKED_PROVIDERS, BASE_PRIORITIES, } from './types';
|
|
5
5
|
export type { ChatbotConfig } from './config-loader';
|
|
6
6
|
export { getPriorityMappings, getBookedProviderMappings, getBasePriorities, getPriorityBoosts, getSystemIds, getPriorityToBookedProviders, getPriorityCalculation, getSpecialBehaviors, } from './config-loader';
|
|
7
|
+
export type { EngineType, EngineConfig, SimpleEngineConfig, AdvancedEngineConfig, CustomEngineConfig } from './engine-types';
|
|
8
|
+
export { isValidEngineType, getDefaultEngineConfig } from './engine-types';
|
|
7
9
|
export type { AIQuestion } from './ai-questions-loader';
|
|
8
10
|
export { loadAllAIQuestionsForSector, convertAIQuestionToModuleQuestion, findQuestionIndexInModule, checkConditions, } from './ai-questions-loader';
|
|
9
11
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,cAAc,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAA;AACjF,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAA;AAC5C,YAAY,EACV,YAAY,EACZ,cAAc,EACd,cAAc,EACd,mBAAmB,EACnB,eAAe,EACf,gBAAgB,EAChB,aAAa,EACb,aAAa,EACb,sBAAsB,EACtB,cAAc,EACd,YAAY,EACZ,cAAc,EACd,UAAU,EACV,gBAAgB,EAChB,YAAY,EACZ,aAAa,GACd,MAAM,SAAS,CAAA;AAEhB,OAAO,EACL,mBAAmB,EACnB,eAAe,EACf,yBAAyB,EACzB,4BAA4B,EAC5B,eAAe,GAChB,MAAM,SAAS,CAAA;AAEhB,YAAY,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAA;AACpD,OAAO,EACL,mBAAmB,EACnB,yBAAyB,EACzB,iBAAiB,EACjB,iBAAiB,EACjB,YAAY,EACZ,4BAA4B,EAC5B,sBAAsB,EACtB,mBAAmB,GACpB,MAAM,iBAAiB,CAAA;AAExB,YAAY,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAA;AACvD,OAAO,EACL,2BAA2B,EAC3B,iCAAiC,EACjC,yBAAyB,EACzB,eAAe,GAChB,MAAM,uBAAuB,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,cAAc,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAA;AACjF,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAA;AAC5C,YAAY,EACV,YAAY,EACZ,cAAc,EACd,cAAc,EACd,mBAAmB,EACnB,eAAe,EACf,gBAAgB,EAChB,aAAa,EACb,aAAa,EACb,sBAAsB,EACtB,cAAc,EACd,YAAY,EACZ,cAAc,EACd,UAAU,EACV,gBAAgB,EAChB,YAAY,EACZ,aAAa,GACd,MAAM,SAAS,CAAA;AAEhB,OAAO,EACL,mBAAmB,EACnB,eAAe,EACf,yBAAyB,EACzB,4BAA4B,EAC5B,eAAe,GAChB,MAAM,SAAS,CAAA;AAEhB,YAAY,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAA;AACpD,OAAO,EACL,mBAAmB,EACnB,yBAAyB,EACzB,iBAAiB,EACjB,iBAAiB,EACjB,YAAY,EACZ,4BAA4B,EAC5B,sBAAsB,EACtB,mBAAmB,GACpB,MAAM,iBAAiB,CAAA;AAExB,YAAY,EAAE,UAAU,EAAE,YAAY,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAA;AAC5H,OAAO,EAAE,iBAAiB,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAA;AAE1E,YAAY,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAA;AACvD,OAAO,EACL,2BAA2B,EAC3B,iCAAiC,EACjC,yBAAyB,EACzB,eAAe,GAChB,MAAM,uBAAuB,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -4,4 +4,5 @@
|
|
|
4
4
|
export { QuestionEngine, getQuestionEngine, resetQuestionEngine } from './engine';
|
|
5
5
|
export { PRIORITY_TO_MODULES, PRIORITY_BOOSTS, BOOKED_PROVIDER_TO_MODULE, PRIORITY_TO_BOOKED_PROVIDERS, BASE_PRIORITIES, } from './types';
|
|
6
6
|
export { getPriorityMappings, getBookedProviderMappings, getBasePriorities, getPriorityBoosts, getSystemIds, getPriorityToBookedProviders, getPriorityCalculation, getSpecialBehaviors, } from './config-loader';
|
|
7
|
+
export { isValidEngineType, getDefaultEngineConfig } from './engine-types';
|
|
7
8
|
export { loadAllAIQuestionsForSector, convertAIQuestionToModuleQuestion, findQuestionIndexInModule, checkConditions, } from './ai-questions-loader';
|