dsh-live-voice-debugger 0.6.1 → 0.6.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.
package/lib/client.js CHANGED
@@ -74,10 +74,17 @@ var init_en2 = __esm({
74
74
  translation2 = {
75
75
  active: "Recording",
76
76
  allSources: "All sources",
77
+ assistantEnd: "Assistant playback ended",
78
+ assistantPause: "Assistant playback paused",
79
+ assistantResume: "Assistant playback resumed",
80
+ assistantStart: "Assistant playback started",
77
81
  attempts: "Transcription history",
78
82
  audio: "Recording playback",
79
83
  audioError: "Unable to load or play recording audio.",
80
84
  cancel: "Cancel",
85
+ captureEnd: "Capture ended",
86
+ captureGated: "Microphone suspension requested for speaker playback",
87
+ captureStart: "Capture started",
81
88
  captured: "Captured audio",
82
89
  completed: "Completed",
83
90
  confirmDelete: "Delete this entire recording, including its audio and transcription history? This cannot be undone. Deleting an active recording also discards its future saved audio.",
@@ -89,6 +96,9 @@ var init_en2 = __esm({
89
96
  end: "End",
90
97
  engine: "Engine",
91
98
  error: "Error",
99
+ eventTime: "Event time",
100
+ events: "Assistant and capture events",
101
+ eventsHelp: "Markers show the captured audio boundary and the actual event time. Events after capture stops may share its final boundary; no assistant audio is added to the recording.",
92
102
  export: "Export self-contained JSON",
93
103
  exportError: "Unable to export the recording.",
94
104
  failed: "Failed",
@@ -98,6 +108,8 @@ var init_en2 = __esm({
98
108
  loading: "Loading recordings\u2026",
99
109
  memory: "Memory only",
100
110
  microphone: "Microphone",
111
+ name: "Session name",
112
+ nameError: "Unable to save the name. Star the session and use a single line of at most 120 characters.",
101
113
  noAttempts: "No transcription attempts yet.",
102
114
  open: "Open segment",
103
115
  pending: "Pending",
@@ -108,7 +120,10 @@ var init_en2 = __esm({
108
120
  play: "Play segment",
109
121
  playSession: "Play saved session",
110
122
  refresh: "Refresh recordings",
123
+ saveName: "Save name",
111
124
  saved: "Saved audio",
125
+ search: "Search segment transcripts",
126
+ searchEmpty: "No transcribed segments match.",
112
127
  segments: "Segments",
113
128
  selectSession: "Select a recording session.",
114
129
  shared: "Shared audio",
@@ -122,12 +137,19 @@ var init_en2 = __esm({
122
137
  starred: "Protected from automatic cleanup",
123
138
  start: "Start",
124
139
  state: "State",
140
+ storageAudio: "Stored audio (MB)",
141
+ storageTotal: "Total stored audio (MB)",
142
+ storageUnknown: "Unavailable",
125
143
  success: "Success",
126
144
  timeline: "Speech / silence timeline",
127
145
  title: "Recordings",
128
146
  unavailable: "Recording service unavailable. Enable recording in Live Voice settings with a compatible runtime.",
129
147
  unstar: "Remove protection",
130
- unstarHelp: "Allow automatic cleanup and include this recording in the retention count again. Manual deletion is still allowed. Browser storage and eviction protection are unchanged."
148
+ unstarHelp: "Allow automatic cleanup and include this recording in the retention count again. Manual deletion is still allowed. Browser storage and eviction protection are unchanged.",
149
+ window: "Timeline window",
150
+ windowEnd: "Window end",
151
+ windowReset: "Show full session",
152
+ windowStart: "Window start"
131
153
  };
132
154
  en_default2 = Object.freeze(translation2);
133
155
  }
@@ -236,10 +258,17 @@ var init_es2 = __esm({
236
258
  translation6 = {
237
259
  active: "Grabando",
238
260
  allSources: "Todas las fuentes",
261
+ assistantEnd: "Reproducci\xF3n del asistente finalizada",
262
+ assistantPause: "Reproducci\xF3n del asistente pausada",
263
+ assistantResume: "Reproducci\xF3n del asistente reanudada",
264
+ assistantStart: "Reproducci\xF3n del asistente iniciada",
239
265
  attempts: "Historial de transcripci\xF3n",
240
266
  audio: "Reproducci\xF3n de la grabaci\xF3n",
241
267
  audioError: "No se pudo cargar o reproducir el audio.",
242
268
  cancel: "Cancelar",
269
+ captureEnd: "Captura finalizada",
270
+ captureGated: "Suspensi\xF3n del micr\xF3fono solicitada para reproducir por altavoz",
271
+ captureStart: "Captura iniciada",
243
272
  captured: "Audio capturado",
244
273
  completed: "Completada",
245
274
  confirmDelete: "\xBFEliminar toda esta grabaci\xF3n, incluido el audio y el historial de transcripci\xF3n? No se puede deshacer. Eliminar una grabaci\xF3n activa tambi\xE9n descarta su audio guardado futuro.",
@@ -251,6 +280,9 @@ var init_es2 = __esm({
251
280
  end: "Fin",
252
281
  engine: "Motor",
253
282
  error: "Error",
283
+ eventTime: "Hora del evento",
284
+ events: "Eventos del asistente y la captura",
285
+ eventsHelp: "Los marcadores muestran el l\xEDmite del audio capturado y la hora real del evento. Tras detener la captura, varios eventos pueden compartir su l\xEDmite final; no se a\xF1ade audio del asistente.",
254
286
  export: "Exportar JSON completo",
255
287
  exportError: "No se pudo exportar la grabaci\xF3n.",
256
288
  failed: "Fallida",
@@ -260,6 +292,8 @@ var init_es2 = __esm({
260
292
  loading: "Cargando grabaciones\u2026",
261
293
  memory: "Solo en memoria",
262
294
  microphone: "Micr\xF3fono",
295
+ name: "Nombre de la sesi\xF3n",
296
+ nameError: "No se pudo guardar el nombre. Marca la sesi\xF3n con estrella y usa una l\xEDnea de hasta 120 caracteres.",
263
297
  noAttempts: "Todav\xEDa no hay intentos de transcripci\xF3n.",
264
298
  open: "Segmento abierto",
265
299
  pending: "Pendiente",
@@ -270,7 +304,10 @@ var init_es2 = __esm({
270
304
  play: "Reproducir segmento",
271
305
  playSession: "Reproducir sesi\xF3n guardada",
272
306
  refresh: "Actualizar grabaciones",
307
+ saveName: "Guardar nombre",
273
308
  saved: "Audio guardado",
309
+ search: "Buscar transcripciones de segmentos",
310
+ searchEmpty: "No hay segmentos transcritos que coincidan.",
274
311
  segments: "Segmentos",
275
312
  selectSession: "Seleccione una sesi\xF3n de grabaci\xF3n.",
276
313
  shared: "Audio compartido",
@@ -284,12 +321,19 @@ var init_es2 = __esm({
284
321
  starred: "Protegida de la limpieza autom\xE1tica",
285
322
  start: "Inicio",
286
323
  state: "Estado",
324
+ storageAudio: "Audio almacenado (MB)",
325
+ storageTotal: "Total de audio almacenado (MB)",
326
+ storageUnknown: "No disponible",
287
327
  success: "\xC9xito",
288
328
  timeline: "Cronolog\xEDa de voz / silencio",
289
329
  title: "Grabaciones",
290
330
  unavailable: "Servicio de grabaci\xF3n no disponible. Active la grabaci\xF3n en los ajustes de Voz en vivo con un runtime compatible.",
291
331
  unstar: "Quitar protecci\xF3n",
292
- unstarHelp: "Permite la limpieza autom\xE1tica e incluye de nuevo esta grabaci\xF3n en el recuento de retenci\xF3n. La eliminaci\xF3n manual sigue permitida. El almacenamiento y la protecci\xF3n contra eliminaci\xF3n del navegador no cambian."
332
+ unstarHelp: "Permite la limpieza autom\xE1tica e incluye de nuevo esta grabaci\xF3n en el recuento de retenci\xF3n. La eliminaci\xF3n manual sigue permitida. El almacenamiento y la protecci\xF3n contra eliminaci\xF3n del navegador no cambian.",
333
+ window: "Intervalo de la l\xEDnea de tiempo",
334
+ windowEnd: "Fin del intervalo",
335
+ windowReset: "Mostrar toda la sesi\xF3n",
336
+ windowStart: "Inicio del intervalo"
293
337
  };
294
338
  es_default2 = Object.freeze(translation6);
295
339
  }
@@ -398,10 +442,17 @@ var init_fr2 = __esm({
398
442
  translation10 = {
399
443
  active: "Enregistrement",
400
444
  allSources: "Toutes les sources",
445
+ assistantEnd: "Lecture de l\u2019assistant termin\xE9e",
446
+ assistantPause: "Lecture de l\u2019assistant en pause",
447
+ assistantResume: "Lecture de l\u2019assistant reprise",
448
+ assistantStart: "Lecture de l\u2019assistant d\xE9marr\xE9e",
401
449
  attempts: "Historique des transcriptions",
402
450
  audio: "Lecture de l\u2019enregistrement",
403
451
  audioError: "Impossible de charger ou lire l\u2019audio.",
404
452
  cancel: "Annuler",
453
+ captureEnd: "Capture termin\xE9e",
454
+ captureGated: "Suspension du microphone demand\xE9e pour la lecture sur haut-parleur",
455
+ captureStart: "Capture d\xE9marr\xE9e",
405
456
  captured: "Audio captur\xE9",
406
457
  completed: "Termin\xE9",
407
458
  confirmDelete: "Supprimer cet enregistrement entier, y compris son audio et son historique de transcription ? Cette action est irr\xE9versible. Supprimer un enregistrement actif supprime aussi son futur audio enregistr\xE9.",
@@ -413,6 +464,9 @@ var init_fr2 = __esm({
413
464
  end: "Fin",
414
465
  engine: "Moteur",
415
466
  error: "Erreur",
467
+ eventTime: "Heure de l\u2019\xE9v\xE9nement",
468
+ events: "\xC9v\xE9nements de l\u2019assistant et de la capture",
469
+ eventsHelp: "Les rep\xE8res indiquent la limite audio captur\xE9e et l\u2019heure r\xE9elle. Apr\xE8s l\u2019arr\xEAt de la capture, plusieurs \xE9v\xE9nements peuvent partager la limite finale ; aucun audio de l\u2019assistant n\u2019est ajout\xE9.",
416
470
  export: "Exporter le JSON autonome",
417
471
  exportError: "Impossible d\u2019exporter l\u2019enregistrement.",
418
472
  failed: "\xC9chec",
@@ -422,6 +476,8 @@ var init_fr2 = __esm({
422
476
  loading: "Chargement des enregistrements\u2026",
423
477
  memory: "En m\xE9moire uniquement",
424
478
  microphone: "Microphone",
479
+ name: "Nom de la session",
480
+ nameError: "Impossible d\u2019enregistrer le nom. Marquez la session d\u2019une \xE9toile et utilisez une ligne de 120 caract\xE8res maximum.",
425
481
  noAttempts: "Aucune tentative de transcription.",
426
482
  open: "Segment ouvert",
427
483
  pending: "En attente",
@@ -432,7 +488,10 @@ var init_fr2 = __esm({
432
488
  play: "Lire le segment",
433
489
  playSession: "Lire la session sauvegard\xE9e",
434
490
  refresh: "Actualiser les enregistrements",
491
+ saveName: "Enregistrer le nom",
435
492
  saved: "Audio sauvegard\xE9",
493
+ search: "Rechercher dans les transcriptions",
494
+ searchEmpty: "Aucun segment transcrit ne correspond.",
436
495
  segments: "Segments",
437
496
  selectSession: "S\xE9lectionnez une session d\u2019enregistrement.",
438
497
  shared: "Audio partag\xE9",
@@ -446,12 +505,19 @@ var init_fr2 = __esm({
446
505
  starred: "Prot\xE9g\xE9 du nettoyage automatique",
447
506
  start: "D\xE9but",
448
507
  state: "\xC9tat",
508
+ storageAudio: "Audio stock\xE9 (MB)",
509
+ storageTotal: "Total de l\u2019audio stock\xE9 (MB)",
510
+ storageUnknown: "Indisponible",
449
511
  success: "R\xE9ussite",
450
512
  timeline: "Chronologie parole / silence",
451
513
  title: "Enregistrements",
452
514
  unavailable: "Service d\u2019enregistrement indisponible. Activez l\u2019enregistrement dans les param\xE8tres de Voix en direct avec un runtime compatible.",
453
515
  unstar: "Retirer la protection",
454
- unstarHelp: "Autorise le nettoyage automatique et compte \xE0 nouveau cet enregistrement parmi ceux \xE0 conserver. La suppression manuelle reste autoris\xE9e. Le stockage et la protection contre l\u2019\xE9viction par le navigateur ne changent pas."
516
+ unstarHelp: "Autorise le nettoyage automatique et compte \xE0 nouveau cet enregistrement parmi ceux \xE0 conserver. La suppression manuelle reste autoris\xE9e. Le stockage et la protection contre l\u2019\xE9viction par le navigateur ne changent pas.",
517
+ window: "Intervalle de la chronologie",
518
+ windowEnd: "Fin de l\u2019intervalle",
519
+ windowReset: "Afficher toute la session",
520
+ windowStart: "D\xE9but de l\u2019intervalle"
455
521
  };
456
522
  fr_default2 = Object.freeze(translation10);
457
523
  }
@@ -560,10 +626,17 @@ var init_hi2 = __esm({
560
626
  translation14 = {
561
627
  active: "\u0930\u093F\u0915\u0949\u0930\u094D\u0921\u093F\u0902\u0917 \u091C\u093E\u0930\u0940",
562
628
  allSources: "\u0938\u092D\u0940 \u0938\u094D\u0930\u094B\u0924",
629
+ assistantEnd: "\u0938\u0939\u093E\u092F\u0915 \u0915\u093E \u092A\u094D\u0932\u0947\u092C\u0948\u0915 \u0938\u092E\u093E\u092A\u094D\u0924",
630
+ assistantPause: "\u0938\u0939\u093E\u092F\u0915 \u0915\u093E \u092A\u094D\u0932\u0947\u092C\u0948\u0915 \u0930\u0941\u0915\u093E",
631
+ assistantResume: "\u0938\u0939\u093E\u092F\u0915 \u0915\u093E \u092A\u094D\u0932\u0947\u092C\u0948\u0915 \u092B\u093F\u0930 \u0936\u0941\u0930\u0942",
632
+ assistantStart: "\u0938\u0939\u093E\u092F\u0915 \u0915\u093E \u092A\u094D\u0932\u0947\u092C\u0948\u0915 \u0936\u0941\u0930\u0942",
563
633
  attempts: "\u091F\u094D\u0930\u093E\u0902\u0938\u0915\u094D\u0930\u093F\u092A\u094D\u0936\u0928 \u0907\u0924\u093F\u0939\u093E\u0938",
564
634
  audio: "\u0930\u093F\u0915\u0949\u0930\u094D\u0921\u093F\u0902\u0917 \u092A\u094D\u0932\u0947\u092C\u0948\u0915",
565
635
  audioError: "\u0930\u093F\u0915\u0949\u0930\u094D\u0921\u093F\u0902\u0917 \u0911\u0921\u093F\u092F\u094B \u0932\u094B\u0921 \u092F\u093E \u091A\u0932\u093E\u092F\u093E \u0928\u0939\u0940\u0902 \u091C\u093E \u0938\u0915\u093E\u0964",
566
636
  cancel: "\u0930\u0926\u094D\u0926 \u0915\u0930\u0947\u0902",
637
+ captureEnd: "\u0915\u0948\u092A\u094D\u091A\u0930 \u0938\u092E\u093E\u092A\u094D\u0924",
638
+ captureGated: "\u0938\u094D\u092A\u0940\u0915\u0930 \u092A\u094D\u0932\u0947\u092C\u0948\u0915 \u0915\u0947 \u0932\u093F\u090F \u092E\u093E\u0907\u0915\u094D\u0930\u094B\u092B\u093C\u094B\u0928 \u0930\u094B\u0915\u0928\u0947 \u0915\u093E \u0905\u0928\u0941\u0930\u094B\u0927",
639
+ captureStart: "\u0915\u0948\u092A\u094D\u091A\u0930 \u0936\u0941\u0930\u0942",
567
640
  captured: "\u0915\u0948\u092A\u094D\u091A\u0930 \u0915\u093F\u092F\u093E \u0917\u092F\u093E \u0911\u0921\u093F\u092F\u094B",
568
641
  completed: "\u092A\u0942\u0930\u094D\u0923",
569
642
  confirmDelete: "\u0911\u0921\u093F\u092F\u094B \u0914\u0930 \u091F\u094D\u0930\u093E\u0902\u0938\u0915\u094D\u0930\u093F\u092A\u094D\u0936\u0928 \u0907\u0924\u093F\u0939\u093E\u0938 \u0938\u0939\u093F\u0924 \u092F\u0939 \u092A\u0942\u0930\u0940 \u0930\u093F\u0915\u0949\u0930\u094D\u0921\u093F\u0902\u0917 \u0939\u091F\u093E\u090F\u0901? \u0907\u0938\u0947 \u0935\u093E\u092A\u0938 \u0928\u0939\u0940\u0902 \u0932\u093E\u092F\u093E \u091C\u093E \u0938\u0915\u0924\u093E\u0964 \u0938\u0915\u094D\u0930\u093F\u092F \u0930\u093F\u0915\u0949\u0930\u094D\u0921\u093F\u0902\u0917 \u0939\u091F\u093E\u0928\u0947 \u092A\u0930 \u0906\u0917\u0947 \u0938\u0939\u0947\u091C\u093E \u091C\u093E\u0928\u0947 \u0935\u093E\u0932\u093E \u0911\u0921\u093F\u092F\u094B \u092D\u0940 \u0939\u091F\u093E \u0926\u093F\u092F\u093E \u091C\u093E\u0924\u093E \u0939\u0948\u0964",
@@ -575,6 +648,9 @@ var init_hi2 = __esm({
575
648
  end: "\u0905\u0902\u0924",
576
649
  engine: "\u0907\u0902\u091C\u0928",
577
650
  error: "\u0924\u094D\u0930\u0941\u091F\u093F",
651
+ eventTime: "\u0918\u091F\u0928\u093E \u0915\u093E \u0938\u092E\u092F",
652
+ events: "\u0938\u0939\u093E\u092F\u0915 \u0914\u0930 \u0915\u0948\u092A\u094D\u091A\u0930 \u0915\u0940 \u0918\u091F\u0928\u093E\u090F\u0901",
653
+ eventsHelp: "\u091A\u093F\u0939\u094D\u0928 \u0915\u0948\u092A\u094D\u091A\u0930 \u0915\u093F\u090F \u0917\u090F \u0911\u0921\u093F\u092F\u094B \u0915\u0940 \u0938\u0940\u092E\u093E \u0914\u0930 \u0918\u091F\u0928\u093E \u0915\u093E \u0935\u093E\u0938\u094D\u0924\u0935\u093F\u0915 \u0938\u092E\u092F \u0926\u093F\u0916\u093E\u0924\u0947 \u0939\u0948\u0902\u0964 \u0915\u0948\u092A\u094D\u091A\u0930 \u0930\u0941\u0915\u0928\u0947 \u0915\u0947 \u092C\u093E\u0926 \u0918\u091F\u0928\u093E\u0913\u0902 \u0915\u0940 \u0905\u0902\u0924\u093F\u092E \u0938\u0940\u092E\u093E \u0938\u092E\u093E\u0928 \u0939\u094B \u0938\u0915\u0924\u0940 \u0939\u0948; \u0938\u0939\u093E\u092F\u0915 \u0915\u093E \u0911\u0921\u093F\u092F\u094B \u0930\u093F\u0915\u0949\u0930\u094D\u0921\u093F\u0902\u0917 \u092E\u0947\u0902 \u0928\u0939\u0940\u0902 \u091C\u094B\u0921\u093C\u093E \u091C\u093E\u0924\u093E\u0964",
578
654
  export: "\u0938\u094D\u0935\u092F\u0902\u092A\u0942\u0930\u094D\u0923 JSON \u0928\u093F\u0930\u094D\u092F\u093E\u0924 \u0915\u0930\u0947\u0902",
579
655
  exportError: "\u0930\u093F\u0915\u0949\u0930\u094D\u0921\u093F\u0902\u0917 \u0928\u093F\u0930\u094D\u092F\u093E\u0924 \u0928\u0939\u0940\u0902 \u0915\u0940 \u091C\u093E \u0938\u0915\u0940\u0964",
580
656
  failed: "\u0935\u093F\u092B\u0932",
@@ -584,6 +660,8 @@ var init_hi2 = __esm({
584
660
  loading: "\u0930\u093F\u0915\u0949\u0930\u094D\u0921\u093F\u0902\u0917 \u0932\u094B\u0921 \u0939\u094B \u0930\u0939\u0940 \u0939\u0948\u0902\u2026",
585
661
  memory: "\u0915\u0947\u0935\u0932 \u092E\u0947\u092E\u094B\u0930\u0940 \u092E\u0947\u0902",
586
662
  microphone: "\u092E\u093E\u0907\u0915\u094D\u0930\u094B\u092B\u093C\u094B\u0928",
663
+ name: "\u0938\u0924\u094D\u0930 \u0915\u093E \u0928\u093E\u092E",
664
+ nameError: "\u0928\u093E\u092E \u0938\u0939\u0947\u091C\u093E \u0928\u0939\u0940\u0902 \u091C\u093E \u0938\u0915\u093E\u0964 \u0938\u0924\u094D\u0930 \u092A\u0930 \u0924\u093E\u0930\u093E \u0932\u0917\u093E\u090F\u0901 \u0914\u0930 \u0905\u0927\u093F\u0915\u0924\u092E 120 \u0905\u0915\u094D\u0937\u0930\u094B\u0902 \u0915\u0940 \u090F\u0915 \u092A\u0902\u0915\u094D\u0924\u093F \u0915\u093E \u0909\u092A\u092F\u094B\u0917 \u0915\u0930\u0947\u0902\u0964",
587
665
  noAttempts: "\u0905\u092D\u0940 \u0915\u094B\u0908 \u091F\u094D\u0930\u093E\u0902\u0938\u0915\u094D\u0930\u093F\u092A\u094D\u0936\u0928 \u092A\u094D\u0930\u092F\u093E\u0938 \u0928\u0939\u0940\u0902 \u0939\u0948\u0964",
588
666
  open: "\u0916\u0941\u0932\u093E \u0916\u0902\u0921",
589
667
  pending: "\u0932\u0902\u092C\u093F\u0924",
@@ -594,7 +672,10 @@ var init_hi2 = __esm({
594
672
  play: "\u0916\u0902\u0921 \u091A\u0932\u093E\u090F\u0901",
595
673
  playSession: "\u0938\u0939\u0947\u091C\u093E \u0938\u0924\u094D\u0930 \u091A\u0932\u093E\u090F\u0901",
596
674
  refresh: "\u0930\u093F\u0915\u0949\u0930\u094D\u0921\u093F\u0902\u0917 \u0930\u0940\u092B\u093C\u094D\u0930\u0947\u0936 \u0915\u0930\u0947\u0902",
675
+ saveName: "\u0928\u093E\u092E \u0938\u0939\u0947\u091C\u0947\u0902",
597
676
  saved: "\u0938\u0939\u0947\u091C\u093E \u0911\u0921\u093F\u092F\u094B",
677
+ search: "\u0916\u0902\u0921\u094B\u0902 \u0915\u0947 \u092A\u094D\u0930\u0924\u093F\u0932\u0947\u0916 \u0916\u094B\u091C\u0947\u0902",
678
+ searchEmpty: "\u0915\u094B\u0908 \u092E\u0947\u0932 \u0916\u093E\u0924\u093E \u092A\u094D\u0930\u0924\u093F\u0932\u093F\u0916\u093F\u0924 \u0916\u0902\u0921 \u0928\u0939\u0940\u0902 \u092E\u093F\u0932\u093E\u0964",
598
679
  segments: "\u0916\u0902\u0921",
599
680
  selectSession: "\u0930\u093F\u0915\u0949\u0930\u094D\u0921\u093F\u0902\u0917 \u0938\u0924\u094D\u0930 \u091A\u0941\u0928\u0947\u0902\u0964",
600
681
  shared: "\u0938\u093E\u091D\u093E \u0911\u0921\u093F\u092F\u094B",
@@ -608,12 +689,19 @@ var init_hi2 = __esm({
608
689
  starred: "\u0938\u094D\u0935\u091A\u093E\u0932\u093F\u0924 \u0938\u092B\u093C\u093E\u0908 \u0938\u0947 \u0938\u0941\u0930\u0915\u094D\u0937\u093F\u0924",
609
690
  start: "\u0936\u0941\u0930\u0941\u0906\u0924",
610
691
  state: "\u0938\u094D\u0925\u093F\u0924\u093F",
692
+ storageAudio: "\u0938\u0939\u0947\u091C\u093E \u0917\u092F\u093E \u0911\u0921\u093F\u092F\u094B (MB)",
693
+ storageTotal: "\u0915\u0941\u0932 \u0938\u0939\u0947\u091C\u093E \u0917\u092F\u093E \u0911\u0921\u093F\u092F\u094B (MB)",
694
+ storageUnknown: "\u0905\u0928\u0941\u092A\u0932\u092C\u094D\u0927",
611
695
  success: "\u0938\u092B\u0932",
612
696
  timeline: "\u0906\u0935\u093E\u091C\u093C / \u092E\u094C\u0928 \u0938\u092E\u092F\u0930\u0947\u0916\u093E",
613
697
  title: "\u0930\u093F\u0915\u0949\u0930\u094D\u0921\u093F\u0902\u0917",
614
698
  unavailable: "\u0930\u093F\u0915\u0949\u0930\u094D\u0921\u093F\u0902\u0917 \u0938\u0947\u0935\u093E \u0909\u092A\u0932\u092C\u094D\u0927 \u0928\u0939\u0940\u0902 \u0939\u0948\u0964 \u0938\u0902\u0917\u0924 \u0930\u0928\u091F\u093E\u0907\u092E \u0915\u0947 \u0938\u093E\u0925 \u0932\u093E\u0907\u0935 \u0935\u0949\u0907\u0938 \u0938\u0947\u091F\u093F\u0902\u0917\u094D\u0938 \u092E\u0947\u0902 \u0930\u093F\u0915\u0949\u0930\u094D\u0921\u093F\u0902\u0917 \u091A\u093E\u0932\u0942 \u0915\u0930\u0947\u0902\u0964",
615
699
  unstar: "\u0938\u0941\u0930\u0915\u094D\u0937\u093E \u0939\u091F\u093E\u090F\u0901",
616
- unstarHelp: "\u0938\u094D\u0935\u091A\u093E\u0932\u093F\u0924 \u0938\u092B\u093C\u093E\u0908 \u0915\u0940 \u0905\u0928\u0941\u092E\u0924\u093F \u0926\u0947\u0902 \u0914\u0930 \u0907\u0938 \u0930\u093F\u0915\u0949\u0930\u094D\u0921\u093F\u0902\u0917 \u0915\u094B \u092B\u093F\u0930 \u0938\u0947 \u0930\u0916\u0940 \u091C\u093E\u0928\u0947 \u0935\u093E\u0932\u0940 \u0930\u093F\u0915\u0949\u0930\u094D\u0921\u093F\u0902\u0917 \u0915\u0940 \u0917\u093F\u0928\u0924\u0940 \u092E\u0947\u0902 \u0936\u093E\u092E\u093F\u0932 \u0915\u0930\u0947\u0902\u0964 \u092E\u0948\u0928\u094D\u092F\u0941\u0905\u0932 \u0930\u0942\u092A \u0938\u0947 \u0939\u091F\u093E\u0928\u093E \u0905\u092C \u092D\u0940 \u0938\u0902\u092D\u0935 \u0939\u0948\u0964 \u092C\u094D\u0930\u093E\u0909\u091C\u093C\u0930 \u0915\u093E \u0938\u094D\u091F\u094B\u0930\u0947\u091C \u0914\u0930 \u0928\u093F\u0937\u094D\u0915\u093E\u0938\u0928 \u0938\u0941\u0930\u0915\u094D\u0937\u093E \u0928\u0939\u0940\u0902 \u092C\u0926\u0932\u0924\u0947\u0964"
700
+ unstarHelp: "\u0938\u094D\u0935\u091A\u093E\u0932\u093F\u0924 \u0938\u092B\u093C\u093E\u0908 \u0915\u0940 \u0905\u0928\u0941\u092E\u0924\u093F \u0926\u0947\u0902 \u0914\u0930 \u0907\u0938 \u0930\u093F\u0915\u0949\u0930\u094D\u0921\u093F\u0902\u0917 \u0915\u094B \u092B\u093F\u0930 \u0938\u0947 \u0930\u0916\u0940 \u091C\u093E\u0928\u0947 \u0935\u093E\u0932\u0940 \u0930\u093F\u0915\u0949\u0930\u094D\u0921\u093F\u0902\u0917 \u0915\u0940 \u0917\u093F\u0928\u0924\u0940 \u092E\u0947\u0902 \u0936\u093E\u092E\u093F\u0932 \u0915\u0930\u0947\u0902\u0964 \u092E\u0948\u0928\u094D\u092F\u0941\u0905\u0932 \u0930\u0942\u092A \u0938\u0947 \u0939\u091F\u093E\u0928\u093E \u0905\u092C \u092D\u0940 \u0938\u0902\u092D\u0935 \u0939\u0948\u0964 \u092C\u094D\u0930\u093E\u0909\u091C\u093C\u0930 \u0915\u093E \u0938\u094D\u091F\u094B\u0930\u0947\u091C \u0914\u0930 \u0928\u093F\u0937\u094D\u0915\u093E\u0938\u0928 \u0938\u0941\u0930\u0915\u094D\u0937\u093E \u0928\u0939\u0940\u0902 \u092C\u0926\u0932\u0924\u0947\u0964",
701
+ window: "\u091F\u093E\u0907\u092E\u0932\u093E\u0907\u0928 \u0915\u093E \u0939\u093F\u0938\u094D\u0938\u093E",
702
+ windowEnd: "\u0939\u093F\u0938\u094D\u0938\u0947 \u0915\u093E \u0905\u0902\u0924",
703
+ windowReset: "\u092A\u0942\u0930\u093E \u0938\u0924\u094D\u0930 \u0926\u093F\u0916\u093E\u090F\u0901",
704
+ windowStart: "\u0939\u093F\u0938\u094D\u0938\u0947 \u0915\u0940 \u0936\u0941\u0930\u0941\u0906\u0924"
617
705
  };
618
706
  hi_default2 = Object.freeze(translation14);
619
707
  }
@@ -722,10 +810,17 @@ var init_pt_BR2 = __esm({
722
810
  translation18 = {
723
811
  active: "Gravando",
724
812
  allSources: "Todas as fontes",
813
+ assistantEnd: "Reprodu\xE7\xE3o do assistente encerrada",
814
+ assistantPause: "Reprodu\xE7\xE3o do assistente pausada",
815
+ assistantResume: "Reprodu\xE7\xE3o do assistente retomada",
816
+ assistantStart: "Reprodu\xE7\xE3o do assistente iniciada",
725
817
  attempts: "Hist\xF3rico de transcri\xE7\xE3o",
726
818
  audio: "Reprodu\xE7\xE3o da grava\xE7\xE3o",
727
819
  audioError: "N\xE3o foi poss\xEDvel carregar ou reproduzir o \xE1udio.",
728
820
  cancel: "Cancelar",
821
+ captureEnd: "Captura encerrada",
822
+ captureGated: "Suspens\xE3o do microfone solicitada para reprodu\xE7\xE3o no alto-falante",
823
+ captureStart: "Captura iniciada",
729
824
  captured: "\xC1udio capturado",
730
825
  completed: "Conclu\xEDda",
731
826
  confirmDelete: "Excluir esta grava\xE7\xE3o inteira, incluindo \xE1udio e hist\xF3rico de transcri\xE7\xE3o? N\xE3o \xE9 poss\xEDvel desfazer. Excluir uma grava\xE7\xE3o ativa tamb\xE9m descarta o \xE1udio salvo futuro.",
@@ -737,6 +832,9 @@ var init_pt_BR2 = __esm({
737
832
  end: "Fim",
738
833
  engine: "Motor",
739
834
  error: "Erro",
835
+ eventTime: "Hor\xE1rio do evento",
836
+ events: "Eventos do assistente e da captura",
837
+ eventsHelp: "Os marcadores mostram o limite do \xE1udio capturado e o hor\xE1rio real do evento. Eventos ap\xF3s o fim da captura podem compartilhar seu limite final; nenhum \xE1udio do assistente \xE9 adicionado \xE0 grava\xE7\xE3o.",
740
838
  export: "Exportar JSON completo",
741
839
  exportError: "N\xE3o foi poss\xEDvel exportar a grava\xE7\xE3o.",
742
840
  failed: "Falhou",
@@ -746,6 +844,8 @@ var init_pt_BR2 = __esm({
746
844
  loading: "Carregando grava\xE7\xF5es\u2026",
747
845
  memory: "Somente na mem\xF3ria",
748
846
  microphone: "Microfone",
847
+ name: "Nome da sess\xE3o",
848
+ nameError: "N\xE3o foi poss\xEDvel salvar o nome. Marque a sess\xE3o com estrela e use uma \xFAnica linha de at\xE9 120 caracteres.",
749
849
  noAttempts: "Nenhuma tentativa de transcri\xE7\xE3o ainda.",
750
850
  open: "Segmento aberto",
751
851
  pending: "Pendente",
@@ -756,7 +856,10 @@ var init_pt_BR2 = __esm({
756
856
  play: "Reproduzir segmento",
757
857
  playSession: "Reproduzir sess\xE3o salva",
758
858
  refresh: "Atualizar grava\xE7\xF5es",
859
+ saveName: "Salvar nome",
759
860
  saved: "\xC1udio salvo",
861
+ search: "Pesquisar transcri\xE7\xF5es dos segmentos",
862
+ searchEmpty: "Nenhum segmento transcrito corresponde \xE0 pesquisa.",
760
863
  segments: "Segmentos",
761
864
  selectSession: "Selecione uma sess\xE3o de grava\xE7\xE3o.",
762
865
  shared: "\xC1udio compartilhado",
@@ -770,12 +873,19 @@ var init_pt_BR2 = __esm({
770
873
  starred: "Protegida da limpeza autom\xE1tica",
771
874
  start: "In\xEDcio",
772
875
  state: "Estado",
876
+ storageAudio: "\xC1udio armazenado (MB)",
877
+ storageTotal: "Total de \xE1udio armazenado (MB)",
878
+ storageUnknown: "Indispon\xEDvel",
773
879
  success: "Sucesso",
774
880
  timeline: "Linha do tempo de fala / sil\xEAncio",
775
881
  title: "Grava\xE7\xF5es",
776
882
  unavailable: "Servi\xE7o de grava\xE7\xE3o indispon\xEDvel. Ative a grava\xE7\xE3o nas configura\xE7\xF5es da Voz ao Vivo com um runtime compat\xEDvel.",
777
883
  unstar: "Remover prote\xE7\xE3o",
778
- unstarHelp: "Permite a limpeza autom\xE1tica e inclui novamente esta grava\xE7\xE3o na contagem de reten\xE7\xE3o. A exclus\xE3o manual continua permitida. O armazenamento e a prote\xE7\xE3o contra remo\xE7\xE3o pelo navegador n\xE3o mudam."
884
+ unstarHelp: "Permite a limpeza autom\xE1tica e inclui novamente esta grava\xE7\xE3o na contagem de reten\xE7\xE3o. A exclus\xE3o manual continua permitida. O armazenamento e a prote\xE7\xE3o contra remo\xE7\xE3o pelo navegador n\xE3o mudam.",
885
+ window: "Recorte da linha do tempo",
886
+ windowEnd: "Fim do recorte",
887
+ windowReset: "Mostrar sess\xE3o inteira",
888
+ windowStart: "In\xEDcio do recorte"
779
889
  };
780
890
  pt_BR_default2 = Object.freeze(translation18);
781
891
  }
@@ -884,10 +994,17 @@ var init_zh2 = __esm({
884
994
  translation22 = {
885
995
  active: "\u6B63\u5728\u5F55\u5236",
886
996
  allSources: "\u6240\u6709\u6765\u6E90",
997
+ assistantEnd: "\u52A9\u624B\u64AD\u653E\u7ED3\u675F",
998
+ assistantPause: "\u52A9\u624B\u64AD\u653E\u6682\u505C",
999
+ assistantResume: "\u52A9\u624B\u64AD\u653E\u6062\u590D",
1000
+ assistantStart: "\u52A9\u624B\u5F00\u59CB\u64AD\u653E",
887
1001
  attempts: "\u8F6C\u5F55\u5386\u53F2",
888
1002
  audio: "\u5F55\u97F3\u64AD\u653E",
889
1003
  audioError: "\u65E0\u6CD5\u52A0\u8F7D\u6216\u64AD\u653E\u5F55\u97F3\u97F3\u9891\u3002",
890
1004
  cancel: "\u53D6\u6D88",
1005
+ captureEnd: "\u91C7\u96C6\u7ED3\u675F",
1006
+ captureGated: "\u5DF2\u8BF7\u6C42\u6682\u505C\u9EA6\u514B\u98CE\u4EE5\u901A\u8FC7\u626C\u58F0\u5668\u64AD\u653E",
1007
+ captureStart: "\u91C7\u96C6\u5F00\u59CB",
891
1008
  captured: "\u5DF2\u6355\u83B7\u97F3\u9891",
892
1009
  completed: "\u5DF2\u5B8C\u6210",
893
1010
  confirmDelete: "\u5220\u9664\u6574\u4E2A\u5F55\u97F3\uFF0C\u5305\u62EC\u97F3\u9891\u548C\u8F6C\u5F55\u5386\u53F2\uFF1F\u6B64\u64CD\u4F5C\u65E0\u6CD5\u64A4\u9500\u3002\u5220\u9664\u6B63\u5728\u5F55\u5236\u7684\u4F1A\u8BDD\u8FD8\u4F1A\u4E22\u5F03\u540E\u7EED\u4FDD\u5B58\u7684\u97F3\u9891\u3002",
@@ -899,6 +1016,9 @@ var init_zh2 = __esm({
899
1016
  end: "\u7ED3\u675F",
900
1017
  engine: "\u5F15\u64CE",
901
1018
  error: "\u9519\u8BEF",
1019
+ eventTime: "\u4E8B\u4EF6\u65F6\u95F4",
1020
+ events: "\u52A9\u624B\u4E0E\u91C7\u96C6\u4E8B\u4EF6",
1021
+ eventsHelp: "\u6807\u8BB0\u663E\u793A\u5DF2\u91C7\u96C6\u97F3\u9891\u7684\u8FB9\u754C\u548C\u4E8B\u4EF6\u5B9E\u9645\u65F6\u95F4\u3002\u91C7\u96C6\u505C\u6B62\u540E\u7684\u4E8B\u4EF6\u53EF\u80FD\u5171\u7528\u6700\u7EC8\u8FB9\u754C\uFF1B\u4E0D\u4F1A\u5C06\u52A9\u624B\u97F3\u9891\u6DFB\u52A0\u5230\u5F55\u97F3\u3002",
902
1022
  export: "\u5BFC\u51FA\u5B8C\u6574\u72EC\u7ACB JSON",
903
1023
  exportError: "\u65E0\u6CD5\u5BFC\u51FA\u5F55\u97F3\u3002",
904
1024
  failed: "\u5931\u8D25",
@@ -908,6 +1028,8 @@ var init_zh2 = __esm({
908
1028
  loading: "\u6B63\u5728\u52A0\u8F7D\u5F55\u97F3\u2026",
909
1029
  memory: "\u4EC5\u5728\u5185\u5B58\u4E2D",
910
1030
  microphone: "\u9EA6\u514B\u98CE",
1031
+ name: "\u4F1A\u8BDD\u540D\u79F0",
1032
+ nameError: "\u65E0\u6CD5\u4FDD\u5B58\u540D\u79F0\u3002\u8BF7\u5148\u52A0\u661F\u6807\uFF0C\u5E76\u4F7F\u7528\u4E0D\u8D85\u8FC7120\u4E2A\u5B57\u7B26\u7684\u5355\u884C\u540D\u79F0\u3002",
911
1033
  noAttempts: "\u5C1A\u65E0\u8F6C\u5F55\u5C1D\u8BD5\u3002",
912
1034
  open: "\u672A\u7ED3\u675F\u7247\u6BB5",
913
1035
  pending: "\u5904\u7406\u4E2D",
@@ -918,7 +1040,10 @@ var init_zh2 = __esm({
918
1040
  play: "\u64AD\u653E\u7247\u6BB5",
919
1041
  playSession: "\u64AD\u653E\u5DF2\u4FDD\u5B58\u4F1A\u8BDD",
920
1042
  refresh: "\u5237\u65B0\u5F55\u97F3",
1043
+ saveName: "\u4FDD\u5B58\u540D\u79F0",
921
1044
  saved: "\u5DF2\u4FDD\u5B58\u97F3\u9891",
1045
+ search: "\u641C\u7D22\u7247\u6BB5\u8F6C\u5F55",
1046
+ searchEmpty: "\u6CA1\u6709\u5339\u914D\u7684\u5DF2\u8F6C\u5F55\u7247\u6BB5\u3002",
922
1047
  segments: "\u7247\u6BB5",
923
1048
  selectSession: "\u8BF7\u9009\u62E9\u5F55\u97F3\u4F1A\u8BDD\u3002",
924
1049
  shared: "\u5171\u4EAB\u97F3\u9891",
@@ -932,12 +1057,19 @@ var init_zh2 = __esm({
932
1057
  starred: "\u53D7\u4FDD\u62A4\uFF0C\u4E0D\u4F1A\u81EA\u52A8\u6E05\u7406",
933
1058
  start: "\u5F00\u59CB",
934
1059
  state: "\u72B6\u6001",
1060
+ storageAudio: "\u5DF2\u5B58\u50A8\u97F3\u9891 (MB)",
1061
+ storageTotal: "\u5DF2\u5B58\u50A8\u97F3\u9891\u603B\u91CF (MB)",
1062
+ storageUnknown: "\u4E0D\u53EF\u7528",
935
1063
  success: "\u6210\u529F",
936
1064
  timeline: "\u8BED\u97F3 / \u9759\u97F3\u65F6\u95F4\u7EBF",
937
1065
  title: "\u5F55\u97F3",
938
1066
  unavailable: "\u5F55\u97F3\u670D\u52A1\u4E0D\u53EF\u7528\u3002\u8BF7\u5728\u517C\u5BB9\u7684\u5B9E\u65F6\u8BED\u97F3\u8BBE\u7F6E\u4E2D\u542F\u7528\u5F55\u97F3\u3002",
939
1067
  unstar: "\u53D6\u6D88\u4FDD\u62A4",
940
- unstarHelp: "\u5141\u8BB8\u81EA\u52A8\u6E05\u7406\uFF0C\u5E76\u5C06\u6B64\u5F55\u97F3\u91CD\u65B0\u8BA1\u5165\u4FDD\u7559\u6570\u91CF\u3002\u4ECD\u53EF\u624B\u52A8\u5220\u9664\u3002\u6D4F\u89C8\u5668\u5B58\u50A8\u548C\u9632\u9010\u51FA\u4FDD\u62A4\u4FDD\u6301\u4E0D\u53D8\u3002"
1068
+ unstarHelp: "\u5141\u8BB8\u81EA\u52A8\u6E05\u7406\uFF0C\u5E76\u5C06\u6B64\u5F55\u97F3\u91CD\u65B0\u8BA1\u5165\u4FDD\u7559\u6570\u91CF\u3002\u4ECD\u53EF\u624B\u52A8\u5220\u9664\u3002\u6D4F\u89C8\u5668\u5B58\u50A8\u548C\u9632\u9010\u51FA\u4FDD\u62A4\u4FDD\u6301\u4E0D\u53D8\u3002",
1069
+ window: "\u65F6\u95F4\u8F74\u8303\u56F4",
1070
+ windowEnd: "\u8303\u56F4\u7ED3\u675F",
1071
+ windowReset: "\u663E\u793A\u5B8C\u6574\u4F1A\u8BDD",
1072
+ windowStart: "\u8303\u56F4\u5F00\u59CB"
941
1073
  };
942
1074
  zh_default2 = Object.freeze(translation22);
943
1075
  }
@@ -1014,7 +1146,7 @@ __export(apply_exports, {
1014
1146
  inject: () => inject
1015
1147
  });
1016
1148
  module.exports = __toCommonJS(apply_exports);
1017
- var import_react27 = __toESM(require("react"), 1);
1149
+ var import_react28 = __toESM(require("react"), 1);
1018
1150
 
1019
1151
  // ../live-voice/src/shared/design-system/buttons/IconButton.tsx
1020
1152
  var import_react2 = __toESM(require("react"), 1);
@@ -1243,7 +1375,7 @@ var import_react20 = __toESM(require("react"), 1);
1243
1375
  var import_client = require("react-dom/client");
1244
1376
 
1245
1377
  // src/DebuggerPanel.tsx
1246
- var import_react24 = __toESM(require("react"), 1);
1378
+ var import_react25 = __toESM(require("react"), 1);
1247
1379
 
1248
1380
  // ../live-voice/src/modules/core/diagnostics.ts
1249
1381
  var DIAGNOSTIC_KEY = /* @__PURE__ */ Symbol.for("dsh-live-voice.diagnostics.v1");
@@ -1378,7 +1510,213 @@ function StateTree({
1378
1510
  }
1379
1511
 
1380
1512
  // src/RecordingPanel.tsx
1513
+ var import_react23 = __toESM(require("react"), 1);
1514
+
1515
+ // src/TimelineWindow.tsx
1381
1516
  var import_react22 = __toESM(require("react"), 1);
1517
+ function TimelineWindow({ total, start, end, copy, format, onChange, onReset }) {
1518
+ const track = import_react22.default.useRef(null);
1519
+ const drag = import_react22.default.useRef(null);
1520
+ const stopDrag = () => {
1521
+ const current = drag.current;
1522
+ drag.current = null;
1523
+ if (current?.element.hasPointerCapture(current.pointer))
1524
+ current.element.releasePointerCapture(current.pointer);
1525
+ };
1526
+ import_react22.default.useEffect(() => {
1527
+ if (total <= 0) stopDrag();
1528
+ }, [total]);
1529
+ import_react22.default.useEffect(() => stopDrag, []);
1530
+ const change = (part, delta, initialStart = start, initialEnd = end) => {
1531
+ if (total <= 0) return;
1532
+ if (part === "start")
1533
+ onChange(Math.max(0, Math.min(initialEnd - 1, initialStart + delta)), initialEnd);
1534
+ else if (part === "end")
1535
+ onChange(initialStart, Math.min(total, Math.max(initialStart + 1, initialEnd + delta)));
1536
+ else {
1537
+ const offset = Math.max(-initialStart, Math.min(total - initialEnd, delta));
1538
+ onChange(initialStart + offset, initialEnd + offset);
1539
+ }
1540
+ };
1541
+ const begin = (event, part) => {
1542
+ if (total <= 0 || event.button !== 0 || drag.current) return;
1543
+ const width = track.current?.getBoundingClientRect().width ?? 0;
1544
+ if (width <= 0) return;
1545
+ event.preventDefault();
1546
+ event.currentTarget.focus();
1547
+ event.currentTarget.setPointerCapture(event.pointerId);
1548
+ drag.current = {
1549
+ pointer: event.pointerId,
1550
+ x: event.clientX,
1551
+ width,
1552
+ total,
1553
+ start,
1554
+ end,
1555
+ part,
1556
+ element: event.currentTarget
1557
+ };
1558
+ };
1559
+ const move = (event) => {
1560
+ const current = drag.current;
1561
+ if (!current || current.pointer !== event.pointerId) return;
1562
+ change(
1563
+ current.part,
1564
+ Math.round((event.clientX - current.x) * current.total / current.width),
1565
+ current.start,
1566
+ current.end
1567
+ );
1568
+ };
1569
+ const finish = (event) => {
1570
+ if (drag.current?.pointer !== event.pointerId) return;
1571
+ stopDrag();
1572
+ };
1573
+ const keyboard = (event, part) => {
1574
+ const step = Math.max(1, Math.round(total / (event.shiftKey ? 10 : 100)));
1575
+ const amount = {
1576
+ ArrowLeft: -step,
1577
+ ArrowDown: -step,
1578
+ ArrowRight: step,
1579
+ ArrowUp: step,
1580
+ PageDown: -step * 10,
1581
+ PageUp: step * 10
1582
+ }[event.key];
1583
+ let delta = amount;
1584
+ if (event.key === "Home") delta = part === "end" ? start + 1 - end : -start;
1585
+ if (event.key === "End") delta = part === "start" ? end - 1 - start : total - end;
1586
+ if (delta === void 0) return;
1587
+ event.preventDefault();
1588
+ change(part, delta);
1589
+ };
1590
+ const handlers = (part) => ({
1591
+ onPointerDown: (event) => begin(event, part),
1592
+ onPointerMove: move,
1593
+ onPointerUp: (event) => {
1594
+ move(event);
1595
+ finish(event);
1596
+ },
1597
+ onPointerCancel: finish,
1598
+ onLostPointerCapture: () => {
1599
+ drag.current = null;
1600
+ },
1601
+ onKeyDown: (event) => keyboard(event, part)
1602
+ });
1603
+ const percent = (value) => total > 0 ? value / total * 100 : 0;
1604
+ return /* @__PURE__ */ import_react22.default.createElement("div", { className: "dlvd-timeline-window", role: "group", "aria-label": copy.window }, /* @__PURE__ */ import_react22.default.createElement("div", { className: "dlvd-window-selector" }, /* @__PURE__ */ import_react22.default.createElement("div", { className: "dlvd-window-values" }, /* @__PURE__ */ import_react22.default.createElement("span", null, copy.windowStart, ": ", format(start)), /* @__PURE__ */ import_react22.default.createElement("span", null, copy.windowEnd, ": ", format(end))), /* @__PURE__ */ import_react22.default.createElement("div", { className: "dlvd-window-track", ref: track }, /* @__PURE__ */ import_react22.default.createElement(
1605
+ "button",
1606
+ {
1607
+ type: "button",
1608
+ role: "slider",
1609
+ className: "dlvd-window-selection",
1610
+ "aria-label": copy.window,
1611
+ "aria-valuemin": 0,
1612
+ "aria-valuemax": Math.max(0, total - (end - start)),
1613
+ "aria-valuenow": start,
1614
+ "aria-valuetext": format(start) + " \u2013 " + format(end),
1615
+ "aria-orientation": "horizontal",
1616
+ disabled: total <= 0,
1617
+ style: { left: percent(start) + "%", width: percent(end - start) + "%" },
1618
+ ...handlers("range")
1619
+ }
1620
+ ), /* @__PURE__ */ import_react22.default.createElement(
1621
+ "button",
1622
+ {
1623
+ type: "button",
1624
+ role: "slider",
1625
+ className: "dlvd-window-handle",
1626
+ "data-edge": "start",
1627
+ "aria-label": copy.windowStart,
1628
+ "aria-valuemin": 0,
1629
+ "aria-valuemax": Math.max(0, end - 1),
1630
+ "aria-valuenow": start,
1631
+ "aria-valuetext": format(start),
1632
+ "aria-orientation": "horizontal",
1633
+ disabled: total <= 0,
1634
+ style: { left: percent(start) + "%" },
1635
+ ...handlers("start")
1636
+ }
1637
+ ), /* @__PURE__ */ import_react22.default.createElement(
1638
+ "button",
1639
+ {
1640
+ type: "button",
1641
+ role: "slider",
1642
+ className: "dlvd-window-handle",
1643
+ "data-edge": "end",
1644
+ "aria-label": copy.windowEnd,
1645
+ "aria-valuemin": Math.min(total, start + 1),
1646
+ "aria-valuemax": total,
1647
+ "aria-valuenow": end,
1648
+ "aria-valuetext": format(end),
1649
+ "aria-orientation": "horizontal",
1650
+ disabled: total <= 0,
1651
+ style: { left: percent(end) + "%" },
1652
+ ...handlers("end")
1653
+ }
1654
+ ))), /* @__PURE__ */ import_react22.default.createElement(
1655
+ "button",
1656
+ {
1657
+ type: "button",
1658
+ className: "dlvd-window-reset",
1659
+ title: copy.windowReset,
1660
+ "aria-label": copy.windowReset,
1661
+ onClick: onReset
1662
+ },
1663
+ /* @__PURE__ */ import_react22.default.createElement(
1664
+ "svg",
1665
+ {
1666
+ width: "18",
1667
+ height: "18",
1668
+ viewBox: "0 0 24 24",
1669
+ fill: "none",
1670
+ stroke: "currentColor",
1671
+ strokeWidth: "1.7",
1672
+ strokeLinecap: "round",
1673
+ strokeLinejoin: "round",
1674
+ "aria-hidden": "true",
1675
+ focusable: "false"
1676
+ },
1677
+ /* @__PURE__ */ import_react22.default.createElement("path", { d: "M8 3H3v5m13-5h5v5M3 16v5h5m13-5v5h-5M8 8l-5-5m13 5 5-5M8 16l-5 5m13-5 5 5" })
1678
+ )
1679
+ ));
1680
+ }
1681
+
1682
+ // src/segmentSearch.ts
1683
+ var normalize = (text) => text.normalize("NFKD").replace(/\p{M}/gu, "").toLowerCase().replace(/[^\p{L}\p{N}]+/gu, " ").trim();
1684
+ function distance(a, b) {
1685
+ let row = Array.from({ length: b.length + 1 }, (_, i) => i);
1686
+ for (let i = 0; i < a.length; i++) {
1687
+ const next = [i + 1];
1688
+ for (let j = 0; j < b.length; j++)
1689
+ next.push(Math.min(next[j] + 1, row[j + 1] + 1, row[j] + (a[i] === b[j] ? 0 : 1)));
1690
+ row = next;
1691
+ }
1692
+ return row[b.length];
1693
+ }
1694
+ function searchSegments(segments, query) {
1695
+ if (!query.trim()) return segments;
1696
+ const needle = normalize(query.slice(0, 160));
1697
+ if (!needle) return [];
1698
+ const words = needle.split(" ");
1699
+ return segments.map((segment, index) => {
1700
+ const transcripts = segment.attempts.filter((a) => a.status === "success" && a.text?.trim()).map((a) => normalize(a.text));
1701
+ let score = Infinity;
1702
+ for (const text of transcripts) {
1703
+ const tokens = text.split(" ");
1704
+ if (text === needle) score = Math.min(score, 0);
1705
+ else if (text.includes(needle)) score = Math.min(score, 1);
1706
+ else if (words.every((word) => tokens.includes(word))) score = Math.min(score, 2);
1707
+ else if (words.every((word) => tokens.some((token) => token.includes(word))))
1708
+ score = Math.min(score, 3);
1709
+ else if (words.every(
1710
+ (word) => tokens.some((token) => {
1711
+ const limit = word.length < 4 ? 0 : word.length < 8 ? 1 : 2;
1712
+ return Math.abs(token.length - word.length) <= limit && distance(word, token) <= limit;
1713
+ })
1714
+ ))
1715
+ score = Math.min(score, 4);
1716
+ }
1717
+ return { segment, index, score };
1718
+ }).filter((hit) => Number.isFinite(hit.score)).sort((a, b) => a.score - b.score || a.index - b.index).map((hit) => hit.segment);
1719
+ }
1382
1720
 
1383
1721
  // ../live-voice/src/modules/recording/types.ts
1384
1722
  var RECORDING_KEY = /* @__PURE__ */ Symbol.for("dsh-live-voice.recordings.v1");
@@ -1503,6 +1841,7 @@ function createRecordingInspector(target, changed) {
1503
1841
  }
1504
1842
 
1505
1843
  // src/RecordingPanel.tsx
1844
+ var megabytes = (bytes) => (bytes / 1e6).toFixed(3) + " MB";
1506
1845
  function duration(samples, rate) {
1507
1846
  const milliseconds = Math.max(0, Math.round(samples / Math.max(1, rate) * 1e3));
1508
1847
  const seconds = Math.floor(milliseconds / 1e3);
@@ -1519,7 +1858,7 @@ function stateName(session, copy) {
1519
1858
  }[session.state];
1520
1859
  }
1521
1860
  function RecordingPanel({ copy, target }) {
1522
- const [view, setView] = import_react22.default.useState({
1861
+ const [view, setView] = import_react23.default.useState({
1523
1862
  service: null,
1524
1863
  sessions: [],
1525
1864
  selected: null,
@@ -1527,9 +1866,9 @@ function RecordingPanel({ copy, target }) {
1527
1866
  loading: true,
1528
1867
  failed: false
1529
1868
  });
1530
- const inspector = import_react22.default.useRef(null);
1531
- const [filter, setFilter] = import_react22.default.useState("");
1532
- import_react22.default.useEffect(() => {
1869
+ const inspector = import_react23.default.useRef(null);
1870
+ const [filter, setFilter] = import_react23.default.useState("");
1871
+ import_react23.default.useEffect(() => {
1533
1872
  const current = createRecordingInspector(target, setView);
1534
1873
  inspector.current = current;
1535
1874
  current.discover();
@@ -1546,12 +1885,12 @@ function RecordingPanel({ copy, target }) {
1546
1885
  ...new Map(view.sessions.map((session) => [sourceKey(session), session])).values()
1547
1886
  ];
1548
1887
  const visible = view.sessions.filter((session) => !filter || sourceKey(session) === filter).slice().sort((a, b) => b.startedAt.localeCompare(a.startedAt));
1549
- import_react22.default.useEffect(() => {
1888
+ import_react23.default.useEffect(() => {
1550
1889
  if (!view.loading && filter && visible.length && !visible.some((s) => s.id === view.selected?.id))
1551
1890
  inspector.current?.select(visible[0].id);
1552
1891
  }, [filter, view.selected?.id, view.loading, visible[0]?.id]);
1553
1892
  const selected = view.selected && visible.some((s) => s.id === view.selected?.id) ? view.selected : null;
1554
- return /* @__PURE__ */ import_react22.default.createElement("section", { className: "dlvd-recordings", "aria-label": copy.recordings.title }, /* @__PURE__ */ import_react22.default.createElement("p", null, copy.recordings.help), /* @__PURE__ */ import_react22.default.createElement("div", { className: "dlvd-toolbar" }, /* @__PURE__ */ import_react22.default.createElement("label", null, copy.recordings.sourceFilter, " ", /* @__PURE__ */ import_react22.default.createElement("select", { value: filter, onChange: (event) => setFilter(event.target.value) }, /* @__PURE__ */ import_react22.default.createElement("option", { value: "" }, copy.recordings.allSources), sources.map((session) => /* @__PURE__ */ import_react22.default.createElement("option", { key: sourceKey(session), value: sourceKey(session) }, sourceName(session, copy))))), /* @__PURE__ */ import_react22.default.createElement(
1893
+ return /* @__PURE__ */ import_react23.default.createElement("section", { className: "dlvd-recordings", "aria-label": copy.recordings.title }, /* @__PURE__ */ import_react23.default.createElement("p", null, copy.recordings.help), /* @__PURE__ */ import_react23.default.createElement("div", { className: "dlvd-toolbar" }, /* @__PURE__ */ import_react23.default.createElement("label", null, copy.recordings.sourceFilter, " ", /* @__PURE__ */ import_react23.default.createElement("select", { value: filter, onChange: (event) => setFilter(event.target.value) }, /* @__PURE__ */ import_react23.default.createElement("option", { value: "" }, copy.recordings.allSources), sources.map((session) => /* @__PURE__ */ import_react23.default.createElement("option", { key: sourceKey(session), value: sourceKey(session) }, sourceName(session, copy))))), /* @__PURE__ */ import_react23.default.createElement(
1555
1894
  "button",
1556
1895
  {
1557
1896
  type: "button",
@@ -1561,22 +1900,22 @@ function RecordingPanel({ copy, target }) {
1561
1900
  }
1562
1901
  },
1563
1902
  copy.recordings.refresh
1564
- )), view.failed && /* @__PURE__ */ import_react22.default.createElement("p", { role: "alert" }, copy.recordings.loadError), !view.service ? /* @__PURE__ */ import_react22.default.createElement("p", { role: "status" }, copy.recordings.unavailable) : /* @__PURE__ */ import_react22.default.createElement(import_react22.default.Fragment, null, view.loading && /* @__PURE__ */ import_react22.default.createElement("p", { role: "status" }, copy.recordings.loading), /* @__PURE__ */ import_react22.default.createElement("div", { className: "dlvd-recording-columns" }, /* @__PURE__ */ import_react22.default.createElement(
1903
+ )), view.failed && /* @__PURE__ */ import_react23.default.createElement("p", { role: "alert" }, copy.recordings.loadError), !view.service ? /* @__PURE__ */ import_react23.default.createElement("p", { role: "status" }, copy.recordings.unavailable) : /* @__PURE__ */ import_react23.default.createElement(import_react23.default.Fragment, null, view.loading && /* @__PURE__ */ import_react23.default.createElement("p", { role: "status" }, copy.recordings.loading), /* @__PURE__ */ import_react23.default.createElement("p", { className: "dlvd-audio-total" }, copy.recordings.storageTotal, ":", " ", view.sessions.every((s) => s.audioBytes !== void 0) ? megabytes(view.sessions.reduce((sum, s) => sum + (s.audioBytes ?? 0), 0)) : copy.recordings.storageUnknown), /* @__PURE__ */ import_react23.default.createElement("div", { className: "dlvd-recording-columns" }, /* @__PURE__ */ import_react23.default.createElement(
1565
1904
  "div",
1566
1905
  {
1567
1906
  className: "dlvd-session-list dlvd-scroll",
1568
1907
  tabIndex: 0,
1569
1908
  "aria-label": copy.recordings.title
1570
1909
  },
1571
- !visible.length && !view.loading && /* @__PURE__ */ import_react22.default.createElement("p", null, copy.recordings.empty),
1572
- sources.filter((source) => !filter || sourceKey(source) === filter).map((source) => /* @__PURE__ */ import_react22.default.createElement("section", { key: sourceKey(source), "aria-label": sourceName(source, copy) }, /* @__PURE__ */ import_react22.default.createElement("h3", null, sourceName(source, copy)), /* @__PURE__ */ import_react22.default.createElement("table", null, /* @__PURE__ */ import_react22.default.createElement("thead", null, /* @__PURE__ */ import_react22.default.createElement("tr", null, /* @__PURE__ */ import_react22.default.createElement("th", { scope: "col" }, copy.recordings.date), /* @__PURE__ */ import_react22.default.createElement("th", { scope: "col" }, copy.recordings.state), /* @__PURE__ */ import_react22.default.createElement("th", { scope: "col" }, copy.recordings.duration), /* @__PURE__ */ import_react22.default.createElement("th", { scope: "col" }, copy.recordings.saved))), /* @__PURE__ */ import_react22.default.createElement("tbody", null, visible.filter((session) => sourceKey(session) === sourceKey(source)).map((session) => /* @__PURE__ */ import_react22.default.createElement("tr", { key: session.id, "data-selected": session.id === selected?.id }, /* @__PURE__ */ import_react22.default.createElement("td", null, /* @__PURE__ */ import_react22.default.createElement(
1910
+ !visible.length && !view.loading && /* @__PURE__ */ import_react23.default.createElement("p", null, copy.recordings.empty),
1911
+ sources.filter((source) => !filter || sourceKey(source) === filter).map((source) => /* @__PURE__ */ import_react23.default.createElement("section", { key: sourceKey(source), "aria-label": sourceName(source, copy) }, /* @__PURE__ */ import_react23.default.createElement("h3", null, sourceName(source, copy)), /* @__PURE__ */ import_react23.default.createElement("table", null, /* @__PURE__ */ import_react23.default.createElement("thead", null, /* @__PURE__ */ import_react23.default.createElement("tr", null, /* @__PURE__ */ import_react23.default.createElement("th", { scope: "col" }, copy.recordings.date), /* @__PURE__ */ import_react23.default.createElement("th", { scope: "col" }, copy.recordings.state), /* @__PURE__ */ import_react23.default.createElement("th", { scope: "col" }, copy.recordings.duration), /* @__PURE__ */ import_react23.default.createElement("th", { scope: "col" }, copy.recordings.saved))), /* @__PURE__ */ import_react23.default.createElement("tbody", null, visible.filter((session) => sourceKey(session) === sourceKey(source)).map((session) => /* @__PURE__ */ import_react23.default.createElement("tr", { key: session.id, "data-selected": session.id === selected?.id }, /* @__PURE__ */ import_react23.default.createElement("td", null, /* @__PURE__ */ import_react23.default.createElement(
1573
1912
  "button",
1574
1913
  {
1575
1914
  type: "button",
1576
1915
  "aria-pressed": session.id === selected?.id,
1577
1916
  onClick: () => inspector.current?.select(session.id)
1578
1917
  },
1579
- session.starred && /* @__PURE__ */ import_react22.default.createElement(
1918
+ session.starred && /* @__PURE__ */ import_react23.default.createElement(
1580
1919
  "span",
1581
1920
  {
1582
1921
  role: "img",
@@ -1586,9 +1925,10 @@ function RecordingPanel({ copy, target }) {
1586
1925
  "\u2605"
1587
1926
  ),
1588
1927
  " ",
1589
- /* @__PURE__ */ import_react22.default.createElement("time", { dateTime: session.startedAt }, new Date(session.startedAt).toLocaleString())
1590
- )), /* @__PURE__ */ import_react22.default.createElement("td", null, stateName(session, copy)), /* @__PURE__ */ import_react22.default.createElement("td", null, duration(session.capturedSamples, session.sampleRate)), /* @__PURE__ */ import_react22.default.createElement("td", null, duration(session.savedSamples, session.sampleRate), /* @__PURE__ */ import_react22.default.createElement("br", null), session.storage === "indexeddb" || session.persistent ? copy.recordings.persistent : copy.recordings.memory)))))))
1591
- ), /* @__PURE__ */ import_react22.default.createElement("div", { className: "dlvd-recording-detail dlvd-scroll", tabIndex: 0 }, selected ? /* @__PURE__ */ import_react22.default.createElement(
1928
+ session.name && /* @__PURE__ */ import_react23.default.createElement("strong", null, session.name, /* @__PURE__ */ import_react23.default.createElement("br", null)),
1929
+ /* @__PURE__ */ import_react23.default.createElement("time", { dateTime: session.startedAt }, new Date(session.startedAt).toLocaleString())
1930
+ )), /* @__PURE__ */ import_react23.default.createElement("td", null, stateName(session, copy)), /* @__PURE__ */ import_react23.default.createElement("td", null, duration(session.capturedSamples, session.sampleRate)), /* @__PURE__ */ import_react23.default.createElement("td", null, duration(session.savedSamples, session.sampleRate), /* @__PURE__ */ import_react23.default.createElement("br", null), session.storage === "indexeddb" || session.persistent ? copy.recordings.persistent : copy.recordings.memory)))))))
1931
+ ), /* @__PURE__ */ import_react23.default.createElement("div", { className: "dlvd-recording-detail dlvd-scroll", tabIndex: 0 }, selected ? /* @__PURE__ */ import_react23.default.createElement(
1592
1932
  RecordingDetail,
1593
1933
  {
1594
1934
  key: selected.id,
@@ -1598,7 +1938,7 @@ function RecordingPanel({ copy, target }) {
1598
1938
  segments: view.segments,
1599
1939
  refresh: () => inspector.current?.refresh()
1600
1940
  }
1601
- ) : /* @__PURE__ */ import_react22.default.createElement("p", null, copy.recordings.selectSession)))));
1941
+ ) : /* @__PURE__ */ import_react23.default.createElement("p", null, copy.recordings.selectSession)))));
1602
1942
  }
1603
1943
  function RecordingDetail({
1604
1944
  copy,
@@ -1607,19 +1947,24 @@ function RecordingDetail({
1607
1947
  segments,
1608
1948
  refresh
1609
1949
  }) {
1610
- const container = import_react22.default.useRef(null);
1611
- const audio = import_react22.default.useRef(null);
1612
- const playback = import_react22.default.useRef(null);
1613
- const download = import_react22.default.useRef(null);
1614
- const generation = import_react22.default.useRef(0);
1615
- const playGeneration = import_react22.default.useRef(0);
1616
- const [error, setError] = import_react22.default.useState(null);
1617
- const [playing, setPlaying] = import_react22.default.useState(false);
1618
- const [exporting, setExporting] = import_react22.default.useState(false);
1619
- const [deleting, setDeleting] = import_react22.default.useState(false);
1620
- const [starring, setStarring] = import_react22.default.useState(false);
1621
- const [confirmDelete, setConfirmDelete] = import_react22.default.useState(false);
1622
- const [selectedSegment, setSelectedSegment] = import_react22.default.useState("");
1950
+ const container = import_react23.default.useRef(null);
1951
+ const audio = import_react23.default.useRef(null);
1952
+ const playback = import_react23.default.useRef(null);
1953
+ const download = import_react23.default.useRef(null);
1954
+ const generation = import_react23.default.useRef(0);
1955
+ const playGeneration = import_react23.default.useRef(0);
1956
+ const [error, setError] = import_react23.default.useState(null);
1957
+ const [playing, setPlaying] = import_react23.default.useState(false);
1958
+ const [exporting, setExporting] = import_react23.default.useState(false);
1959
+ const [deleting, setDeleting] = import_react23.default.useState(false);
1960
+ const [starring, setStarring] = import_react23.default.useState(false);
1961
+ const [confirmDelete, setConfirmDelete] = import_react23.default.useState(false);
1962
+ const [name, setName] = import_react23.default.useState(session.name ?? "");
1963
+ const [naming, setNaming] = import_react23.default.useState(false);
1964
+ import_react23.default.useEffect(() => {
1965
+ setName(session.name ?? "");
1966
+ }, [session.id, session.name, service]);
1967
+ const [selectedSegment, setSelectedSegment] = import_react23.default.useState("");
1623
1968
  const clearPlayback = (player = audio.current) => {
1624
1969
  ++playGeneration.current;
1625
1970
  if (player?.hasAttribute("src")) {
@@ -1634,7 +1979,7 @@ function RecordingDetail({
1634
1979
  if (download.current) download.current.api.revokeObjectURL(download.current.url);
1635
1980
  download.current = null;
1636
1981
  };
1637
- import_react22.default.useEffect(() => {
1982
+ import_react23.default.useEffect(() => {
1638
1983
  setStarring(false);
1639
1984
  const owner = container.current?.ownerDocument.defaultView;
1640
1985
  const player = audio.current;
@@ -1720,6 +2065,29 @@ function RecordingDetail({
1720
2065
  if (token === generation.current) setStarring(false);
1721
2066
  }
1722
2067
  };
2068
+ const saveName = async () => {
2069
+ if (!service.setName) return;
2070
+ const token = generation.current;
2071
+ setNaming(true);
2072
+ setError(null);
2073
+ try {
2074
+ await service.setName(session.id, name);
2075
+ if (token === generation.current) refresh();
2076
+ } catch {
2077
+ if (token === generation.current) setError("nameError");
2078
+ } finally {
2079
+ if (token === generation.current) setNaming(false);
2080
+ }
2081
+ };
2082
+ const eventName = (kind) => ({
2083
+ "assistant-start": copy.recordings.assistantStart,
2084
+ "assistant-end": copy.recordings.assistantEnd,
2085
+ "assistant-pause": copy.recordings.assistantPause,
2086
+ "assistant-resume": copy.recordings.assistantResume,
2087
+ "capture-gated": copy.recordings.captureGated,
2088
+ "capture-start": copy.recordings.captureStart,
2089
+ "capture-end": copy.recordings.captureEnd
2090
+ })[kind] ?? kind;
1723
2091
  const removeSession = async () => {
1724
2092
  const token = ++generation.current;
1725
2093
  setExporting(false);
@@ -1740,20 +2108,60 @@ function RecordingDetail({
1740
2108
  if (token === generation.current) setDeleting(false);
1741
2109
  }
1742
2110
  };
2111
+ const [search, setSearch] = import_react23.default.useState("");
2112
+ import_react23.default.useEffect(() => setSearch(""), [session.id, service]);
2113
+ const matchedSegments = import_react23.default.useMemo(() => searchSegments(segments, search), [segments, search]);
1743
2114
  const length = Math.max(1, session.savedSamples);
2115
+ const [windowStart, setWindowStart] = import_react23.default.useState(0);
2116
+ const [windowEnd, setWindowEnd] = import_react23.default.useState(null);
2117
+ import_react23.default.useEffect(() => {
2118
+ setWindowStart(0);
2119
+ setWindowEnd(null);
2120
+ }, [session.id, service]);
2121
+ const viewEnd = Math.max(1, Math.min(length, windowEnd ?? length));
2122
+ const viewStart = Math.max(0, Math.min(windowStart, viewEnd - 1));
2123
+ const viewLength = viewEnd - viewStart;
2124
+ const inWindow = (sample) => sample >= viewStart && sample <= viewEnd;
2125
+ const position = (sample) => (sample - viewStart) / viewLength * 100 + "%";
1744
2126
  const segmentName = (segment) => (segment.kind === "speech" ? copy.recordings.speech : copy.recordings.silence) + " \xB7 " + duration(segment.startSample, session.sampleRate) + " \u2014 " + duration(segment.endSample, session.sampleRate);
1745
- return /* @__PURE__ */ import_react22.default.createElement("section", { ref: container, "aria-label": sourceName(session, copy) }, /* @__PURE__ */ import_react22.default.createElement("h3", null, sourceName(session, copy)), /* @__PURE__ */ import_react22.default.createElement("dl", { className: "dlvd-recording-meta" }, /* @__PURE__ */ import_react22.default.createElement("dt", null, copy.recordings.date), /* @__PURE__ */ import_react22.default.createElement("dd", null, new Date(session.startedAt).toLocaleString()), /* @__PURE__ */ import_react22.default.createElement("dt", null, copy.recordings.state), /* @__PURE__ */ import_react22.default.createElement("dd", null, stateName(session, copy)), /* @__PURE__ */ import_react22.default.createElement("dt", null, copy.recordings.captured), /* @__PURE__ */ import_react22.default.createElement("dd", null, duration(session.capturedSamples, session.sampleRate)), /* @__PURE__ */ import_react22.default.createElement("dt", null, copy.recordings.saved), /* @__PURE__ */ import_react22.default.createElement("dd", null, duration(session.savedSamples, session.sampleRate), " \xB7", session.storage === "indexeddb" || session.persistent ? copy.recordings.persistent : copy.recordings.memory), session.endedAt && /* @__PURE__ */ import_react22.default.createElement(import_react22.default.Fragment, null, /* @__PURE__ */ import_react22.default.createElement("dt", null, copy.recordings.end), /* @__PURE__ */ import_react22.default.createElement("dd", null, new Date(session.endedAt).toLocaleString()))), session.error && /* @__PURE__ */ import_react22.default.createElement("p", { role: "alert" }, copy.recordings.error, ": ", session.error), /* @__PURE__ */ import_react22.default.createElement("div", { className: "dlvd-toolbar" }, /* @__PURE__ */ import_react22.default.createElement(
2127
+ return /* @__PURE__ */ import_react23.default.createElement("section", { ref: container, "aria-label": sourceName(session, copy) }, /* @__PURE__ */ import_react23.default.createElement("h3", null, session.name || sourceName(session, copy)), session.starred && service.setName && /* @__PURE__ */ import_react23.default.createElement(
2128
+ "form",
2129
+ {
2130
+ className: "dlvd-toolbar",
2131
+ onSubmit: (event) => {
2132
+ event.preventDefault();
2133
+ void saveName();
2134
+ }
2135
+ },
2136
+ /* @__PURE__ */ import_react23.default.createElement("label", null, copy.recordings.name, " ", /* @__PURE__ */ import_react23.default.createElement(
2137
+ "input",
2138
+ {
2139
+ value: name,
2140
+ maxLength: 120,
2141
+ disabled: naming || deleting,
2142
+ onInput: (event) => setName(event.currentTarget.value)
2143
+ }
2144
+ )),
2145
+ /* @__PURE__ */ import_react23.default.createElement(
2146
+ "button",
2147
+ {
2148
+ type: "submit",
2149
+ disabled: naming || deleting || starring || name === (session.name ?? "")
2150
+ },
2151
+ copy.recordings.saveName
2152
+ )
2153
+ ), /* @__PURE__ */ import_react23.default.createElement("dl", { className: "dlvd-recording-meta" }, /* @__PURE__ */ import_react23.default.createElement("dt", null, copy.recordings.date), /* @__PURE__ */ import_react23.default.createElement("dd", null, new Date(session.startedAt).toLocaleString()), /* @__PURE__ */ import_react23.default.createElement("dt", null, copy.recordings.state), /* @__PURE__ */ import_react23.default.createElement("dd", null, stateName(session, copy)), /* @__PURE__ */ import_react23.default.createElement("dt", null, copy.recordings.storageAudio), /* @__PURE__ */ import_react23.default.createElement("dd", null, session.audioBytes === void 0 ? copy.recordings.storageUnknown : megabytes(session.audioBytes)), /* @__PURE__ */ import_react23.default.createElement("dt", null, copy.recordings.captured), /* @__PURE__ */ import_react23.default.createElement("dd", null, duration(session.capturedSamples, session.sampleRate)), /* @__PURE__ */ import_react23.default.createElement("dt", null, copy.recordings.saved), /* @__PURE__ */ import_react23.default.createElement("dd", null, duration(session.savedSamples, session.sampleRate), " \xB7", session.storage === "indexeddb" || session.persistent ? copy.recordings.persistent : copy.recordings.memory), session.endedAt && /* @__PURE__ */ import_react23.default.createElement(import_react23.default.Fragment, null, /* @__PURE__ */ import_react23.default.createElement("dt", null, copy.recordings.end), /* @__PURE__ */ import_react23.default.createElement("dd", null, new Date(session.endedAt).toLocaleString()))), session.error && /* @__PURE__ */ import_react23.default.createElement("p", { role: "alert" }, copy.recordings.error, ": ", session.error), /* @__PURE__ */ import_react23.default.createElement("div", { className: "dlvd-toolbar" }, /* @__PURE__ */ import_react23.default.createElement(
1746
2154
  "button",
1747
2155
  {
1748
2156
  type: "button",
1749
2157
  "aria-label": session.starred ? copy.recordings.unstar : copy.recordings.star,
1750
2158
  "aria-pressed": !!session.starred,
1751
2159
  title: session.starred ? copy.recordings.unstarHelp : copy.recordings.starHelp,
1752
- disabled: starring || deleting,
2160
+ disabled: starring || deleting || naming,
1753
2161
  onClick: () => void toggleStarred()
1754
2162
  },
1755
2163
  session.starred ? "\u2605" : "\u2606"
1756
- ), /* @__PURE__ */ import_react22.default.createElement(
2164
+ ), /* @__PURE__ */ import_react23.default.createElement(
1757
2165
  "button",
1758
2166
  {
1759
2167
  type: "button",
@@ -1761,34 +2169,34 @@ function RecordingDetail({
1761
2169
  onClick: () => void play()
1762
2170
  },
1763
2171
  copy.recordings.playSession
1764
- ), /* @__PURE__ */ import_react22.default.createElement("button", { type: "button", disabled: exporting || deleting, onClick: () => void exportSession() }, copy.recordings.export), /* @__PURE__ */ import_react22.default.createElement(
2172
+ ), /* @__PURE__ */ import_react23.default.createElement("button", { type: "button", disabled: exporting || deleting, onClick: () => void exportSession() }, copy.recordings.export), /* @__PURE__ */ import_react23.default.createElement(
1765
2173
  "button",
1766
2174
  {
1767
2175
  type: "button",
1768
- disabled: deleting || starring,
2176
+ disabled: deleting || starring || naming,
1769
2177
  onClick: () => setConfirmDelete(true)
1770
2178
  },
1771
2179
  copy.recordings.delete
1772
- )), confirmDelete && /* @__PURE__ */ import_react22.default.createElement(
2180
+ )), confirmDelete && /* @__PURE__ */ import_react23.default.createElement(
1773
2181
  "div",
1774
2182
  {
1775
2183
  className: "dlvd-delete-confirm",
1776
2184
  role: "group",
1777
2185
  "aria-label": copy.recordings.confirmDelete
1778
2186
  },
1779
- /* @__PURE__ */ import_react22.default.createElement("p", null, copy.recordings.confirmDelete),
1780
- /* @__PURE__ */ import_react22.default.createElement(
2187
+ /* @__PURE__ */ import_react23.default.createElement("p", null, copy.recordings.confirmDelete),
2188
+ /* @__PURE__ */ import_react23.default.createElement(
1781
2189
  "button",
1782
2190
  {
1783
2191
  type: "button",
1784
- disabled: deleting || starring,
2192
+ disabled: deleting || starring || naming,
1785
2193
  onClick: () => void removeSession()
1786
2194
  },
1787
2195
  copy.recordings.delete
1788
2196
  ),
1789
2197
  " ",
1790
- /* @__PURE__ */ import_react22.default.createElement("button", { type: "button", disabled: deleting, onClick: () => setConfirmDelete(false) }, copy.recordings.cancel)
1791
- ), error && /* @__PURE__ */ import_react22.default.createElement("p", { role: "alert" }, copy.recordings[error]), /* @__PURE__ */ import_react22.default.createElement(
2198
+ /* @__PURE__ */ import_react23.default.createElement("button", { type: "button", disabled: deleting, onClick: () => setConfirmDelete(false) }, copy.recordings.cancel)
2199
+ ), error && /* @__PURE__ */ import_react23.default.createElement("p", { role: "alert" }, copy.recordings[error]), /* @__PURE__ */ import_react23.default.createElement(
1792
2200
  "audio",
1793
2201
  {
1794
2202
  ref: audio,
@@ -1800,7 +2208,25 @@ function RecordingDetail({
1800
2208
  setError("audioError");
1801
2209
  }
1802
2210
  }
1803
- ), /* @__PURE__ */ import_react22.default.createElement("h4", null, copy.recordings.timeline), /* @__PURE__ */ import_react22.default.createElement("div", { className: "dlvd-timeline", role: "group", "aria-label": copy.recordings.timeline }, segments.map((segment) => /* @__PURE__ */ import_react22.default.createElement(
2211
+ ), /* @__PURE__ */ import_react23.default.createElement("h4", null, copy.recordings.timeline), /* @__PURE__ */ import_react23.default.createElement(
2212
+ TimelineWindow,
2213
+ {
2214
+ key: session.id,
2215
+ total: session.savedSamples,
2216
+ start: viewStart,
2217
+ end: Math.min(viewEnd, session.savedSamples),
2218
+ copy: copy.recordings,
2219
+ format: (sample) => duration(sample, session.sampleRate),
2220
+ onChange: (start, end) => {
2221
+ setWindowStart(start);
2222
+ setWindowEnd(end >= length ? null : end);
2223
+ },
2224
+ onReset: () => {
2225
+ setWindowStart(0);
2226
+ setWindowEnd(null);
2227
+ }
2228
+ }
2229
+ ), /* @__PURE__ */ import_react23.default.createElement("div", { className: "dlvd-timeline", role: "group", "aria-label": copy.recordings.timeline }, segments.filter((segment) => segment.endSample > viewStart && segment.startSample < viewEnd).map((segment) => /* @__PURE__ */ import_react23.default.createElement(
1804
2230
  "button",
1805
2231
  {
1806
2232
  key: segment.id,
@@ -1810,8 +2236,8 @@ function RecordingDetail({
1810
2236
  title: segmentName(segment),
1811
2237
  "aria-pressed": selectedSegment === segment.id,
1812
2238
  style: {
1813
- left: segment.startSample / length * 100 + "%",
1814
- width: Math.max(0, segment.endSample - segment.startSample) / length * 100 + "%"
2239
+ left: position(Math.max(viewStart, segment.startSample)),
2240
+ width: (Math.min(viewEnd, segment.endSample) - Math.max(viewStart, segment.startSample)) / viewLength * 100 + "%"
1815
2241
  },
1816
2242
  onClick: () => {
1817
2243
  clearPlayback();
@@ -1819,16 +2245,39 @@ function RecordingDetail({
1819
2245
  setSelectedSegment(segment.id);
1820
2246
  }
1821
2247
  }
1822
- )), session.pins.map((pin) => /* @__PURE__ */ import_react22.default.createElement(
2248
+ )), (session.events ?? []).filter((event) => inWindow(event.atSample)).map((event, index) => /* @__PURE__ */ import_react23.default.createElement(
2249
+ "span",
2250
+ {
2251
+ key: event.id,
2252
+ className: "dlvd-event-pin",
2253
+ "data-event": event.kind,
2254
+ style: {
2255
+ left: position(event.atSample),
2256
+ top: index % 3 * 12
2257
+ },
2258
+ title: eventName(event.kind) + " \xB7 " + new Date(event.occurredAt).toLocaleString(),
2259
+ "aria-hidden": "true"
2260
+ },
2261
+ "\u25C6"
2262
+ )), session.pins.filter((pin) => inWindow(pin.atSample)).map((pin) => /* @__PURE__ */ import_react23.default.createElement(
1823
2263
  "span",
1824
2264
  {
1825
2265
  key: pin.id,
1826
2266
  className: "dlvd-pin",
1827
2267
  "aria-hidden": "true",
1828
- style: { left: Math.min(length, pin.atSample) / length * 100 + "%" },
2268
+ style: { left: position(pin.atSample) },
1829
2269
  title: (pin.kind === "speech-start" ? copy.recordings.speech : copy.recordings.silence) + " \xB7 " + duration(pin.atSample, session.sampleRate)
1830
2270
  }
1831
- ))), /* @__PURE__ */ import_react22.default.createElement("div", { className: "dlvd-timeline-legend" }, /* @__PURE__ */ import_react22.default.createElement("span", { "data-kind": "speech" }, copy.recordings.speech), " \xB7 ", /* @__PURE__ */ import_react22.default.createElement("span", { "data-kind": "silence" }, copy.recordings.silence), " \xB7 ", duration(session.savedSamples, session.sampleRate)), /* @__PURE__ */ import_react22.default.createElement("h4", null, copy.recordings.segments), /* @__PURE__ */ import_react22.default.createElement("table", { className: "dlvd-segments" }, /* @__PURE__ */ import_react22.default.createElement("thead", null, /* @__PURE__ */ import_react22.default.createElement("tr", null, /* @__PURE__ */ import_react22.default.createElement("th", { scope: "col" }, copy.recordings.state), /* @__PURE__ */ import_react22.default.createElement("th", { scope: "col" }, copy.recordings.start), /* @__PURE__ */ import_react22.default.createElement("th", { scope: "col" }, copy.recordings.end), /* @__PURE__ */ import_react22.default.createElement("th", { scope: "col" }, copy.recordings.duration), /* @__PURE__ */ import_react22.default.createElement("th", { scope: "col" }, copy.recordings.audio))), /* @__PURE__ */ import_react22.default.createElement("tbody", null, segments.map((segment) => /* @__PURE__ */ import_react22.default.createElement(import_react22.default.Fragment, { key: segment.id }, /* @__PURE__ */ import_react22.default.createElement("tr", { "data-selected": selectedSegment === segment.id }, /* @__PURE__ */ import_react22.default.createElement("td", null, segment.kind === "speech" ? copy.recordings.speech : copy.recordings.silence, segment.open && /* @__PURE__ */ import_react22.default.createElement("small", null, copy.recordings.open)), /* @__PURE__ */ import_react22.default.createElement("td", null, duration(segment.startSample, session.sampleRate)), /* @__PURE__ */ import_react22.default.createElement("td", null, duration(segment.endSample, session.sampleRate)), /* @__PURE__ */ import_react22.default.createElement("td", null, duration(segment.endSample - segment.startSample, session.sampleRate)), /* @__PURE__ */ import_react22.default.createElement("td", null, /* @__PURE__ */ import_react22.default.createElement(
2271
+ ))), /* @__PURE__ */ import_react23.default.createElement("div", { className: "dlvd-timeline-legend" }, /* @__PURE__ */ import_react23.default.createElement("span", { "data-kind": "speech" }, copy.recordings.speech), " \xB7 ", /* @__PURE__ */ import_react23.default.createElement("span", { "data-kind": "silence" }, copy.recordings.silence), " \xB7 ", duration(viewStart, session.sampleRate), " \u2013", " ", duration(Math.min(viewEnd, session.savedSamples), session.sampleRate)), /* @__PURE__ */ import_react23.default.createElement("h4", null, copy.recordings.events), /* @__PURE__ */ import_react23.default.createElement("p", null, copy.recordings.eventsHelp), /* @__PURE__ */ import_react23.default.createElement("table", { className: "dlvd-recording-events" }, /* @__PURE__ */ import_react23.default.createElement("thead", null, /* @__PURE__ */ import_react23.default.createElement("tr", null, /* @__PURE__ */ import_react23.default.createElement("th", { scope: "col" }, copy.recordings.state), /* @__PURE__ */ import_react23.default.createElement("th", { scope: "col" }, copy.recordings.eventTime), /* @__PURE__ */ import_react23.default.createElement("th", { scope: "col" }, copy.recordings.captured))), /* @__PURE__ */ import_react23.default.createElement("tbody", null, (session.events ?? []).map((event) => /* @__PURE__ */ import_react23.default.createElement("tr", { key: event.id }, /* @__PURE__ */ import_react23.default.createElement("td", null, eventName(event.kind)), /* @__PURE__ */ import_react23.default.createElement("td", null, /* @__PURE__ */ import_react23.default.createElement("time", { dateTime: event.occurredAt }, new Date(event.occurredAt).toLocaleString(), ".", new Date(event.occurredAt).getMilliseconds().toString().padStart(3, "0"))), /* @__PURE__ */ import_react23.default.createElement("td", null, duration(event.atSample, session.sampleRate)))))), /* @__PURE__ */ import_react23.default.createElement("h4", null, copy.recordings.segments), /* @__PURE__ */ import_react23.default.createElement("label", null, copy.recordings.search, /* @__PURE__ */ import_react23.default.createElement(
2272
+ "input",
2273
+ {
2274
+ type: "search",
2275
+ value: search,
2276
+ maxLength: 160,
2277
+ "aria-label": copy.recordings.search,
2278
+ onInput: (event) => setSearch(event.currentTarget.value)
2279
+ }
2280
+ )), search.trim() && matchedSegments.length === 0 && /* @__PURE__ */ import_react23.default.createElement("p", { role: "status" }, copy.recordings.searchEmpty), /* @__PURE__ */ import_react23.default.createElement("table", { className: "dlvd-segments" }, /* @__PURE__ */ import_react23.default.createElement("thead", null, /* @__PURE__ */ import_react23.default.createElement("tr", null, /* @__PURE__ */ import_react23.default.createElement("th", { scope: "col" }, copy.recordings.state), /* @__PURE__ */ import_react23.default.createElement("th", { scope: "col" }, copy.recordings.start), /* @__PURE__ */ import_react23.default.createElement("th", { scope: "col" }, copy.recordings.end), /* @__PURE__ */ import_react23.default.createElement("th", { scope: "col" }, copy.recordings.duration), /* @__PURE__ */ import_react23.default.createElement("th", { scope: "col" }, copy.recordings.audio))), /* @__PURE__ */ import_react23.default.createElement("tbody", null, matchedSegments.map((segment) => /* @__PURE__ */ import_react23.default.createElement(import_react23.default.Fragment, { key: segment.id }, /* @__PURE__ */ import_react23.default.createElement("tr", { "data-selected": selectedSegment === segment.id }, /* @__PURE__ */ import_react23.default.createElement("td", null, segment.kind === "speech" ? copy.recordings.speech : copy.recordings.silence, segment.open && /* @__PURE__ */ import_react23.default.createElement("small", null, copy.recordings.open)), /* @__PURE__ */ import_react23.default.createElement("td", null, duration(segment.startSample, session.sampleRate)), /* @__PURE__ */ import_react23.default.createElement("td", null, duration(segment.endSample, session.sampleRate)), /* @__PURE__ */ import_react23.default.createElement("td", null, duration(segment.endSample - segment.startSample, session.sampleRate)), /* @__PURE__ */ import_react23.default.createElement("td", null, /* @__PURE__ */ import_react23.default.createElement(
1832
2281
  "button",
1833
2282
  {
1834
2283
  type: "button",
@@ -1837,15 +2286,15 @@ function RecordingDetail({
1837
2286
  onClick: () => void play(segment)
1838
2287
  },
1839
2288
  copy.recordings.play
1840
- ))), segment.kind === "speech" && /* @__PURE__ */ import_react22.default.createElement("tr", null, /* @__PURE__ */ import_react22.default.createElement("td", { colSpan: 5 }, /* @__PURE__ */ import_react22.default.createElement("details", { open: selectedSegment === segment.id || void 0 }, /* @__PURE__ */ import_react22.default.createElement("summary", null, copy.recordings.attempts, " \xB7 ", segment.attempts.length), !segment.attempts.length && /* @__PURE__ */ import_react22.default.createElement("p", null, copy.recordings.noAttempts), segment.attempts.map((attempt) => /* @__PURE__ */ import_react22.default.createElement("article", { className: "dlvd-attempt", key: attempt.id }, /* @__PURE__ */ import_react22.default.createElement("div", null, copy.recordings.engine, ": ", attempt.engine, " \xB7", {
2289
+ ))), segment.kind === "speech" && /* @__PURE__ */ import_react23.default.createElement("tr", null, /* @__PURE__ */ import_react23.default.createElement("td", { colSpan: 5 }, /* @__PURE__ */ import_react23.default.createElement("details", { open: !!search.trim() || selectedSegment === segment.id || void 0 }, /* @__PURE__ */ import_react23.default.createElement("summary", null, copy.recordings.attempts, " \xB7 ", segment.attempts.length), !segment.attempts.length && /* @__PURE__ */ import_react23.default.createElement("p", null, copy.recordings.noAttempts), segment.attempts.map((attempt) => /* @__PURE__ */ import_react23.default.createElement("article", { className: "dlvd-attempt", key: attempt.id }, /* @__PURE__ */ import_react23.default.createElement("div", null, copy.recordings.engine, ": ", attempt.engine, " \xB7", {
1841
2290
  pending: copy.recordings.pending,
1842
2291
  success: copy.recordings.success,
1843
2292
  error: copy.recordings.error
1844
- }[attempt.status]), /* @__PURE__ */ import_react22.default.createElement("time", { dateTime: attempt.createdAt }, new Date(attempt.createdAt).toLocaleString()), attempt.finishedAt && /* @__PURE__ */ import_react22.default.createElement(import_react22.default.Fragment, null, " ", "\u2014", " ", /* @__PURE__ */ import_react22.default.createElement("time", { dateTime: attempt.finishedAt }, new Date(attempt.finishedAt).toLocaleString())), /* @__PURE__ */ import_react22.default.createElement("div", null, duration(attempt.startSample, session.sampleRate), " \u2014", " ", duration(attempt.endSample, session.sampleRate)), attempt.text != null && /* @__PURE__ */ import_react22.default.createElement("p", { className: "dlvd-transcript" }, attempt.text), attempt.error && /* @__PURE__ */ import_react22.default.createElement("p", { className: "dlvd-attempt-error" }, copy.recordings.error, ": ", attempt.error)))))))))), /* @__PURE__ */ import_react22.default.createElement("details", null, /* @__PURE__ */ import_react22.default.createElement("summary", null, copy.recordings.pins, " \xB7 ", session.pins.length), /* @__PURE__ */ import_react22.default.createElement("table", null, /* @__PURE__ */ import_react22.default.createElement("thead", null, /* @__PURE__ */ import_react22.default.createElement("tr", null, /* @__PURE__ */ import_react22.default.createElement("th", { scope: "col" }, copy.recordings.state), /* @__PURE__ */ import_react22.default.createElement("th", { scope: "col" }, copy.recordings.start), /* @__PURE__ */ import_react22.default.createElement("th", { scope: "col" }, copy.recordings.pinConfirmed), /* @__PURE__ */ import_react22.default.createElement("th", { scope: "col" }, copy.recordings.pinDelay))), /* @__PURE__ */ import_react22.default.createElement("tbody", null, session.pins.map((pin) => /* @__PURE__ */ import_react22.default.createElement("tr", { key: pin.id }, /* @__PURE__ */ import_react22.default.createElement("td", null, pin.kind === "speech-start" ? copy.recordings.speech : copy.recordings.silence), /* @__PURE__ */ import_react22.default.createElement("td", null, duration(pin.atSample, session.sampleRate)), /* @__PURE__ */ import_react22.default.createElement("td", null, duration(pin.confirmedAtSample, session.sampleRate)), /* @__PURE__ */ import_react22.default.createElement("td", null, duration(pin.delaySamples, session.sampleRate))))))));
2293
+ }[attempt.status]), /* @__PURE__ */ import_react23.default.createElement("time", { dateTime: attempt.createdAt }, new Date(attempt.createdAt).toLocaleString()), attempt.finishedAt && /* @__PURE__ */ import_react23.default.createElement(import_react23.default.Fragment, null, " ", "\u2014", " ", /* @__PURE__ */ import_react23.default.createElement("time", { dateTime: attempt.finishedAt }, new Date(attempt.finishedAt).toLocaleString())), /* @__PURE__ */ import_react23.default.createElement("div", null, duration(attempt.startSample, session.sampleRate), " \u2014", " ", duration(attempt.endSample, session.sampleRate)), attempt.text != null && /* @__PURE__ */ import_react23.default.createElement("p", { className: "dlvd-transcript" }, attempt.text), attempt.error && /* @__PURE__ */ import_react23.default.createElement("p", { className: "dlvd-attempt-error" }, copy.recordings.error, ": ", attempt.error)))))))))), /* @__PURE__ */ import_react23.default.createElement("details", null, /* @__PURE__ */ import_react23.default.createElement("summary", null, copy.recordings.pins, " \xB7 ", session.pins.length), /* @__PURE__ */ import_react23.default.createElement("table", null, /* @__PURE__ */ import_react23.default.createElement("thead", null, /* @__PURE__ */ import_react23.default.createElement("tr", null, /* @__PURE__ */ import_react23.default.createElement("th", { scope: "col" }, copy.recordings.state), /* @__PURE__ */ import_react23.default.createElement("th", { scope: "col" }, copy.recordings.start), /* @__PURE__ */ import_react23.default.createElement("th", { scope: "col" }, copy.recordings.pinConfirmed), /* @__PURE__ */ import_react23.default.createElement("th", { scope: "col" }, copy.recordings.pinDelay))), /* @__PURE__ */ import_react23.default.createElement("tbody", null, session.pins.map((pin) => /* @__PURE__ */ import_react23.default.createElement("tr", { key: pin.id }, /* @__PURE__ */ import_react23.default.createElement("td", null, pin.kind === "speech-start" ? copy.recordings.speech : copy.recordings.silence), /* @__PURE__ */ import_react23.default.createElement("td", null, duration(pin.atSample, session.sampleRate)), /* @__PURE__ */ import_react23.default.createElement("td", null, duration(pin.confirmedAtSample, session.sampleRate)), /* @__PURE__ */ import_react23.default.createElement("td", null, duration(pin.delaySamples, session.sampleRate))))))));
1845
2294
  }
1846
2295
 
1847
2296
  // src/RuntimePanel.tsx
1848
- var import_react23 = __toESM(require("react"), 1);
2297
+ var import_react24 = __toESM(require("react"), 1);
1849
2298
  function RuntimePanel({ data, copy }) {
1850
2299
  const unknown = copy.runtimes.unavailable;
1851
2300
  const bytes = (n) => typeof n === "number" && Number.isFinite(n) ? (n / 1073741824).toFixed(3) + " GiB (" + Math.round(n).toLocaleString() + " B)" : unknown;
@@ -1861,20 +2310,20 @@ function RuntimePanel({ data, copy }) {
1861
2310
  released: copy.runtimes.released,
1862
2311
  cancelled: copy.runtimes.cancelled
1863
2312
  })[v] ?? unknown;
1864
- const row = (label, value) => /* @__PURE__ */ import_react23.default.createElement(import_react23.default.Fragment, { key: label }, /* @__PURE__ */ import_react23.default.createElement("dt", null, label), /* @__PURE__ */ import_react23.default.createElement("dd", null, value));
1865
- return /* @__PURE__ */ import_react23.default.createElement("section", { className: "dlvd-runtimes dlvd-scroll", tabIndex: 0, "aria-label": copy.runtimes.title }, /* @__PURE__ */ import_react23.default.createElement("h3", null, copy.runtimes.title, " ", /* @__PURE__ */ import_react23.default.createElement(Hint, { label: copy.runtimes.title }, copy.runtimes.help)), /* @__PURE__ */ import_react23.default.createElement("dl", { className: "dlvd-recording-meta" }, row(
2313
+ const row = (label, value) => /* @__PURE__ */ import_react24.default.createElement(import_react24.default.Fragment, { key: label }, /* @__PURE__ */ import_react24.default.createElement("dt", null, label), /* @__PURE__ */ import_react24.default.createElement("dd", null, value));
2314
+ return /* @__PURE__ */ import_react24.default.createElement("section", { className: "dlvd-runtimes dlvd-scroll", tabIndex: 0, "aria-label": copy.runtimes.title }, /* @__PURE__ */ import_react24.default.createElement("h3", null, copy.runtimes.title, " ", /* @__PURE__ */ import_react24.default.createElement(Hint, { label: copy.runtimes.title }, copy.runtimes.help)), /* @__PURE__ */ import_react24.default.createElement("dl", { className: "dlvd-recording-meta" }, row(
1866
2315
  copy.runtimes.versions,
1867
2316
  (data.versions?.onnx ?? unknown) + " / " + (data.versions?.transformers ?? unknown)
1868
2317
  ), row(copy.runtimes.id, data.runtimeId ?? unknown), row(
1869
2318
  copy.runtimes.gpu,
1870
2319
  data.gpu === "available" ? copy.runtimes.yes : data.gpu === "unavailable" ? copy.runtimes.no : unknown
1871
- ), row(copy.runtimes.storage, bytes(data.storageAvailableBytes)), row(copy.runtimes.heap, bytes(data.pageJsHeapBytes)), row(copy.runtimes.ram, unknown), row(copy.runtimes.vram, unknown)), (data.models ?? []).map((model) => /* @__PURE__ */ import_react23.default.createElement("article", { className: "dlvd-runtime-card", key: model.key }, /* @__PURE__ */ import_react23.default.createElement("h3", null, model.name), /* @__PURE__ */ import_react23.default.createElement("dl", { className: "dlvd-recording-meta" }, row(copy.runtimes.status, status(model.phase)), row(
2320
+ ), row(copy.runtimes.storage, bytes(data.storageAvailableBytes)), row(copy.runtimes.heap, bytes(data.pageJsHeapBytes)), row(copy.runtimes.ram, unknown), row(copy.runtimes.vram, unknown)), (data.models ?? []).map((model) => /* @__PURE__ */ import_react24.default.createElement("article", { className: "dlvd-runtime-card", key: model.key }, /* @__PURE__ */ import_react24.default.createElement("h3", null, model.name), /* @__PURE__ */ import_react24.default.createElement("dl", { className: "dlvd-recording-meta" }, row(copy.runtimes.status, status(model.phase)), row(
1872
2321
  copy.runtimes.device,
1873
2322
  model.device === "webgpu" ? "WebGPU" : model.device === "wasm" ? "WebAssembly CPU" : unknown
1874
2323
  ), row(copy.runtimes.worker, model.workerActive ? copy.runtimes.yes : copy.runtimes.no), row(copy.runtimes.revision, model.repository + " @ " + model.revision), row(copy.runtimes.quantization, model.encoderDtype + " / " + model.decoderDtype), row(copy.runtimes.modelBytes, bytes(model.modelBytes)), row(copy.runtimes.cache, bytes(model.cachedBytes)), row(copy.runtimes.pcm, bytes(model.pcmBytes)), row(copy.runtimes.load, ms(model.loadMs) + " / " + ms(model.workerLoadMs)), row(copy.runtimes.inference, ms(model.workerInferenceMs)), row(copy.runtimes.audio, ms(model.audioMs)), row(
1875
2324
  copy.runtimes.ratio,
1876
2325
  model.workerInferenceMs != null && model.audioMs > 0 ? (model.workerInferenceMs / model.audioMs).toFixed(2) + "\xD7" : unknown
1877
- ), row(copy.runtimes.queue, model.queued), row(copy.runtimes.active, model.active), row(copy.runtimes.pending, model.pendingRequests), row(copy.runtimes.completed, model.completed), row(copy.runtimes.failed, model.failed)), model.error && /* @__PURE__ */ import_react23.default.createElement("p", { role: "alert" }, copy.runtimes.error, ": ", /* @__PURE__ */ import_react23.default.createElement("code", null, model.error)))), /* @__PURE__ */ import_react23.default.createElement("h3", null, copy.runtimes.events), /* @__PURE__ */ import_react23.default.createElement("div", { className: "dlvd-history" }, !data.events?.length && /* @__PURE__ */ import_react23.default.createElement("p", null, copy.commons.empty), [...data.events ?? []].reverse().map((event) => /* @__PURE__ */ import_react23.default.createElement("div", { key: event.sequence, "data-level": event.status === "error" ? "error" : "debug" }, /* @__PURE__ */ import_react23.default.createElement("time", null, new Date(event.timeMs).toLocaleTimeString()), " \xB7 ", event.model, " \xB7", " ", event.operation === "load" ? copy.runtimes.load : event.operation === "worker" ? copy.runtimes.worker : copy.runtimes.inference, " ", "\xB7 ", status(event.status), event.durationMs != null ? " \xB7 " + ms(event.durationMs) : "", event.code && /* @__PURE__ */ import_react23.default.createElement(import_react23.default.Fragment, null, " ", "\xB7 ", /* @__PURE__ */ import_react23.default.createElement("code", null, event.code))))));
2326
+ ), row(copy.runtimes.queue, model.queued), row(copy.runtimes.active, model.active), row(copy.runtimes.pending, model.pendingRequests), row(copy.runtimes.completed, model.completed), row(copy.runtimes.failed, model.failed)), model.error && /* @__PURE__ */ import_react24.default.createElement("p", { role: "alert" }, copy.runtimes.error, ": ", /* @__PURE__ */ import_react24.default.createElement("code", null, model.error)))), /* @__PURE__ */ import_react24.default.createElement("h3", null, copy.runtimes.events), /* @__PURE__ */ import_react24.default.createElement("div", { className: "dlvd-history" }, !data.events?.length && /* @__PURE__ */ import_react24.default.createElement("p", null, copy.commons.empty), [...data.events ?? []].reverse().map((event) => /* @__PURE__ */ import_react24.default.createElement("div", { key: event.sequence, "data-level": event.status === "error" ? "error" : "debug" }, /* @__PURE__ */ import_react24.default.createElement("time", null, new Date(event.timeMs).toLocaleTimeString()), " \xB7 ", event.model, " \xB7", " ", event.operation === "load" ? copy.runtimes.load : event.operation === "worker" ? copy.runtimes.worker : copy.runtimes.inference, " ", "\xB7 ", status(event.status), event.durationMs != null ? " \xB7 " + ms(event.durationMs) : "", event.code && /* @__PURE__ */ import_react24.default.createElement(import_react24.default.Fragment, null, " ", "\xB7 ", /* @__PURE__ */ import_react24.default.createElement("code", null, event.code))))));
1878
2327
  }
1879
2328
 
1880
2329
  // src/DebuggerPanel.tsx
@@ -1883,19 +2332,19 @@ function DebuggerPanel({
1883
2332
  onClose,
1884
2333
  target = window
1885
2334
  }) {
1886
- const [tab, setTab] = import_react24.default.useState("recordings");
1887
- const tabsId = import_react24.default.useId();
1888
- const [frozen, setFrozen] = import_react24.default.useState(false);
1889
- const [refreshHz, setRefreshHz] = import_react24.default.useState(10);
1890
- const updateRef = import_react24.default.useRef(null);
1891
- const [content, setContent] = import_react24.default.useState(false);
1892
- const [module2, setModule] = import_react24.default.useState("");
1893
- const [view, setView] = import_react24.default.useState(null);
1894
- const [failed, setFailed] = import_react24.default.useState(false);
1895
- const [eventsPaused, setEventsPaused] = import_react24.default.useState(false);
1896
- const pausedRef = import_react24.default.useRef(false);
1897
- const inspectorRef = import_react24.default.useRef(null);
1898
- import_react24.default.useEffect(() => {
2335
+ const [tab, setTab] = import_react25.default.useState("recordings");
2336
+ const tabsId = import_react25.default.useId();
2337
+ const [frozen, setFrozen] = import_react25.default.useState(false);
2338
+ const [refreshHz, setRefreshHz] = import_react25.default.useState(10);
2339
+ const updateRef = import_react25.default.useRef(null);
2340
+ const [content, setContent] = import_react25.default.useState(false);
2341
+ const [module2, setModule] = import_react25.default.useState("");
2342
+ const [view, setView] = import_react25.default.useState(null);
2343
+ const [failed, setFailed] = import_react25.default.useState(false);
2344
+ const [eventsPaused, setEventsPaused] = import_react25.default.useState(false);
2345
+ const pausedRef = import_react25.default.useRef(false);
2346
+ const inspectorRef = import_react25.default.useRef(null);
2347
+ import_react25.default.useEffect(() => {
1899
2348
  if (frozen) return;
1900
2349
  let inspector = null;
1901
2350
  let source = null;
@@ -1928,7 +2377,7 @@ function DebuggerPanel({
1928
2377
  inspectorRef.current = null;
1929
2378
  };
1930
2379
  }, [frozen, content, target]);
1931
- import_react24.default.useEffect(() => {
2380
+ import_react25.default.useEffect(() => {
1932
2381
  if (frozen) return;
1933
2382
  const timer = setInterval(() => updateRef.current?.(), 1e3 / refreshHz);
1934
2383
  return () => clearInterval(timer);
@@ -1937,10 +2386,10 @@ function DebuggerPanel({
1937
2386
  const runtimeData = view?.state?.runtimes;
1938
2387
  const hasRuntimes = !!runtimeData?.models?.length;
1939
2388
  const tabs = hasRuntimes ? ["recordings", "states", "runtimes"] : ["recordings", "states"];
1940
- import_react24.default.useEffect(() => {
2389
+ import_react25.default.useEffect(() => {
1941
2390
  if (tab === "runtimes" && !hasRuntimes) setTab("states");
1942
2391
  }, [tab, hasRuntimes]);
1943
- return /* @__PURE__ */ import_react24.default.createElement("aside", { className: "dlvd-panel", "aria-label": copy.commons.title }, /* @__PURE__ */ import_react24.default.createElement("header", null, /* @__PURE__ */ import_react24.default.createElement("strong", null, copy.commons.title), /* @__PURE__ */ import_react24.default.createElement("span", null, refreshHz, " Hz"), /* @__PURE__ */ import_react24.default.createElement("button", { type: "button", onClick: onClose, "aria-label": copy.commons.close }, "\xD7")), /* @__PURE__ */ import_react24.default.createElement("div", { className: "dlvd-tabs", role: "tablist", "aria-label": copy.commons.title }, tabs.map((name) => /* @__PURE__ */ import_react24.default.createElement(
2392
+ return /* @__PURE__ */ import_react25.default.createElement("aside", { className: "dlvd-panel", "aria-label": copy.commons.title }, /* @__PURE__ */ import_react25.default.createElement("header", null, /* @__PURE__ */ import_react25.default.createElement("strong", null, copy.commons.title), /* @__PURE__ */ import_react25.default.createElement("span", null, refreshHz, " Hz"), /* @__PURE__ */ import_react25.default.createElement("button", { type: "button", onClick: onClose, "aria-label": copy.commons.close }, "\xD7")), /* @__PURE__ */ import_react25.default.createElement("div", { className: "dlvd-tabs", role: "tablist", "aria-label": copy.commons.title }, tabs.map((name) => /* @__PURE__ */ import_react25.default.createElement(
1944
2393
  "button",
1945
2394
  {
1946
2395
  type: "button",
@@ -1962,7 +2411,7 @@ function DebuggerPanel({
1962
2411
  }
1963
2412
  },
1964
2413
  name === "recordings" ? copy.recordings.title : name === "runtimes" ? copy.runtimes.title : copy.commons.states
1965
- ))), /* @__PURE__ */ import_react24.default.createElement(
2414
+ ))), /* @__PURE__ */ import_react25.default.createElement(
1966
2415
  "div",
1967
2416
  {
1968
2417
  className: "dlvd-tab-panel",
@@ -1971,8 +2420,8 @@ function DebuggerPanel({
1971
2420
  "aria-labelledby": tabsId + "-recordings-tab",
1972
2421
  hidden: tab !== "recordings"
1973
2422
  },
1974
- tab === "recordings" && /* @__PURE__ */ import_react24.default.createElement(RecordingPanel, { copy, target })
1975
- ), hasRuntimes && /* @__PURE__ */ import_react24.default.createElement(
2423
+ tab === "recordings" && /* @__PURE__ */ import_react25.default.createElement(RecordingPanel, { copy, target })
2424
+ ), hasRuntimes && /* @__PURE__ */ import_react25.default.createElement(
1976
2425
  "div",
1977
2426
  {
1978
2427
  className: "dlvd-tab-panel",
@@ -1981,8 +2430,8 @@ function DebuggerPanel({
1981
2430
  "aria-labelledby": tabsId + "-runtimes-tab",
1982
2431
  hidden: tab !== "runtimes"
1983
2432
  },
1984
- tab === "runtimes" && /* @__PURE__ */ import_react24.default.createElement(RuntimePanel, { data: runtimeData, copy })
1985
- ), /* @__PURE__ */ import_react24.default.createElement(
2433
+ tab === "runtimes" && /* @__PURE__ */ import_react25.default.createElement(RuntimePanel, { data: runtimeData, copy })
2434
+ ), /* @__PURE__ */ import_react25.default.createElement(
1986
2435
  "div",
1987
2436
  {
1988
2437
  className: "dlvd-tab-panel",
@@ -1991,15 +2440,15 @@ function DebuggerPanel({
1991
2440
  "aria-labelledby": tabsId + "-states-tab",
1992
2441
  hidden: tab !== "states"
1993
2442
  },
1994
- /* @__PURE__ */ import_react24.default.createElement("p", null, copy.commons.help),
1995
- /* @__PURE__ */ import_react24.default.createElement("div", { className: "dlvd-toolbar" }, /* @__PURE__ */ import_react24.default.createElement("label", null, copy.commons.refreshRate, /* @__PURE__ */ import_react24.default.createElement(
2443
+ /* @__PURE__ */ import_react25.default.createElement("p", null, copy.commons.help),
2444
+ /* @__PURE__ */ import_react25.default.createElement("div", { className: "dlvd-toolbar" }, /* @__PURE__ */ import_react25.default.createElement("label", null, copy.commons.refreshRate, /* @__PURE__ */ import_react25.default.createElement(
1996
2445
  "select",
1997
2446
  {
1998
2447
  value: refreshHz,
1999
2448
  onChange: (event) => setRefreshHz(Number(event.target.value))
2000
2449
  },
2001
- [1, 2, 5, 10, 20].map((hz) => /* @__PURE__ */ import_react24.default.createElement("option", { key: hz, value: hz }, hz, " Hz"))
2002
- )), /* @__PURE__ */ import_react24.default.createElement("button", { type: "button", onClick: () => setFrozen(!frozen) }, frozen ? copy.commons.resume : copy.commons.freeze), /* @__PURE__ */ import_react24.default.createElement("label", null, /* @__PURE__ */ import_react24.default.createElement(
2450
+ [1, 2, 5, 10, 20].map((hz) => /* @__PURE__ */ import_react25.default.createElement("option", { key: hz, value: hz }, hz, " Hz"))
2451
+ )), /* @__PURE__ */ import_react25.default.createElement("button", { type: "button", onClick: () => setFrozen(!frozen) }, frozen ? copy.commons.resume : copy.commons.freeze), /* @__PURE__ */ import_react25.default.createElement("label", null, /* @__PURE__ */ import_react25.default.createElement(
2003
2452
  "input",
2004
2453
  {
2005
2454
  type: "checkbox",
@@ -2011,7 +2460,7 @@ function DebuggerPanel({
2011
2460
  }
2012
2461
  }
2013
2462
  ), copy.commons.content)),
2014
- failed ? /* @__PURE__ */ import_react24.default.createElement("p", { role: "alert" }, copy.commons.error) : !view ? /* @__PURE__ */ import_react24.default.createElement("p", { role: "status" }, copy.commons.waiting) : /* @__PURE__ */ import_react24.default.createElement("div", { className: "dlvd-columns" }, /* @__PURE__ */ import_react24.default.createElement("section", { className: "dlvd-state-pane", "aria-label": copy.commons.states }, /* @__PURE__ */ import_react24.default.createElement("h3", null, copy.commons.states), /* @__PURE__ */ import_react24.default.createElement("div", { className: "dlvd-scroll", tabIndex: 0 }, /* @__PURE__ */ import_react24.default.createElement(StateTree, { name: "context", value: view.state, omitted: copy.commons.omitted }))), /* @__PURE__ */ import_react24.default.createElement("section", { className: "dlvd-event-pane", "aria-label": copy.commons.transitions }, /* @__PURE__ */ import_react24.default.createElement("h3", null, copy.commons.transitions), /* @__PURE__ */ import_react24.default.createElement("div", { className: "dlvd-toolbar" }, /* @__PURE__ */ import_react24.default.createElement(
2463
+ failed ? /* @__PURE__ */ import_react25.default.createElement("p", { role: "alert" }, copy.commons.error) : !view ? /* @__PURE__ */ import_react25.default.createElement("p", { role: "status" }, copy.commons.waiting) : /* @__PURE__ */ import_react25.default.createElement("div", { className: "dlvd-columns" }, /* @__PURE__ */ import_react25.default.createElement("section", { className: "dlvd-state-pane", "aria-label": copy.commons.states }, /* @__PURE__ */ import_react25.default.createElement("h3", null, copy.commons.states), /* @__PURE__ */ import_react25.default.createElement("div", { className: "dlvd-scroll", tabIndex: 0 }, /* @__PURE__ */ import_react25.default.createElement(StateTree, { name: "context", value: view.state, omitted: copy.commons.omitted }))), /* @__PURE__ */ import_react25.default.createElement("section", { className: "dlvd-event-pane", "aria-label": copy.commons.transitions }, /* @__PURE__ */ import_react25.default.createElement("h3", null, copy.commons.transitions), /* @__PURE__ */ import_react25.default.createElement("div", { className: "dlvd-toolbar" }, /* @__PURE__ */ import_react25.default.createElement(
2015
2464
  "button",
2016
2465
  {
2017
2466
  type: "button",
@@ -2024,7 +2473,7 @@ function DebuggerPanel({
2024
2473
  }
2025
2474
  },
2026
2475
  eventsPaused ? copy.commons.eventsResume : copy.commons.eventsPause
2027
- ), /* @__PURE__ */ import_react24.default.createElement(
2476
+ ), /* @__PURE__ */ import_react25.default.createElement(
2028
2477
  "button",
2029
2478
  {
2030
2479
  type: "button",
@@ -2034,14 +2483,14 @@ function DebuggerPanel({
2034
2483
  }
2035
2484
  },
2036
2485
  copy.commons.eventsClear
2037
- )), /* @__PURE__ */ import_react24.default.createElement("label", null, copy.commons.filter, /* @__PURE__ */ import_react24.default.createElement("select", { value: module2, onChange: (event) => setModule(event.target.value) }, /* @__PURE__ */ import_react24.default.createElement("option", { value: "" }, copy.commons.all), modules.map((name) => /* @__PURE__ */ import_react24.default.createElement("option", { key: name }, name)))), /* @__PURE__ */ import_react24.default.createElement("div", { className: "dlvd-history dlvd-scroll", tabIndex: 0 }, view.transitions.filter((entry) => !module2 || entry.module === module2).slice().reverse().map((entry) => /* @__PURE__ */ import_react24.default.createElement("details", { key: entry.sequence, "data-level": entry.level }, /* @__PURE__ */ import_react24.default.createElement("summary", null, /* @__PURE__ */ import_react24.default.createElement("small", null, new Date(entry.timeMs).toLocaleTimeString()), " ", /* @__PURE__ */ import_react24.default.createElement("code", null, entry.sessionId, " / ", entry.module)), /* @__PURE__ */ import_react24.default.createElement(
2486
+ )), /* @__PURE__ */ import_react25.default.createElement("label", null, copy.commons.filter, /* @__PURE__ */ import_react25.default.createElement("select", { value: module2, onChange: (event) => setModule(event.target.value) }, /* @__PURE__ */ import_react25.default.createElement("option", { value: "" }, copy.commons.all), modules.map((name) => /* @__PURE__ */ import_react25.default.createElement("option", { key: name }, name)))), /* @__PURE__ */ import_react25.default.createElement("div", { className: "dlvd-history dlvd-scroll", tabIndex: 0 }, view.transitions.filter((entry) => !module2 || entry.module === module2).slice().reverse().map((entry) => /* @__PURE__ */ import_react25.default.createElement("details", { key: entry.sequence, "data-level": entry.level }, /* @__PURE__ */ import_react25.default.createElement("summary", null, /* @__PURE__ */ import_react25.default.createElement("small", null, new Date(entry.timeMs).toLocaleTimeString()), " ", /* @__PURE__ */ import_react25.default.createElement("code", null, entry.sessionId, " / ", entry.module)), /* @__PURE__ */ import_react25.default.createElement(
2038
2487
  StateTree,
2039
2488
  {
2040
2489
  name: "before",
2041
2490
  value: entry.before,
2042
2491
  omitted: copy.commons.omitted
2043
2492
  }
2044
- ), /* @__PURE__ */ import_react24.default.createElement(StateTree, { name: "after", value: entry.after, omitted: copy.commons.omitted }))), !view.transitions.length && /* @__PURE__ */ import_react24.default.createElement("p", null, copy.commons.empty))))
2493
+ ), /* @__PURE__ */ import_react25.default.createElement(StateTree, { name: "after", value: entry.after, omitted: copy.commons.omitted }))), !view.transitions.length && /* @__PURE__ */ import_react25.default.createElement("p", null, copy.commons.empty))))
2045
2494
  ));
2046
2495
  }
2047
2496
 
@@ -2073,7 +2522,7 @@ function normalizeDebuggerLocale(locale) {
2073
2522
  }
2074
2523
 
2075
2524
  // node_modules/.pnpm/@wads.dev+i18n-react@0.0.1-alpha.0_react@19.3.0_typescript@7.0.2/node_modules/@wads.dev/i18n-react/dist/index.js
2076
- var import_react25 = require("react");
2525
+ var import_react26 = require("react");
2077
2526
 
2078
2527
  // node_modules/.pnpm/@wads.dev+i18n-ts@0.0.1-alpha.0_typescript@7.0.2/node_modules/@wads.dev/i18n-ts/dist/runtime/language.js
2079
2528
  function detectLanguage() {
@@ -2106,21 +2555,21 @@ function deepFreeze(value) {
2106
2555
 
2107
2556
  // node_modules/.pnpm/@wads.dev+i18n-react@0.0.1-alpha.0_react@19.3.0_typescript@7.0.2/node_modules/@wads.dev/i18n-react/dist/index.js
2108
2557
  function createTranslationRuntime({ availableLangs, defaultLang, onLanguageLoaded }) {
2109
- const context = (0, import_react25.createContext)({});
2558
+ const context = (0, import_react26.createContext)({});
2110
2559
  function useTranslation(selector) {
2111
- const value = (0, import_react25.useContext)(context);
2560
+ const value = (0, import_react26.useContext)(context);
2112
2561
  if (!value.current)
2113
2562
  throw new Error("useTranslation must be used within TranslationProvider.");
2114
2563
  return { ...value, scoped: selector ? selector(value.current.lang) : value.current.lang };
2115
2564
  }
2116
2565
  function TranslationProvider({ children }) {
2117
- const [saved, setSaved] = (0, import_react25.useState)();
2118
- const [language, setCurrentLanguage] = (0, import_react25.useState)();
2566
+ const [saved, setSaved] = (0, import_react26.useState)();
2567
+ const [language, setCurrentLanguage] = (0, import_react26.useState)();
2119
2568
  function setLanguage(nextLanguage, save) {
2120
2569
  if (save)
2121
2570
  setSaved(nextLanguage);
2122
2571
  }
2123
- (0, import_react25.useEffect)(() => {
2572
+ (0, import_react26.useEffect)(() => {
2124
2573
  void loadLanguage(availableLangs, defaultLang, saved).then((loadedLanguage) => {
2125
2574
  setCurrentLanguage(loadedLanguage);
2126
2575
  onLanguageLoaded?.(loadedLanguage);
@@ -2128,7 +2577,7 @@ function createTranslationRuntime({ availableLangs, defaultLang, onLanguageLoade
2128
2577
  }, [saved]);
2129
2578
  if (!language)
2130
2579
  return null;
2131
- return (0, import_react25.createElement)(context.Provider, { value: { setLanguage, available: availableLangs, current: language, saved } }, children);
2580
+ return (0, import_react26.createElement)(context.Provider, { value: { setLanguage, available: availableLangs, current: language, saved } }, children);
2132
2581
  }
2133
2582
  return { TranslationProvider, useTranslation };
2134
2583
  }
@@ -2143,28 +2592,28 @@ var {
2143
2592
  });
2144
2593
 
2145
2594
  // src/i18n/DshLanguageBoundary.tsx
2146
- var import_react26 = __toESM(require("react"), 1);
2595
+ var import_react27 = __toESM(require("react"), 1);
2147
2596
  var fallback = Object.freeze({ active: "en", revision: 0 });
2148
2597
  function DshLanguageBoundary({ locale, children }) {
2149
2598
  const { current, setLanguage } = useDebuggerLanguage();
2150
- const subscribe = import_react26.default.useCallback(
2599
+ const subscribe = import_react27.default.useCallback(
2151
2600
  (listener) => locale?.subscribe?.(listener) ?? (() => {
2152
2601
  }),
2153
2602
  [locale]
2154
2603
  );
2155
- const snapshot = import_react26.default.useCallback(() => locale?.getSnapshot?.() ?? fallback, [locale]);
2156
- const state = import_react26.default.useSyncExternalStore(subscribe, snapshot, snapshot);
2604
+ const snapshot = import_react27.default.useCallback(() => locale?.getSnapshot?.() ?? fallback, [locale]);
2605
+ const state = import_react27.default.useSyncExternalStore(subscribe, snapshot, snapshot);
2157
2606
  const expected = normalizeDebuggerLocale(state.active);
2158
- import_react26.default.useEffect(() => {
2607
+ import_react27.default.useEffect(() => {
2159
2608
  if (current.locale !== expected) setLanguage(expected, true);
2160
2609
  }, [current.locale, expected, setLanguage]);
2161
- const initialized = import_react26.default.useRef(false);
2610
+ const initialized = import_react27.default.useRef(false);
2162
2611
  if (current.locale === expected) initialized.current = true;
2163
2612
  return initialized.current ? children : null;
2164
2613
  }
2165
2614
  function withDebuggerLanguage(Component, locale) {
2166
2615
  function Localized(props) {
2167
- return /* @__PURE__ */ import_react26.default.createElement(DebuggerTranslationProvider, null, /* @__PURE__ */ import_react26.default.createElement(DshLanguageBoundary, { locale }, /* @__PURE__ */ import_react26.default.createElement(Component, { ...props })));
2616
+ return /* @__PURE__ */ import_react27.default.createElement(DebuggerTranslationProvider, null, /* @__PURE__ */ import_react27.default.createElement(DshLanguageBoundary, { locale }, /* @__PURE__ */ import_react27.default.createElement(Component, { ...props })));
2168
2617
  }
2169
2618
  Localized.displayName = "DebuggerLanguage(" + (Component.displayName || Component.name || "Component") + ")";
2170
2619
  return Localized;
@@ -2200,6 +2649,9 @@ function registerDshLocales(ctx) {
2200
2649
 
2201
2650
  // src/styles.ts
2202
2651
  var styles = `
2652
+ .dlvd-timeline-window{display:flex;gap:12px;align-items:center}.dlvd-window-selector{flex:1;min-width:0;padding:0 10px}.dlvd-window-values{display:flex;justify-content:space-between;gap:12px;flex-wrap:wrap;font-variant-numeric:tabular-nums}.dlvd-window-track{position:relative;height:32px;touch-action:none;user-select:none}.dlvd-window-track:before{content:"";position:absolute;left:0;right:0;top:14px;height:4px;border-radius:4px;background:var(--dsw-alias-border-l2,#ffffff40)}.dlvd-panel .dlvd-window-selection{position:absolute;top:11px;height:10px;min-width:1px;padding:0;border:0;border-radius:4px;background:var(--dsw-alias-state-business-primary,#7aaaff);cursor:grab;touch-action:none}.dlvd-panel .dlvd-window-selection:active{cursor:grabbing}.dlvd-panel .dlvd-window-handle{position:absolute;top:0;width:20px;height:32px;transform:translateX(-50%);padding:0;border:0;border-radius:4px;background:transparent;cursor:ew-resize;touch-action:none;z-index:1}.dlvd-window-handle:before{content:"";position:absolute;width:12px;height:12px;left:4px;top:10px;border-radius:50%;background:var(--dsw-alias-label-primary,#f9fafb);box-shadow:0 0 0 1px #0004}.dlvd-panel .dlvd-window-reset{display:inline-flex;align-items:center;justify-content:center;padding:6px;flex:none}.dlvd-window-track button:disabled{cursor:default}
2653
+ .dlvd-event-pin{position:absolute;transform:translateX(-100%);color:#ffbd66;font-size:14px;line-height:14px;pointer-events:none;z-index:1}.dlvd-event-pin[data-event=capture-gated]{color:#f88888}.dlvd-recordings input{font:inherit;background:var(--dsw-alias-bg-layer-1,#232324);color:inherit;border:1px solid var(--dsw-alias-border-l2,#ffffff1f);border-radius:6px;padding:5px;max-width:100%;box-sizing:border-box}
2654
+
2203
2655
  .dlvd-runtimes{overflow-wrap:anywhere}.dlvd-runtimes h3{margin:8px 0}.dlvd-runtime-card{border-top:1px solid var(--dsw-alias-border-l2,#ffffff1f);padding:12px 0}.dlvd-runtimes .dlvd-history>div{border-bottom:1px solid var(--dsw-alias-border-l1,#ffffff0f);padding:6px 0}.dlvd-tabs{flex-wrap:wrap}
2204
2656
 
2205
2657
  .dlvd-columns{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:16px;flex:1;min-height:0;overflow:hidden}.dlvd-state-pane,.dlvd-event-pane{display:flex;flex-direction:column;min-width:0;min-height:0;overflow:hidden}.dlvd-event-pane{border-left:1px solid var(--dsw-alias-border-l1, #ffffff0f);padding-left:16px}.dlvd-columns h3{margin:0 0 10px}.dlvd-scroll{flex:1;min-height:0;overflow:auto;overscroll-behavior:contain;scrollbar-gutter:stable;padding-right:8px}.dlvd-scroll:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary, #7aaaff);outline-offset:-2px}.dlvd-history summary{overflow-wrap:anywhere}.dlvd-panel>header,.dlvd-panel>p,.dlvd-panel>.dlvd-toolbar{flex-shrink:0}
@@ -2270,10 +2722,10 @@ function apply(ctx) {
2270
2722
  };
2271
2723
  function Host() {
2272
2724
  const { scoped: labels } = useDebuggerLanguage();
2273
- import_react27.default.useEffect(() => {
2725
+ import_react28.default.useEffect(() => {
2274
2726
  if (popup && !popup.closed) popup.document.title = labels.commons.title;
2275
2727
  }, [labels.commons.title]);
2276
- return /* @__PURE__ */ import_react27.default.createElement(DebuggerPanel, { copy: labels, target: window, onClose: () => queueMicrotask(close) });
2728
+ return /* @__PURE__ */ import_react28.default.createElement(DebuggerPanel, { copy: labels, target: window, onClose: () => queueMicrotask(close) });
2277
2729
  }
2278
2730
  const open = () => {
2279
2731
  if (popup && !popup.closed) {
@@ -2307,7 +2759,7 @@ function apply(ctx) {
2307
2759
  container.dataset.plugin = namespace;
2308
2760
  doc.body.appendChild(container);
2309
2761
  root = (0, import_client.createRoot)(container);
2310
- root.render(/* @__PURE__ */ import_react27.default.createElement(LocalizedHost, null));
2762
+ root.render(/* @__PURE__ */ import_react28.default.createElement(LocalizedHost, null));
2311
2763
  enabled = true;
2312
2764
  closedTimer = setInterval(() => {
2313
2765
  if (popup?.closed) close();
@@ -2322,9 +2774,9 @@ function apply(ctx) {
2322
2774
  }
2323
2775
  };
2324
2776
  function Settings() {
2325
- const failed = import_react27.default.useSyncExternalStore(subscribe, () => blocked);
2777
+ const failed = import_react28.default.useSyncExternalStore(subscribe, () => blocked);
2326
2778
  const { scoped: labels } = useDebuggerLanguage();
2327
- return /* @__PURE__ */ import_react27.default.createElement("div", { className: "dlv-diagnostics-launcher" }, /* @__PURE__ */ import_react27.default.createElement("button", { type: "button", className: "dlv-diagnostics-button", onClick: open }, /* @__PURE__ */ import_react27.default.createElement(Icon, { name: "bug" }), labels.commons.diagnostics), /* @__PURE__ */ import_react27.default.createElement(Hint, { label: labels.commons.diagnostics }, labels.commons.activate), failed && /* @__PURE__ */ import_react27.default.createElement("p", { role: "alert" }, labels.commons.popupBlocked));
2779
+ return /* @__PURE__ */ import_react28.default.createElement("div", { className: "dlv-diagnostics-launcher" }, /* @__PURE__ */ import_react28.default.createElement("button", { type: "button", className: "dlv-diagnostics-button", onClick: open }, /* @__PURE__ */ import_react28.default.createElement(Icon, { name: "bug" }), labels.commons.diagnostics), /* @__PURE__ */ import_react28.default.createElement(Hint, { label: labels.commons.diagnostics }, labels.commons.activate), failed && /* @__PURE__ */ import_react28.default.createElement("p", { role: "alert" }, labels.commons.popupBlocked));
2328
2780
  }
2329
2781
  const LocalizedHost = withDebuggerLanguage(Host, ctx.locale);
2330
2782
  const LocalizedSettings = withDebuggerLanguage(Settings, ctx.locale);