@ourlu/assistant-sdk 0.2.3 → 0.2.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.
Files changed (51) hide show
  1. package/dist/iife/audio.v1.028c93fe.js +160 -0
  2. package/dist/iife/audio.v1.051ececf.js +183 -0
  3. package/dist/iife/audio.v1.200db1a6.js +208 -0
  4. package/dist/iife/audio.v1.20858b08.js +191 -0
  5. package/dist/iife/audio.v1.2690e445.js +179 -0
  6. package/dist/iife/audio.v1.2742ff12.js +188 -0
  7. package/dist/iife/audio.v1.70af81b3.js +191 -0
  8. package/dist/iife/audio.v1.95146620.js +1 -1
  9. package/dist/iife/audio.v1.b330baaf.js +166 -0
  10. package/dist/iife/audio.v1.bb9c2d88.js +181 -0
  11. package/dist/iife/audio.v1.ea7571b2.js +182 -0
  12. package/dist/iife/audio.v1.fc0aa8af.js +191 -0
  13. package/dist/iife/audio.v1.js +107 -95
  14. package/dist/iife/engine.v1.2b5bb43b.js +735 -0
  15. package/dist/iife/engine.v1.3b09dc20.js +3 -3
  16. package/dist/iife/engine.v1.56074e5a.js +769 -0
  17. package/dist/iife/engine.v1.61c10e6c.js +770 -0
  18. package/dist/iife/engine.v1.773fc15d.js +2 -2
  19. package/dist/iife/engine.v1.80d2230f.js +770 -0
  20. package/dist/iife/engine.v1.940ba9ea.js +764 -0
  21. package/dist/iife/engine.v1.99a33ee2.js +767 -0
  22. package/dist/iife/engine.v1.9ca6b7ec.js +756 -0
  23. package/dist/iife/engine.v1.a1f7dea2.js +764 -0
  24. package/dist/iife/engine.v1.c0c00bd0.js +721 -0
  25. package/dist/iife/engine.v1.c127656e.js +820 -0
  26. package/dist/iife/engine.v1.c54c9a1a.js +770 -0
  27. package/dist/iife/engine.v1.d1052e81.js +770 -0
  28. package/dist/iife/engine.v1.f6d23a0f.js +770 -0
  29. package/dist/iife/engine.v1.js +135 -36
  30. package/dist/iife/loader.v1.js +5 -1
  31. package/dist/iife/signalement.v1.d321dfde.js +518 -0
  32. package/dist/iife/signalement.v1.js +518 -0
  33. package/dist/iife/ui.v1.00abf020.js +895 -0
  34. package/dist/iife/ui.v1.5d2d4504.js +942 -0
  35. package/dist/iife/ui.v1.6afac75f.js +944 -0
  36. package/dist/iife/ui.v1.6becaa84.js +895 -0
  37. package/dist/iife/ui.v1.6c9e4995.js +895 -0
  38. package/dist/iife/ui.v1.7fb4db0b.js +935 -0
  39. package/dist/iife/ui.v1.88bf5494.js +898 -0
  40. package/dist/iife/ui.v1.923a4e6d.js +937 -0
  41. package/dist/iife/ui.v1.9bfe2815.js +942 -0
  42. package/dist/iife/ui.v1.a8cfe724.js +900 -0
  43. package/dist/iife/ui.v1.c58e1d58.js +959 -0
  44. package/dist/iife/ui.v1.cdfe9a45.js +919 -0
  45. package/dist/iife/ui.v1.e007c7c4.js +926 -0
  46. package/dist/iife/ui.v1.e24ba2bd.js +903 -0
  47. package/dist/iife/ui.v1.f1d8e998.js +903 -0
  48. package/dist/iife/ui.v1.fc52b520.js +895 -0
  49. package/dist/iife/ui.v1.js +154 -147
  50. package/dist/iife/widget-manifest.json +4 -3
  51. package/package.json +2 -1
@@ -9,8 +9,8 @@
9
9
  var trimTrailingSlash = runtime.utils.trimTrailingSlash;
10
10
  var WidgetUIManager = runtime.WidgetUIManager, WidgetAudioManager = runtime.WidgetAudioManager;
11
11
  var EventBus = runtime.EventBus, CONTAINER_ID = runtime.constants.CONTAINER_ID;
12
- var MASCOT_SPECS = JSON.parse('[["mascotSecondaryColor","mascot_secondary_color","data-mascot-secondary-color","#58878d"],["mascotSecondaryDarkColor","mascot_secondary_dark_color","data-mascot-secondary-dark-color","#355c62"],["mascotGoldColor","mascot_gold_color","data-mascot-gold-color","#f4c934"],["mascotEyeColor","mascot_eye_color","data-mascot-eye-color","#040402"],["mascotBeakColor","mascot_beak_color","data-mascot-beak-color","#ab6d46"],["mascotNeutralColor","mascot_neutral_color","data-mascot-neutral-color","#e6e6e6"]]');
13
- var CONFIG_STRING_ATTRS = JSON.parse('[["tenantId","data-tenant-id",""],["widgetKey","data-widget-key",""],["apiBaseUrl","data-api-base-url",""],["widgetOrigin","data-widget-origin",""],["bootstrapEndpoint","data-bootstrap-endpoint",""],["configEndpoint","data-config-endpoint",""],["sessionBootstrapToken","data-session-bootstrap-token",""],["sessionBootstrapTokenExpiresAt","data-session-bootstrap-token-expires-at",""],["chatSessionEndpoint","data-chat-session-endpoint","/v1/occe/chat/sessions"],["chatMessageTemplate","data-chat-message-template","/v1/occe/chat/sessions/{session_id}/messages"],["chatStreamTemplate","data-chat-stream-template","/v1/occe/chat/sessions/{session_id}/stream"],["chatAudioSessionTemplate","data-chat-audio-session-template","/v1/occe/chat/sessions/{session_id}/audio/session"],["chatAudioChunkTemplate","data-chat-audio-chunk-template","/v1/occe/chat/sessions/{session_id}/audio/chunk"],["chatAudioCloseTemplate","data-chat-audio-close-template","/v1/occe/chat/sessions/{session_id}/audio/close"],["chatAudioStreamTemplate","data-chat-audio-stream-template","/v1/occe/chat/sessions/{session_id}/audio/stream"],["panelWidth","data-panel-width","420"],["panelHeight","data-panel-height","640"],["panelMaxHeightVh","data-panel-max-height-vh","85"],["mascotUrl","data-mascot-url",""],["welcomeMessage","data-welcome-message","Bonjour ! Comment puis-je vous aider ?"],["disclaimerText","data-disclaimer-text","Assistant IA - Les reponses ne constituent pas une decision administrative officielle."],["transparencyText","data-transparency-text","Reponses generees par intelligence artificielle."]]');
12
+ var MASCOT_SPECS = JSON.parse('[["mascotSecondaryColor","mascot_secondary_color","data-mascot-secondary-color","#68b1d6"],["mascotSecondaryDarkColor","mascot_secondary_dark_color","data-mascot-secondary-dark-color","#1472a8"],["mascotGoldColor","mascot_gold_color","data-mascot-gold-color","#ffd22e"],["mascotEyeColor","mascot_eye_color","data-mascot-eye-color","#040402"],["mascotBeakColor","mascot_beak_color","data-mascot-beak-color","#ab5f30"],["mascotClawColor","mascot_claw_color","data-mascot-claw-color","#ab5f30"],["mascotNeutralColor","mascot_neutral_color","data-mascot-neutral-color","#e6e6e6"],["mascotBrowColor","mascot_brow_color","data-mascot-brow-color","#3e3e3e"]]');
13
+ var CONFIG_STRING_ATTRS = JSON.parse('[["tenantId","data-tenant-id",""],["widgetKey","data-widget-key",""],["apiBaseUrl","data-api-base-url",""],["widgetOrigin","data-widget-origin",""],["bootstrapEndpoint","data-bootstrap-endpoint",""],["configEndpoint","data-config-endpoint",""],["sessionBootstrapToken","data-session-bootstrap-token",""],["sessionBootstrapTokenExpiresAt","data-session-bootstrap-token-expires-at",""],["chatSessionEndpoint","data-chat-session-endpoint","/v1/occe/chat/sessions"],["chatMessageTemplate","data-chat-message-template","/v1/occe/chat/sessions/{session_id}/messages"],["chatStreamTemplate","data-chat-stream-template","/v1/occe/chat/sessions/{session_id}/stream"],["chatAudioSessionTemplate","data-chat-audio-session-template","/v1/occe/chat/sessions/{session_id}/audio/session"],["chatAudioChunkTemplate","data-chat-audio-chunk-template","/v1/occe/chat/sessions/{session_id}/audio/chunk"],["chatAudioCloseTemplate","data-chat-audio-close-template","/v1/occe/chat/sessions/{session_id}/audio/close"],["chatAudioStreamTemplate","data-chat-audio-stream-template","/v1/occe/chat/sessions/{session_id}/audio/stream"],["panelWidth","data-panel-width","420"],["panelHeight","data-panel-height","640"],["panelMaxHeightVh","data-panel-max-height-vh","85"],["mascotUrl","data-mascot-url",""],["welcomeMessage","data-welcome-message","Bonjour ! Comment puis-je vous aider ?"],["disclaimerText","data-disclaimer-text","Les r\u00e9ponses g\u00e9n\u00e9r\u00e9es par IA ne constituent pas une d\u00e9cision administrative officielle."],["transparencyText","data-transparency-text","Propuls\u00e9 par Ourlu \u00b7 IA locale et transparente."]]');
14
14
  var RUNTIME_ENDPOINT_SPECS = JSON.parse('[["chatSessionEndpoint","chat_session_endpoint","/v1/occe/chat/sessions"],["chatMessageTemplate","chat_message_template","/v1/occe/chat/sessions/{session_id}/messages"],["chatStreamTemplate","chat_stream_template","/v1/occe/chat/sessions/{session_id}/stream"],["chatAudioSessionTemplate","chat_audio_session_template","/v1/occe/chat/sessions/{session_id}/audio/session"],["chatAudioChunkTemplate","chat_audio_chunk_template","/v1/occe/chat/sessions/{session_id}/audio/chunk"],["chatAudioCloseTemplate","chat_audio_close_template","/v1/occe/chat/sessions/{session_id}/audio/close"],["chatAudioStreamTemplate","chat_audio_stream_template","/v1/occe/chat/sessions/{session_id}/audio/stream"]]');
15
15
  function applyMascotLabelColors(config, labels) {
16
16
  MASCOT_SPECS.forEach(function(spec) {
@@ -147,9 +147,9 @@ function applyWidgetTextConfig(config, widgetConfig) {
147
147
  }
148
148
  var TURNSTILE_SCRIPT_URL = "https://challenges.cloudflare.com/turnstile/v0/api.js?render=explicit";
149
149
  var TURNSTILE_CONTAINER_ID = "__ourlu_turnstile_container";
150
- var TURNSTILE_LOAD_TIMEOUT_MS = 10000;
151
- var TURNSTILE_CHALLENGE_TIMEOUT_MS = 30000;
152
- var TURNSTILE_TOKEN_TTL_MS = 240000;
150
+ var TURNSTILE_LOAD_TIMEOUT_MS = 15000;
151
+ var TURNSTILE_CHALLENGE_TIMEOUT_MS = 120000;
152
+ var TURNSTILE_TOKEN_TTL_MS = 280000;
153
153
  function TurnstileChallengeManager(siteKey) {
154
154
  this.siteKey = String(siteKey || "").trim();
155
155
  this.scriptLoaded = false;
@@ -159,7 +159,7 @@ function TurnstileChallengeManager(siteKey) {
159
159
  this.cachedTokenTimestamp = 0;
160
160
  }
161
161
  Object.assign(TurnstileChallengeManager.prototype, {
162
- isEnabled: function() { return Boolean(this.siteKey); },
162
+ isEnabled: function() { return false; /* TURNSTILE_DISABLED_FOR_DEV */ },
163
163
  loadScript: function() {
164
164
  if (this.scriptLoaded) return Promise.resolve();
165
165
  if (this.scriptLoadPromise) return this.scriptLoadPromise;
@@ -170,10 +170,10 @@ Object.assign(TurnstileChallengeManager.prototype, {
170
170
  script.src = TURNSTILE_SCRIPT_URL;
171
171
  script.async = true;
172
172
  var timeoutId = setTimeout(function() {
173
- reject(new Error("Turnstile: délai de chargement dépassé"));
173
+ reject(new Error("Le module de sécurité n'a pas pu se charger. Veuillez réessayer."));
174
174
  }, TURNSTILE_LOAD_TIMEOUT_MS);
175
175
  script.onload = function() { clearTimeout(timeoutId); self.scriptLoaded = true; resolve(); };
176
- script.onerror = function() { clearTimeout(timeoutId); self.scriptLoadPromise = null; reject(new Error("Turnstile: échec du chargement du script")); };
176
+ script.onerror = function() { clearTimeout(timeoutId); self.scriptLoadPromise = null; reject(new Error("Impossible de charger le module de sécurité.")); };
177
177
  document.head.appendChild(script);
178
178
  });
179
179
  return this.scriptLoadPromise;
@@ -183,21 +183,57 @@ Object.assign(TurnstileChallengeManager.prototype, {
183
183
  if (existing) return existing;
184
184
  var container = document.createElement("div");
185
185
  container.id = TURNSTILE_CONTAINER_ID;
186
- container.style.cssText = "display:none;position:fixed;bottom:90px;right:20px;z-index:2147483646;background:#fff;border-radius:12px;padding:16px;box-shadow:0 4px 24px rgba(0,0,0,0.18);";
186
+ container.style.cssText = "display:none;position:fixed;z-index:2147483647;background:transparent;padding:0;";
187
187
  document.body.appendChild(container);
188
188
  return container;
189
189
  },
190
- showContainer: function(container) { container.style.display = "block"; },
190
+ positionInsidePanel: function(container) {
191
+ var widgetHost = document.getElementById("__ourlu_widget_container");
192
+ if (!widgetHost || !widgetHost.shadowRoot) {
193
+ container.style.right = "24px";
194
+ container.style.bottom = "90px";
195
+ container.style.left = "";
196
+ container.style.top = "";
197
+ return;
198
+ }
199
+ var panel = widgetHost.shadowRoot.querySelector("#cm-panel");
200
+ if (!panel) {
201
+ container.style.right = "24px";
202
+ container.style.bottom = "90px";
203
+ container.style.left = "";
204
+ container.style.top = "";
205
+ return;
206
+ }
207
+ var rect = panel.getBoundingClientRect();
208
+ if (rect.width === 0 || rect.height === 0) {
209
+ container.style.right = "24px";
210
+ container.style.bottom = "90px";
211
+ container.style.left = "";
212
+ container.style.top = "";
213
+ return;
214
+ }
215
+ var containerWidth = 300;
216
+ var containerHeight = 65;
217
+ container.style.left = Math.round(rect.left + (rect.width - containerWidth) / 2) + "px";
218
+ container.style.top = Math.round(rect.top + rect.height - containerHeight - 70) + "px";
219
+ container.style.right = "";
220
+ container.style.bottom = "";
221
+ },
222
+ showContainer: function(container) {
223
+ container.style.display = "block";
224
+ this.positionInsidePanel(container);
225
+ },
191
226
  hideContainer: function(container) { container.style.display = "none"; },
192
227
  isCachedTokenValid: function() {
193
228
  return Boolean(this.cachedToken) && (Date.now() - this.cachedTokenTimestamp) < TURNSTILE_TOKEN_TTL_MS;
194
229
  },
195
230
  execute: async function() {
231
+ return ""; /* TURNSTILE_DISABLED_FOR_DEV */
196
232
  if (!this.isEnabled()) return "";
197
233
  if (this.isCachedTokenValid()) return this.cachedToken;
198
234
  await this.loadScript();
199
235
  if (typeof window.turnstile === "undefined") {
200
- throw new Error("Turnstile: API non disponible après chargement");
236
+ throw new Error("Le module de sécurité n'est pas disponible.");
201
237
  }
202
238
  var self = this;
203
239
  var token = await new Promise(function(resolve, reject) {
@@ -205,7 +241,7 @@ Object.assign(TurnstileChallengeManager.prototype, {
205
241
  var timeoutId = setTimeout(function() {
206
242
  self.hideContainer(container);
207
243
  self.cleanup();
208
- reject(new Error("Turnstile: délai de vérification dépassé"));
244
+ reject(new Error("Vérification de sécurité expirée. Veuillez réessayer."));
209
245
  }, TURNSTILE_CHALLENGE_TIMEOUT_MS);
210
246
  if (self.widgetId !== null) { window.turnstile.remove(self.widgetId); self.widgetId = null; }
211
247
  self.widgetId = window.turnstile.render(container, {
@@ -224,13 +260,13 @@ Object.assign(TurnstileChallengeManager.prototype, {
224
260
  clearTimeout(timeoutId);
225
261
  self.hideContainer(container);
226
262
  self.cleanup();
227
- reject(new Error("Turnstile: erreur de vérification (" + errorCode + ")"));
263
+ reject(new Error("Erreur lors de la vérification de sécurité. Veuillez réessayer."));
228
264
  },
229
265
  "timeout-callback": function() {
230
266
  clearTimeout(timeoutId);
231
267
  self.hideContainer(container);
232
268
  self.cleanup();
233
- reject(new Error("Turnstile: expiration du challenge"));
269
+ reject(new Error("La vérification de sécurité a expiré. Veuillez réessayer."));
234
270
  }
235
271
  });
236
272
  });
@@ -279,11 +315,7 @@ Object.assign(WidgetApiManager.prototype, {
279
315
  applyRuntimeConfig: function(payload, sourceLabel) {
280
316
  var runtimeConfig = payload && payload.runtime_config ? payload.runtime_config : {};
281
317
  assignRuntimeEndpoints(this.config, runtimeConfig);
282
- var incomingTurnstileKey = String((payload && payload.turnstile_site_key) || (runtimeConfig && runtimeConfig.turnstile_site_key) || "").trim();
283
- if (incomingTurnstileKey && !this.config.turnstileSiteKey) {
284
- this.config.turnstileSiteKey = incomingTurnstileKey;
285
- if (!this.turnstile) this.turnstile = new TurnstileChallengeManager(incomingTurnstileKey);
286
- }
318
+ /* TURNSTILE_DISABLED_FOR_DEV skip dynamic Turnstile instantiation */
287
319
  var widgetConfig = payload && payload.widget_config ? payload.widget_config : null;
288
320
  if (!widgetConfig) return;
289
321
  var currentThemeVersion = normalizeThemeVersion(this.config.themeVersion);
@@ -428,7 +460,7 @@ Object.assign(WidgetApiManager.prototype, {
428
460
  });
429
461
  var payload = await response.json();
430
462
  var sessionId = payload.session_id || payload.id || "";
431
- if (!sessionId) throw new Error("chat session id absent");
463
+ if (!sessionId) throw new Error("Identifiant de session introuvable.");
432
464
  self.state.sessionId = sessionId;
433
465
  self.state.sessionPromise = null;
434
466
  self.events.emit("ready", payload || {});
@@ -507,6 +539,7 @@ Object.assign(WidgetApiManager.prototype, {
507
539
  if (eventName === "final" && callbacks.onFinal) callbacks.onFinal(payload);
508
540
  if (eventName === "done" && callbacks.onDone) callbacks.onDone(payload);
509
541
  if (eventName === "error" && callbacks.onError) callbacks.onError(payload.message || "Erreur de streaming");
542
+ if (eventName === "module_signalement" && callbacks.onModuleSignalement) callbacks.onModuleSignalement(payload);
510
543
  if (eventName === "transcription_draft_delta" && callbacks.onDelta) callbacks.onDelta(payload);
511
544
  if (eventName === "transcription_draft_complete" && callbacks.onComplete) callbacks.onComplete(payload);
512
545
  if (eventName === "transcription_draft_error" && callbacks.onError) callbacks.onError(payload);
@@ -538,24 +571,22 @@ Object.assign(WidgetApiManager.prototype, {
538
571
  if (requestOptions) Object.assign(options, requestOptions);
539
572
  return options;
540
573
  }, sessionId);
541
- if (!response.body) throw new Error("stream response body is missing");
574
+ if (!response.body) throw new Error("Le flux de réponse est indisponible.");
542
575
  return this.consumeSSE(response.body.getReader(), callbacks, allowedEvents);
543
576
  },
544
577
  streamSession: async function(sessionId, callbacks) {
545
- return this.openEventStream("stream_session", this.config.chatStreamTemplate, sessionId, callbacks, ["token", "final", "error", "done"]);
578
+ return this.openEventStream("stream_session", this.config.chatStreamTemplate, sessionId, callbacks, ["token", "final", "error", "done", "module_signalement"]);
546
579
  },
547
580
  streamAudioDraft: async function(sessionId, callbacks) {
548
581
  var self = this;
549
582
  var controller = new AbortController();
550
- var streamPromise = this.openEventStream(
551
- "audio_stream",
552
- this.config.chatAudioStreamTemplate,
553
- sessionId,
554
- callbacks,
555
- ["transcription_draft_delta", "transcription_draft_complete", "transcription_draft_error"],
556
- { signal: controller.signal }
557
- );
558
- streamPromise.catch(function(error) {
583
+ var response = await this.fetchWithBootstrapRetry("audio_stream", this.config.chatAudioStreamTemplate, function() {
584
+ return { method: "GET", headers: self.buildHeaders(), signal: controller.signal };
585
+ }, sessionId);
586
+ if (!response.body) throw new Error("Le flux de réponse est indisponible.");
587
+ var consumePromise = this.consumeSSE(response.body.getReader(), callbacks,
588
+ ["transcription_draft_delta", "transcription_draft_complete", "transcription_draft_error"]);
589
+ consumePromise.catch(function(error) {
559
590
  if (self.isExpectedStreamAbortError(error)) return;
560
591
  if (callbacks.onTransportError) callbacks.onTransportError(error.message || "Erreur stream audio");
561
592
  });
@@ -633,11 +664,18 @@ function mountFromScript(scriptTag) {
633
664
  var state = { open: false, sessionId: "", token: config.sessionBootstrapToken || "", sending: false, listening: false, bootstrapPromise: null, sessionPromise: null };
634
665
  var ui = new WidgetUIManager(config);
635
666
  if (!ui.mount()) return;
636
- var turnstile = config.turnstileSiteKey ? new TurnstileChallengeManager(config.turnstileSiteKey) : null;
667
+ var turnstile = null; /* TURNSTILE_DISABLED_FOR_DEV */
637
668
  var api = new WidgetApiManager(config, state, events, ui, turnstile);
638
669
  var audio = new WidgetAudioManager(state, api, ui);
639
670
  if (!audio.isSupported()) ui.micButton.style.display = "none";
640
671
  api.hydrateTheme().catch(function() {});
672
+
673
+ var signalementModule = null;
674
+ var SignalementModuleManager = runtime.SignalementModuleManager;
675
+ if (SignalementModuleManager) {
676
+ signalementModule = new SignalementModuleManager(ui.getRoot(), events, api, ui);
677
+ signalementModule.mount(ui.getPanel(), ui.getHeader());
678
+ }
641
679
  var mediaQueryList = null;
642
680
  var handleHostThemeChange = null;
643
681
  if (typeof window.matchMedia === "function") {
@@ -651,9 +689,44 @@ function mountFromScript(scriptTag) {
651
689
  if (typeof mediaQueryList.addEventListener === "function") mediaQueryList.addEventListener("change", handleHostThemeChange);
652
690
  else if (typeof mediaQueryList.addListener === "function") mediaQueryList.addListener(handleHostThemeChange);
653
691
  }
692
+ var signalementActive = false;
693
+
694
+ if (signalementModule) {
695
+ events.on("module:signalement:open", function() { signalementActive = true; });
696
+ events.on("module:signalement:closed", function() { signalementActive = false; });
697
+ events.on("module:signalement:submitted", function(result) {
698
+ signalementActive = false;
699
+ ui.addMessage("assistant", "");
700
+ var lastMsg = ui.messages.lastElementChild;
701
+ if (lastMsg) ui.setAssistantFinalText(lastMsg, "Merci, votre signalement a été transmis. Référence : **" + (result.signalement_id || "N/A") + "**");
702
+ });
703
+ }
704
+
705
+ async function handleSignalementSubmit() {
706
+ if (!signalementModule || !signalementActive) return;
707
+ state.sending = true;
708
+ ui.setComposerDisabled(true);
709
+ ui.showError("");
710
+ try {
711
+ await api.ensureSession();
712
+ await signalementModule.submit();
713
+ } catch (error) {
714
+ ui.showError((error && error.message) || "Erreur lors de l'envoi du signalement.");
715
+ } finally {
716
+ state.sending = false;
717
+ ui.setComposerDisabled(false);
718
+ }
719
+ }
720
+
654
721
  async function handleSend(event) {
655
722
  event.preventDefault();
656
723
  if (state.sending || state.listening) return;
724
+
725
+ if (signalementActive && signalementModule) {
726
+ await handleSignalementSubmit();
727
+ return;
728
+ }
729
+
657
730
  var message = ui.pullInput();
658
731
  if (!message) return;
659
732
  state.sending = true;
@@ -664,14 +737,30 @@ function mountFromScript(scriptTag) {
664
737
  try {
665
738
  var sessionId = await api.postMessage(message);
666
739
  ui.startAssistantStream();
740
+ var pendingSignalementData = null;
667
741
  await api.streamSession(sessionId, {
668
742
  onToken: function(token) { ui.appendAssistantToken(token); },
669
- onFinal: function(payload) { ui.finalizeAssistantMessage(payload.content || ""); },
743
+ onModuleSignalement: function(payload) {
744
+ pendingSignalementData = payload || {};
745
+ },
746
+ onFinal: function(payload) {
747
+ ui.finalizeAssistantMessage(payload.content || "");
748
+ var sigData = pendingSignalementData || (payload.module_signalement ? payload.module_signalement : null);
749
+ if (signalementModule && sigData) {
750
+ var streamEl = ui.messages.lastElementChild;
751
+ ui.injectSignalementButton(streamEl, function() {
752
+ signalementModule.open(sigData);
753
+ });
754
+ }
755
+ },
670
756
  onError: function(errorText) { ui.showError(errorText || "Erreur de streaming."); },
671
757
  onDone: function() {}
672
758
  });
673
759
  } catch (error) {
674
- ui.showError((error && error.message) || "Impossible d'envoyer le message.");
760
+ var sendErrorMessage = (error && error.message) || "Impossible d'envoyer le message.";
761
+ ui.showRetryableError(sendErrorMessage, function() {
762
+ handleSend(event);
763
+ });
675
764
  } finally {
676
765
  state.sending = false;
677
766
  ui.showTyping(false);
@@ -684,7 +773,18 @@ function mountFromScript(scriptTag) {
684
773
  events.emit(state.open ? "open" : "close", {});
685
774
  if (state.open) {
686
775
  api.ensureSession().catch(function(error) {
687
- ui.showError((error && error.message) || "Impossible d'initialiser le chat.");
776
+ var errorMessage = (error && error.message) || "Impossible d'initialiser le chat.";
777
+ ui.showRetryableError(errorMessage, function() {
778
+ state.sessionId = "";
779
+ state.token = "";
780
+ state.bootstrapPromise = null;
781
+ state.sessionPromise = null;
782
+ if (turnstile) turnstile.invalidateCache();
783
+ api.prefetchedBootstrapAcked = false;
784
+ api.ensureSession().catch(function(retryError) {
785
+ ui.showRetryableError((retryError && retryError.message) || "Impossible d'initialiser le chat.", arguments.callee);
786
+ });
787
+ });
688
788
  });
689
789
  }
690
790
  }
@@ -705,7 +805,6 @@ function mountFromScript(scriptTag) {
705
805
  if (typeof mediaQueryList.removeEventListener === "function") mediaQueryList.removeEventListener("change", handleHostThemeChange);
706
806
  else if (typeof mediaQueryList.removeListener === "function") mediaQueryList.removeListener(handleHostThemeChange);
707
807
  }
708
- if (audio.stopDraftStream) audio.stopDraftStream();
709
808
  audio.cleanupMedia();
710
809
  if (ui.host && ui.host.parentNode) ui.host.parentNode.removeChild(ui.host);
711
810
  }, on: function(eventName, handler) { events.on(eventName, handler); } };
@@ -1,6 +1,6 @@
1
1
  (function() {
2
2
  "use strict";
3
- var __WIDGET_MANIFEST__ = {"ui.v1.js":"ui.v1.41a99419.js","audio.v1.js":"audio.v1.95146620.js","engine.v1.js":"engine.v1.3b09dc20.js"};
3
+ var __WIDGET_MANIFEST__ = {"ui.v1.js":"ui.v1.e007c7c4.js","audio.v1.js":"audio.v1.20858b08.js","signalement.v1.js":"signalement.v1.d321dfde.js","engine.v1.js":"engine.v1.c127656e.js"};
4
4
 
5
5
 
6
6
  var RUNTIME_NS = "__OurluWidgetRuntimeV1";
@@ -45,14 +45,18 @@
45
45
  if (!window[RUNTIME_FLAG]) {
46
46
  var uiFileName = resolveManifestFileName("ui.v1.js");
47
47
  var audioFileName = resolveManifestFileName("audio.v1.js");
48
+ var signalementFileName = resolveManifestFileName("signalement.v1.js");
48
49
  var engineFileName = resolveManifestFileName("engine.v1.js");
49
50
 
50
51
  var uiRuntimeUrl = scriptTag.getAttribute("data-runtime-ui-url") || buildApiRuntimeAssetUrl(scriptTag, uiFileName);
51
52
  var audioRuntimeUrl = scriptTag.getAttribute("data-runtime-audio-url") || buildApiRuntimeAssetUrl(scriptTag, audioFileName);
53
+ var signalementRuntimeUrl = scriptTag.getAttribute("data-runtime-signalement-url") || buildApiRuntimeAssetUrl(scriptTag, signalementFileName);
52
54
  var engineRuntimeUrl = scriptTag.getAttribute("data-runtime-engine-url") || buildApiRuntimeAssetUrl(scriptTag, engineFileName);
53
55
 
54
56
  window[RUNTIME_FLAG] = loadScript(uiRuntimeUrl).then(function() {
55
57
  return loadScript(audioRuntimeUrl);
58
+ }).then(function() {
59
+ return loadScript(signalementRuntimeUrl);
56
60
  }).then(function() {
57
61
  return loadScript(engineRuntimeUrl);
58
62
  });