@iblai/iblai-js 2.7.7 → 2.7.9
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.
|
@@ -6720,7 +6720,8 @@ var voiceTabLabels$3 = {
|
|
|
6720
6720
|
},
|
|
6721
6721
|
subTabs: {
|
|
6722
6722
|
voice: "Voice",
|
|
6723
|
-
callConfig: "Voice
|
|
6723
|
+
callConfig: "Voice Call",
|
|
6724
|
+
settings: "Settings"
|
|
6724
6725
|
},
|
|
6725
6726
|
mentorVoice: {
|
|
6726
6727
|
title: "Agent Voice",
|
|
@@ -6781,6 +6782,26 @@ var voiceTabLabels$3 = {
|
|
|
6781
6782
|
}
|
|
6782
6783
|
}
|
|
6783
6784
|
},
|
|
6785
|
+
transcription: {
|
|
6786
|
+
toggle: {
|
|
6787
|
+
label: "Dictation",
|
|
6788
|
+
tooltip: "Lets people speak into the microphone instead of typing, and turns what the agent hears into text. This is the opposite of the voice settings on the other sub-tabs: those decide how the agent sounds, this decides how well it understands what is said to it.",
|
|
6789
|
+
helpText: "When on, a microphone button appears in the chat box."
|
|
6790
|
+
},
|
|
6791
|
+
language: {
|
|
6792
|
+
label: "Spoken language",
|
|
6793
|
+
tooltip: "The language people will speak in. Naming it up front makes transcription noticeably more accurate. Leave it unset and the provider guesses from the audio.",
|
|
6794
|
+
placeholder: "Detect automatically"
|
|
6795
|
+
},
|
|
6796
|
+
instructions: {
|
|
6797
|
+
label: "Transcription hints",
|
|
6798
|
+
tooltip: "Words the transcriber is likely to get wrong — product names, acronyms, people, technical terms. Listing them here helps it spell them correctly.",
|
|
6799
|
+
placeholder: "e.g. Expect the terms ibl.ai, LTI, and Open edX. Spell names as written.",
|
|
6800
|
+
helpText: "Optional. Some transcription providers use these hints; the ones that do not simply ignore them. Leave blank if you are not sure."
|
|
6801
|
+
},
|
|
6802
|
+
saveButton: "Save dictation",
|
|
6803
|
+
savingButton: "Saving…"
|
|
6804
|
+
},
|
|
6784
6805
|
callConfig: {
|
|
6785
6806
|
title: "Voice call",
|
|
6786
6807
|
description: "Customize how voice calls work. Screen sharing always uses live conversation.",
|
|
@@ -6832,7 +6853,9 @@ var voiceTabLabels$3 = {
|
|
|
6832
6853
|
voiceSaved: "Voice saved",
|
|
6833
6854
|
voiceError: "Couldn't save voice settings",
|
|
6834
6855
|
callConfigSaved: "Voice call settings saved",
|
|
6835
|
-
callConfigError: "Couldn't save voice call settings"
|
|
6856
|
+
callConfigError: "Couldn't save voice call settings",
|
|
6857
|
+
transcriptionSaved: "Dictation settings saved",
|
|
6858
|
+
transcriptionError: "Couldn't save dictation settings"
|
|
6836
6859
|
}
|
|
6837
6860
|
};
|
|
6838
6861
|
var voiceTabVoicePicker$3 = {
|
|
@@ -13884,7 +13907,8 @@ var voiceTabLabels$2 = {
|
|
|
13884
13907
|
},
|
|
13885
13908
|
subTabs: {
|
|
13886
13909
|
voice: "Voix",
|
|
13887
|
-
callConfig: "Appel vocal"
|
|
13910
|
+
callConfig: "Appel vocal",
|
|
13911
|
+
settings: "Paramètres"
|
|
13888
13912
|
},
|
|
13889
13913
|
mentorVoice: {
|
|
13890
13914
|
title: "Voix de l'agent",
|
|
@@ -13945,6 +13969,26 @@ var voiceTabLabels$2 = {
|
|
|
13945
13969
|
}
|
|
13946
13970
|
}
|
|
13947
13971
|
},
|
|
13972
|
+
transcription: {
|
|
13973
|
+
toggle: {
|
|
13974
|
+
label: "Dictée",
|
|
13975
|
+
tooltip: "Permet aux utilisateurs de parler dans le micro plutôt que d'écrire, et transforme en texte ce que l'agent entend. C'est l'inverse des réglages vocaux des autres sous-onglets : ceux-ci déterminent la voix de l'agent, celui-ci détermine sa capacité à comprendre ce qu'on lui dit.",
|
|
13976
|
+
helpText: "Une fois activée, un bouton micro apparaît dans la zone de discussion."
|
|
13977
|
+
},
|
|
13978
|
+
language: {
|
|
13979
|
+
label: "Langue parlée",
|
|
13980
|
+
tooltip: "La langue dans laquelle les utilisateurs vont parler. L'indiquer à l'avance rend la transcription nettement plus précise. Si vous ne la définissez pas, le fournisseur la devine à partir de l'audio.",
|
|
13981
|
+
placeholder: "Détecter automatiquement"
|
|
13982
|
+
},
|
|
13983
|
+
instructions: {
|
|
13984
|
+
label: "Indications de transcription",
|
|
13985
|
+
tooltip: "Les mots que la transcription risque d'écorcher : noms de produits, sigles, personnes, termes techniques. Les lister ici l'aide à les orthographier correctement.",
|
|
13986
|
+
placeholder: "ex. : Attendez-vous aux termes ibl.ai, LTI et Open edX. Orthographiez les noms tels quels.",
|
|
13987
|
+
helpText: "Facultatif. Certains fournisseurs de transcription utilisent ces indications ; les autres les ignorent tout simplement. Laissez vide en cas de doute."
|
|
13988
|
+
},
|
|
13989
|
+
saveButton: "Enregistrer la dictée",
|
|
13990
|
+
savingButton: "Enregistrement…"
|
|
13991
|
+
},
|
|
13948
13992
|
callConfig: {
|
|
13949
13993
|
title: "Appel vocal",
|
|
13950
13994
|
description: "Personnalisez le fonctionnement des appels vocaux. Le partage d'écran utilise toujours la conversation en direct.",
|
|
@@ -13996,7 +14040,9 @@ var voiceTabLabels$2 = {
|
|
|
13996
14040
|
voiceSaved: "Voix enregistrée",
|
|
13997
14041
|
voiceError: "Impossible d'enregistrer les paramètres vocaux",
|
|
13998
14042
|
callConfigSaved: "Paramètres d'appel vocal enregistrés",
|
|
13999
|
-
callConfigError: "Impossible d'enregistrer les paramètres d'appel vocal"
|
|
14043
|
+
callConfigError: "Impossible d'enregistrer les paramètres d'appel vocal",
|
|
14044
|
+
transcriptionSaved: "Paramètres de dictée enregistrés",
|
|
14045
|
+
transcriptionError: "Impossible d'enregistrer les paramètres de dictée"
|
|
14000
14046
|
}
|
|
14001
14047
|
};
|
|
14002
14048
|
var voiceTabVoicePicker$2 = {
|
|
@@ -20882,7 +20928,8 @@ var voiceTabLabels$1 = {
|
|
|
20882
20928
|
},
|
|
20883
20929
|
subTabs: {
|
|
20884
20930
|
voice: "Voz",
|
|
20885
|
-
callConfig: "Llamada de voz"
|
|
20931
|
+
callConfig: "Llamada de voz",
|
|
20932
|
+
settings: "Ajustes"
|
|
20886
20933
|
},
|
|
20887
20934
|
mentorVoice: {
|
|
20888
20935
|
title: "Voz del agente",
|
|
@@ -20943,6 +20990,26 @@ var voiceTabLabels$1 = {
|
|
|
20943
20990
|
}
|
|
20944
20991
|
}
|
|
20945
20992
|
},
|
|
20993
|
+
transcription: {
|
|
20994
|
+
toggle: {
|
|
20995
|
+
label: "Dictado",
|
|
20996
|
+
tooltip: "Permite que las personas hablen por el micrófono en lugar de escribir, y convierte en texto lo que el agente escucha. Es lo contrario de los ajustes de voz de las otras subpestañas: aquellos deciden cómo suena el agente, este decide qué tan bien entiende lo que se le dice.",
|
|
20997
|
+
helpText: "Cuando está activado, aparece un botón de micrófono en el cuadro de chat."
|
|
20998
|
+
},
|
|
20999
|
+
language: {
|
|
21000
|
+
label: "Idioma hablado",
|
|
21001
|
+
tooltip: "El idioma en el que hablarán las personas. Indicarlo de antemano hace que la transcripción sea notablemente más precisa. Si lo dejas sin definir, el proveedor lo deduce del audio.",
|
|
21002
|
+
placeholder: "Detectar automáticamente"
|
|
21003
|
+
},
|
|
21004
|
+
instructions: {
|
|
21005
|
+
label: "Sugerencias de transcripción",
|
|
21006
|
+
tooltip: "Palabras que la transcripción probablemente escriba mal: nombres de productos, siglas, personas, términos técnicos. Enumerarlas aquí ayuda a escribirlas correctamente.",
|
|
21007
|
+
placeholder: "p. ej. Espera los términos ibl.ai, LTI y Open edX. Escribe los nombres tal cual.",
|
|
21008
|
+
helpText: "Opcional. Algunos proveedores de transcripción usan estas sugerencias; los que no, simplemente las ignoran. Déjalo en blanco si tienes dudas."
|
|
21009
|
+
},
|
|
21010
|
+
saveButton: "Guardar dictado",
|
|
21011
|
+
savingButton: "Guardando…"
|
|
21012
|
+
},
|
|
20946
21013
|
callConfig: {
|
|
20947
21014
|
title: "Llamada de voz",
|
|
20948
21015
|
description: "Personaliza cómo funcionan las llamadas de voz. El uso compartido de pantalla siempre usa conversación en vivo.",
|
|
@@ -20994,7 +21061,9 @@ var voiceTabLabels$1 = {
|
|
|
20994
21061
|
voiceSaved: "Voz guardada",
|
|
20995
21062
|
voiceError: "No se pudo guardar la configuración de voz",
|
|
20996
21063
|
callConfigSaved: "Configuración de llamada de voz guardada",
|
|
20997
|
-
callConfigError: "No se pudo guardar la configuración de llamada de voz"
|
|
21064
|
+
callConfigError: "No se pudo guardar la configuración de llamada de voz",
|
|
21065
|
+
transcriptionSaved: "Ajustes de dictado guardados",
|
|
21066
|
+
transcriptionError: "No se pudieron guardar los ajustes de dictado"
|
|
20998
21067
|
}
|
|
20999
21068
|
};
|
|
21000
21069
|
var voiceTabVoicePicker$1 = {
|
|
@@ -27880,7 +27949,8 @@ var voiceTabLabels = {
|
|
|
27880
27949
|
},
|
|
27881
27950
|
subTabs: {
|
|
27882
27951
|
voice: "语音",
|
|
27883
|
-
callConfig: "语音通话"
|
|
27952
|
+
callConfig: "语音通话",
|
|
27953
|
+
settings: "设置"
|
|
27884
27954
|
},
|
|
27885
27955
|
mentorVoice: {
|
|
27886
27956
|
title: "智能体声音",
|
|
@@ -27941,6 +28011,26 @@ var voiceTabLabels = {
|
|
|
27941
28011
|
}
|
|
27942
28012
|
}
|
|
27943
28013
|
},
|
|
28014
|
+
transcription: {
|
|
28015
|
+
toggle: {
|
|
28016
|
+
label: "语音听写",
|
|
28017
|
+
tooltip: "让用户用麦克风说话而不是打字,并将智能体听到的内容转写为文字。这与其他子标签页的语音设置方向相反:那些决定智能体如何发声,这里决定它能多准确地听懂别人说的话。",
|
|
28018
|
+
helpText: "开启后,聊天框中会显示麦克风按钮。"
|
|
28019
|
+
},
|
|
28020
|
+
language: {
|
|
28021
|
+
label: "口语语言",
|
|
28022
|
+
tooltip: "用户将使用的语言。预先指定可以明显提高转写准确率。若不设置,服务商会根据音频自行判断。",
|
|
28023
|
+
placeholder: "自动检测"
|
|
28024
|
+
},
|
|
28025
|
+
instructions: {
|
|
28026
|
+
label: "转写提示",
|
|
28027
|
+
tooltip: "转写容易写错的词:产品名、缩写、人名、专业术语。在此列出可帮助它正确拼写。",
|
|
28028
|
+
placeholder: "例如:会出现 ibl.ai、LTI 和 Open edX 等术语。人名按原样拼写。",
|
|
28029
|
+
helpText: "选填。部分转写服务商会使用这些提示,不支持的则直接忽略。不确定时可留空。"
|
|
28030
|
+
},
|
|
28031
|
+
saveButton: "保存听写设置",
|
|
28032
|
+
savingButton: "保存中…"
|
|
28033
|
+
},
|
|
27944
28034
|
callConfig: {
|
|
27945
28035
|
title: "语音通话",
|
|
27946
28036
|
description: "自定义语音通话的工作方式。屏幕共享始终使用实时对话。",
|
|
@@ -27992,7 +28082,9 @@ var voiceTabLabels = {
|
|
|
27992
28082
|
voiceSaved: "声音已保存",
|
|
27993
28083
|
voiceError: "无法保存语音设置",
|
|
27994
28084
|
callConfigSaved: "语音通话设置已保存",
|
|
27995
|
-
callConfigError: "无法保存语音通话设置"
|
|
28085
|
+
callConfigError: "无法保存语音通话设置",
|
|
28086
|
+
transcriptionSaved: "听写设置已保存",
|
|
28087
|
+
transcriptionError: "无法保存听写设置"
|
|
27996
28088
|
}
|
|
27997
28089
|
};
|
|
27998
28090
|
var voiceTabVoicePicker = {
|
|
@@ -239096,6 +239188,7 @@ function ChatInputForm({ onSubmit, onScreenSharingClick, isScreenSharingModalOpe
|
|
|
239096
239188
|
const { handleMicrophoneBtnClick, processing, recording, time } = useVoiceChat({
|
|
239097
239189
|
sendMessage: handleSelectPrompt,
|
|
239098
239190
|
tenantKey,
|
|
239191
|
+
mentorId,
|
|
239099
239192
|
});
|
|
239100
239193
|
const attachedFiles = useSelector(selectAttachedFiles);
|
|
239101
239194
|
// Check if any files are currently uploading
|
|
@@ -242967,9 +243060,9 @@ function Shell({ brandName, showTopBar, showLogo, logoUrl, className, children,
|
|
|
242967
243060
|
const t = useT();
|
|
242968
243061
|
/** Platforms without a logo image 404; the broken img then hides itself. */
|
|
242969
243062
|
const [logoFailed, setLogoFailed] = useState(false);
|
|
242970
|
-
return (jsxs("div", { className: `min-h-dvh bg-background text-foreground ${className !== null && className !== void 0 ? className : ''}`, children: [showTopBar && (jsx("header", { className: "sticky top-0 z-10 border-b border-border bg-card/95 shadow-sm backdrop-blur", children: jsxs("div", { className: "
|
|
243063
|
+
return (jsxs("div", { className: `min-h-dvh bg-background text-foreground ${className !== null && className !== void 0 ? className : ''}`, children: [showTopBar && (jsx("header", { className: "sticky top-0 z-10 border-b border-border bg-card/95 shadow-sm backdrop-blur", children: jsxs("div", { className: "mx-auto flex h-14 w-full max-w-2xl items-center gap-3 px-4 sm:px-6", children: [showLogo && logoUrl && !logoFailed && (
|
|
242971
243064
|
// eslint-disable-next-line @next/next/no-img-element
|
|
242972
|
-
jsx("img", { src: logoUrl, alt: "", onError: () => setLogoFailed(true), className: "
|
|
243065
|
+
jsx("img", { src: logoUrl, alt: "", onError: () => setLogoFailed(true), className: "h-8 w-auto max-w-[30%] shrink-0 object-contain" })), jsx("span", { className: "min-w-0 truncate text-sm font-semibold text-foreground", title: brandName, children: brandName }), jsx("span", { className: "ml-auto shrink-0 text-sm text-muted-foreground", children: t('applyApplyWizard.application') })] }) })), jsx("main", { className: "mx-auto w-full max-w-2xl px-4 py-8 sm:px-6", children: children })] }));
|
|
242973
243066
|
}
|
|
242974
243067
|
|
|
242975
243068
|
/**
|
|
@@ -102265,7 +102265,8 @@ var voiceTabLabels$3 = {
|
|
|
102265
102265
|
},
|
|
102266
102266
|
subTabs: {
|
|
102267
102267
|
voice: "Voice",
|
|
102268
|
-
callConfig: "Voice
|
|
102268
|
+
callConfig: "Voice Call",
|
|
102269
|
+
settings: "Settings"
|
|
102269
102270
|
},
|
|
102270
102271
|
mentorVoice: {
|
|
102271
102272
|
title: "Agent Voice",
|
|
@@ -102326,6 +102327,26 @@ var voiceTabLabels$3 = {
|
|
|
102326
102327
|
}
|
|
102327
102328
|
}
|
|
102328
102329
|
},
|
|
102330
|
+
transcription: {
|
|
102331
|
+
toggle: {
|
|
102332
|
+
label: "Dictation",
|
|
102333
|
+
tooltip: "Lets people speak into the microphone instead of typing, and turns what the agent hears into text. This is the opposite of the voice settings on the other sub-tabs: those decide how the agent sounds, this decides how well it understands what is said to it.",
|
|
102334
|
+
helpText: "When on, a microphone button appears in the chat box."
|
|
102335
|
+
},
|
|
102336
|
+
language: {
|
|
102337
|
+
label: "Spoken language",
|
|
102338
|
+
tooltip: "The language people will speak in. Naming it up front makes transcription noticeably more accurate. Leave it unset and the provider guesses from the audio.",
|
|
102339
|
+
placeholder: "Detect automatically"
|
|
102340
|
+
},
|
|
102341
|
+
instructions: {
|
|
102342
|
+
label: "Transcription hints",
|
|
102343
|
+
tooltip: "Words the transcriber is likely to get wrong — product names, acronyms, people, technical terms. Listing them here helps it spell them correctly.",
|
|
102344
|
+
placeholder: "e.g. Expect the terms ibl.ai, LTI, and Open edX. Spell names as written.",
|
|
102345
|
+
helpText: "Optional. Some transcription providers use these hints; the ones that do not simply ignore them. Leave blank if you are not sure."
|
|
102346
|
+
},
|
|
102347
|
+
saveButton: "Save dictation",
|
|
102348
|
+
savingButton: "Saving…"
|
|
102349
|
+
},
|
|
102329
102350
|
callConfig: {
|
|
102330
102351
|
title: "Voice call",
|
|
102331
102352
|
description: "Customize how voice calls work. Screen sharing always uses live conversation.",
|
|
@@ -102377,7 +102398,9 @@ var voiceTabLabels$3 = {
|
|
|
102377
102398
|
voiceSaved: "Voice saved",
|
|
102378
102399
|
voiceError: "Couldn't save voice settings",
|
|
102379
102400
|
callConfigSaved: "Voice call settings saved",
|
|
102380
|
-
callConfigError: "Couldn't save voice call settings"
|
|
102401
|
+
callConfigError: "Couldn't save voice call settings",
|
|
102402
|
+
transcriptionSaved: "Dictation settings saved",
|
|
102403
|
+
transcriptionError: "Couldn't save dictation settings"
|
|
102381
102404
|
}
|
|
102382
102405
|
};
|
|
102383
102406
|
var voiceTabVoicePicker$3 = {
|
|
@@ -109429,7 +109452,8 @@ var voiceTabLabels$2 = {
|
|
|
109429
109452
|
},
|
|
109430
109453
|
subTabs: {
|
|
109431
109454
|
voice: "Voix",
|
|
109432
|
-
callConfig: "Appel vocal"
|
|
109455
|
+
callConfig: "Appel vocal",
|
|
109456
|
+
settings: "Paramètres"
|
|
109433
109457
|
},
|
|
109434
109458
|
mentorVoice: {
|
|
109435
109459
|
title: "Voix de l'agent",
|
|
@@ -109490,6 +109514,26 @@ var voiceTabLabels$2 = {
|
|
|
109490
109514
|
}
|
|
109491
109515
|
}
|
|
109492
109516
|
},
|
|
109517
|
+
transcription: {
|
|
109518
|
+
toggle: {
|
|
109519
|
+
label: "Dictée",
|
|
109520
|
+
tooltip: "Permet aux utilisateurs de parler dans le micro plutôt que d'écrire, et transforme en texte ce que l'agent entend. C'est l'inverse des réglages vocaux des autres sous-onglets : ceux-ci déterminent la voix de l'agent, celui-ci détermine sa capacité à comprendre ce qu'on lui dit.",
|
|
109521
|
+
helpText: "Une fois activée, un bouton micro apparaît dans la zone de discussion."
|
|
109522
|
+
},
|
|
109523
|
+
language: {
|
|
109524
|
+
label: "Langue parlée",
|
|
109525
|
+
tooltip: "La langue dans laquelle les utilisateurs vont parler. L'indiquer à l'avance rend la transcription nettement plus précise. Si vous ne la définissez pas, le fournisseur la devine à partir de l'audio.",
|
|
109526
|
+
placeholder: "Détecter automatiquement"
|
|
109527
|
+
},
|
|
109528
|
+
instructions: {
|
|
109529
|
+
label: "Indications de transcription",
|
|
109530
|
+
tooltip: "Les mots que la transcription risque d'écorcher : noms de produits, sigles, personnes, termes techniques. Les lister ici l'aide à les orthographier correctement.",
|
|
109531
|
+
placeholder: "ex. : Attendez-vous aux termes ibl.ai, LTI et Open edX. Orthographiez les noms tels quels.",
|
|
109532
|
+
helpText: "Facultatif. Certains fournisseurs de transcription utilisent ces indications ; les autres les ignorent tout simplement. Laissez vide en cas de doute."
|
|
109533
|
+
},
|
|
109534
|
+
saveButton: "Enregistrer la dictée",
|
|
109535
|
+
savingButton: "Enregistrement…"
|
|
109536
|
+
},
|
|
109493
109537
|
callConfig: {
|
|
109494
109538
|
title: "Appel vocal",
|
|
109495
109539
|
description: "Personnalisez le fonctionnement des appels vocaux. Le partage d'écran utilise toujours la conversation en direct.",
|
|
@@ -109541,7 +109585,9 @@ var voiceTabLabels$2 = {
|
|
|
109541
109585
|
voiceSaved: "Voix enregistrée",
|
|
109542
109586
|
voiceError: "Impossible d'enregistrer les paramètres vocaux",
|
|
109543
109587
|
callConfigSaved: "Paramètres d'appel vocal enregistrés",
|
|
109544
|
-
callConfigError: "Impossible d'enregistrer les paramètres d'appel vocal"
|
|
109588
|
+
callConfigError: "Impossible d'enregistrer les paramètres d'appel vocal",
|
|
109589
|
+
transcriptionSaved: "Paramètres de dictée enregistrés",
|
|
109590
|
+
transcriptionError: "Impossible d'enregistrer les paramètres de dictée"
|
|
109545
109591
|
}
|
|
109546
109592
|
};
|
|
109547
109593
|
var voiceTabVoicePicker$2 = {
|
|
@@ -116427,7 +116473,8 @@ var voiceTabLabels$1 = {
|
|
|
116427
116473
|
},
|
|
116428
116474
|
subTabs: {
|
|
116429
116475
|
voice: "Voz",
|
|
116430
|
-
callConfig: "Llamada de voz"
|
|
116476
|
+
callConfig: "Llamada de voz",
|
|
116477
|
+
settings: "Ajustes"
|
|
116431
116478
|
},
|
|
116432
116479
|
mentorVoice: {
|
|
116433
116480
|
title: "Voz del agente",
|
|
@@ -116488,6 +116535,26 @@ var voiceTabLabels$1 = {
|
|
|
116488
116535
|
}
|
|
116489
116536
|
}
|
|
116490
116537
|
},
|
|
116538
|
+
transcription: {
|
|
116539
|
+
toggle: {
|
|
116540
|
+
label: "Dictado",
|
|
116541
|
+
tooltip: "Permite que las personas hablen por el micrófono en lugar de escribir, y convierte en texto lo que el agente escucha. Es lo contrario de los ajustes de voz de las otras subpestañas: aquellos deciden cómo suena el agente, este decide qué tan bien entiende lo que se le dice.",
|
|
116542
|
+
helpText: "Cuando está activado, aparece un botón de micrófono en el cuadro de chat."
|
|
116543
|
+
},
|
|
116544
|
+
language: {
|
|
116545
|
+
label: "Idioma hablado",
|
|
116546
|
+
tooltip: "El idioma en el que hablarán las personas. Indicarlo de antemano hace que la transcripción sea notablemente más precisa. Si lo dejas sin definir, el proveedor lo deduce del audio.",
|
|
116547
|
+
placeholder: "Detectar automáticamente"
|
|
116548
|
+
},
|
|
116549
|
+
instructions: {
|
|
116550
|
+
label: "Sugerencias de transcripción",
|
|
116551
|
+
tooltip: "Palabras que la transcripción probablemente escriba mal: nombres de productos, siglas, personas, términos técnicos. Enumerarlas aquí ayuda a escribirlas correctamente.",
|
|
116552
|
+
placeholder: "p. ej. Espera los términos ibl.ai, LTI y Open edX. Escribe los nombres tal cual.",
|
|
116553
|
+
helpText: "Opcional. Algunos proveedores de transcripción usan estas sugerencias; los que no, simplemente las ignoran. Déjalo en blanco si tienes dudas."
|
|
116554
|
+
},
|
|
116555
|
+
saveButton: "Guardar dictado",
|
|
116556
|
+
savingButton: "Guardando…"
|
|
116557
|
+
},
|
|
116491
116558
|
callConfig: {
|
|
116492
116559
|
title: "Llamada de voz",
|
|
116493
116560
|
description: "Personaliza cómo funcionan las llamadas de voz. El uso compartido de pantalla siempre usa conversación en vivo.",
|
|
@@ -116539,7 +116606,9 @@ var voiceTabLabels$1 = {
|
|
|
116539
116606
|
voiceSaved: "Voz guardada",
|
|
116540
116607
|
voiceError: "No se pudo guardar la configuración de voz",
|
|
116541
116608
|
callConfigSaved: "Configuración de llamada de voz guardada",
|
|
116542
|
-
callConfigError: "No se pudo guardar la configuración de llamada de voz"
|
|
116609
|
+
callConfigError: "No se pudo guardar la configuración de llamada de voz",
|
|
116610
|
+
transcriptionSaved: "Ajustes de dictado guardados",
|
|
116611
|
+
transcriptionError: "No se pudieron guardar los ajustes de dictado"
|
|
116543
116612
|
}
|
|
116544
116613
|
};
|
|
116545
116614
|
var voiceTabVoicePicker$1 = {
|
|
@@ -123425,7 +123494,8 @@ var voiceTabLabels = {
|
|
|
123425
123494
|
},
|
|
123426
123495
|
subTabs: {
|
|
123427
123496
|
voice: "语音",
|
|
123428
|
-
callConfig: "语音通话"
|
|
123497
|
+
callConfig: "语音通话",
|
|
123498
|
+
settings: "设置"
|
|
123429
123499
|
},
|
|
123430
123500
|
mentorVoice: {
|
|
123431
123501
|
title: "智能体声音",
|
|
@@ -123486,6 +123556,26 @@ var voiceTabLabels = {
|
|
|
123486
123556
|
}
|
|
123487
123557
|
}
|
|
123488
123558
|
},
|
|
123559
|
+
transcription: {
|
|
123560
|
+
toggle: {
|
|
123561
|
+
label: "语音听写",
|
|
123562
|
+
tooltip: "让用户用麦克风说话而不是打字,并将智能体听到的内容转写为文字。这与其他子标签页的语音设置方向相反:那些决定智能体如何发声,这里决定它能多准确地听懂别人说的话。",
|
|
123563
|
+
helpText: "开启后,聊天框中会显示麦克风按钮。"
|
|
123564
|
+
},
|
|
123565
|
+
language: {
|
|
123566
|
+
label: "口语语言",
|
|
123567
|
+
tooltip: "用户将使用的语言。预先指定可以明显提高转写准确率。若不设置,服务商会根据音频自行判断。",
|
|
123568
|
+
placeholder: "自动检测"
|
|
123569
|
+
},
|
|
123570
|
+
instructions: {
|
|
123571
|
+
label: "转写提示",
|
|
123572
|
+
tooltip: "转写容易写错的词:产品名、缩写、人名、专业术语。在此列出可帮助它正确拼写。",
|
|
123573
|
+
placeholder: "例如:会出现 ibl.ai、LTI 和 Open edX 等术语。人名按原样拼写。",
|
|
123574
|
+
helpText: "选填。部分转写服务商会使用这些提示,不支持的则直接忽略。不确定时可留空。"
|
|
123575
|
+
},
|
|
123576
|
+
saveButton: "保存听写设置",
|
|
123577
|
+
savingButton: "保存中…"
|
|
123578
|
+
},
|
|
123489
123579
|
callConfig: {
|
|
123490
123580
|
title: "语音通话",
|
|
123491
123581
|
description: "自定义语音通话的工作方式。屏幕共享始终使用实时对话。",
|
|
@@ -123537,7 +123627,9 @@ var voiceTabLabels = {
|
|
|
123537
123627
|
voiceSaved: "声音已保存",
|
|
123538
123628
|
voiceError: "无法保存语音设置",
|
|
123539
123629
|
callConfigSaved: "语音通话设置已保存",
|
|
123540
|
-
callConfigError: "无法保存语音通话设置"
|
|
123630
|
+
callConfigError: "无法保存语音通话设置",
|
|
123631
|
+
transcriptionSaved: "听写设置已保存",
|
|
123632
|
+
transcriptionError: "无法保存听写设置"
|
|
123541
123633
|
}
|
|
123542
123634
|
};
|
|
123543
123635
|
var voiceTabVoicePicker = {
|
|
@@ -261873,6 +261965,7 @@ function ChatInputForm({ onSubmit, onScreenSharingClick, isScreenSharingModalOpe
|
|
|
261873
261965
|
const { handleMicrophoneBtnClick, processing, recording, time } = useVoiceChat({
|
|
261874
261966
|
sendMessage: handleSelectPrompt,
|
|
261875
261967
|
tenantKey,
|
|
261968
|
+
mentorId,
|
|
261876
261969
|
});
|
|
261877
261970
|
const attachedFiles = useSelector(selectAttachedFiles);
|
|
261878
261971
|
// Check if any files are currently uploading
|
|
@@ -273782,7 +273875,8 @@ const AGENT_VOICE_TAB_LABELS = {
|
|
|
273782
273875
|
},
|
|
273783
273876
|
subTabs: {
|
|
273784
273877
|
voice: 'Voice',
|
|
273785
|
-
callConfig: 'Voice
|
|
273878
|
+
callConfig: 'Voice Call',
|
|
273879
|
+
settings: 'Settings',
|
|
273786
273880
|
},
|
|
273787
273881
|
mentorVoice: {
|
|
273788
273882
|
title: 'Agent Voice',
|
|
@@ -273840,6 +273934,26 @@ const AGENT_VOICE_TAB_LABELS = {
|
|
|
273840
273934
|
},
|
|
273841
273935
|
},
|
|
273842
273936
|
},
|
|
273937
|
+
transcription: {
|
|
273938
|
+
toggle: {
|
|
273939
|
+
label: 'Dictation',
|
|
273940
|
+
tooltip: 'Lets people speak into the microphone instead of typing, and turns what the agent hears into text. This is the opposite of the voice settings on the other sub-tabs: those decide how the agent sounds, this decides how well it understands what is said to it.',
|
|
273941
|
+
helpText: 'When on, a microphone button appears in the chat box.',
|
|
273942
|
+
},
|
|
273943
|
+
language: {
|
|
273944
|
+
label: 'Spoken language',
|
|
273945
|
+
tooltip: 'The language people will speak in. Naming it up front makes transcription noticeably more accurate. Leave it unset and the provider guesses from the audio.',
|
|
273946
|
+
placeholder: 'Detect automatically',
|
|
273947
|
+
},
|
|
273948
|
+
instructions: {
|
|
273949
|
+
label: 'Transcription hints',
|
|
273950
|
+
tooltip: 'Words the transcriber is likely to get wrong — product names, acronyms, people, technical terms. Listing them here helps it spell them correctly.',
|
|
273951
|
+
placeholder: 'e.g. Expect the terms ibl.ai, LTI, and Open edX. Spell names as written.',
|
|
273952
|
+
helpText: 'Optional. Some transcription providers use these hints; the ones that do not simply ignore them. Leave blank if you are not sure.',
|
|
273953
|
+
},
|
|
273954
|
+
saveButton: 'Save dictation',
|
|
273955
|
+
savingButton: 'Saving…',
|
|
273956
|
+
},
|
|
273843
273957
|
callConfig: {
|
|
273844
273958
|
title: 'Voice call',
|
|
273845
273959
|
description: 'Customize how voice calls work. Screen sharing always uses live conversation.',
|
|
@@ -273891,6 +274005,8 @@ const AGENT_VOICE_TAB_LABELS = {
|
|
|
273891
274005
|
voiceError: "Couldn't save voice settings",
|
|
273892
274006
|
callConfigSaved: 'Voice call settings saved',
|
|
273893
274007
|
callConfigError: "Couldn't save voice call settings",
|
|
274008
|
+
transcriptionSaved: 'Dictation settings saved',
|
|
274009
|
+
transcriptionError: "Couldn't save dictation settings",
|
|
273894
274010
|
},
|
|
273895
274011
|
};
|
|
273896
274012
|
function buildVoiceTabLabels(t) {
|
|
@@ -273907,6 +274023,7 @@ function buildVoiceTabLabels(t) {
|
|
|
273907
274023
|
subTabs: {
|
|
273908
274024
|
voice: t('voiceTabLabels.subTabs.voice'),
|
|
273909
274025
|
callConfig: t('voiceTabLabels.subTabs.callConfig'),
|
|
274026
|
+
settings: t('voiceTabLabels.subTabs.settings'),
|
|
273910
274027
|
},
|
|
273911
274028
|
mentorVoice: {
|
|
273912
274029
|
title: t('voiceTabLabels.mentorVoice.title'),
|
|
@@ -273966,6 +274083,26 @@ function buildVoiceTabLabels(t) {
|
|
|
273966
274083
|
},
|
|
273967
274084
|
},
|
|
273968
274085
|
},
|
|
274086
|
+
transcription: {
|
|
274087
|
+
toggle: {
|
|
274088
|
+
label: t('voiceTabLabels.transcription.toggle.label'),
|
|
274089
|
+
tooltip: t('voiceTabLabels.transcription.toggle.tooltip'),
|
|
274090
|
+
helpText: t('voiceTabLabels.transcription.toggle.helpText'),
|
|
274091
|
+
},
|
|
274092
|
+
language: {
|
|
274093
|
+
label: t('voiceTabLabels.transcription.language.label'),
|
|
274094
|
+
tooltip: t('voiceTabLabels.transcription.language.tooltip'),
|
|
274095
|
+
placeholder: t('voiceTabLabels.transcription.language.placeholder'),
|
|
274096
|
+
},
|
|
274097
|
+
instructions: {
|
|
274098
|
+
label: t('voiceTabLabels.transcription.instructions.label'),
|
|
274099
|
+
tooltip: t('voiceTabLabels.transcription.instructions.tooltip'),
|
|
274100
|
+
placeholder: t('voiceTabLabels.transcription.instructions.placeholder'),
|
|
274101
|
+
helpText: t('voiceTabLabels.transcription.instructions.helpText'),
|
|
274102
|
+
},
|
|
274103
|
+
saveButton: t('voiceTabLabels.transcription.saveButton'),
|
|
274104
|
+
savingButton: t('voiceTabLabels.transcription.savingButton'),
|
|
274105
|
+
},
|
|
273969
274106
|
callConfig: {
|
|
273970
274107
|
title: t('voiceTabLabels.callConfig.title'),
|
|
273971
274108
|
description: t('voiceTabLabels.callConfig.description'),
|
|
@@ -274018,6 +274155,8 @@ function buildVoiceTabLabels(t) {
|
|
|
274018
274155
|
voiceError: t('voiceTabLabels.toasts.voiceError'),
|
|
274019
274156
|
callConfigSaved: t('voiceTabLabels.toasts.callConfigSaved'),
|
|
274020
274157
|
callConfigError: t('voiceTabLabels.toasts.callConfigError'),
|
|
274158
|
+
transcriptionSaved: t('voiceTabLabels.toasts.transcriptionSaved'),
|
|
274159
|
+
transcriptionError: t('voiceTabLabels.toasts.transcriptionError'),
|
|
274021
274160
|
},
|
|
274022
274161
|
};
|
|
274023
274162
|
}
|
|
@@ -274577,6 +274716,39 @@ function FieldWrap({ label, tooltip, children }) {
|
|
|
274577
274716
|
return (jsxs("div", { className: "space-y-2", children: [jsxs("div", { className: "flex items-center gap-2", children: [jsx(Label$1, { className: "text-sm font-medium text-[#646464]", children: label }), tooltip && (jsx(TooltipProvider, { children: jsxs(Tooltip$1, { children: [jsx(TooltipTrigger, { type: "button", "aria-label": t('voiceTabCallConfigSection.moreInfoAbout', { label }), children: jsx(Info$3, { className: "h-4 w-4 text-gray-400" }) }), jsx(TooltipContent, { side: "top", align: "start", sideOffset: 6, collisionPadding: 16, className: "ibl-tooltip-content z-50 max-w-[300px]", children: jsx("p", { className: "text-xs leading-relaxed whitespace-normal", children: tooltip }) })] }) }))] }), children] }));
|
|
274578
274717
|
}
|
|
274579
274718
|
|
|
274719
|
+
/**
|
|
274720
|
+
* Languages offered for **speech-to-text** (dictation) transcription.
|
|
274721
|
+
*
|
|
274722
|
+
* Deliberately separate from `LANGUAGE_OPTIONS` in `call-config-section.tsx`,
|
|
274723
|
+
* which is the realtime *voice call* list and carries different provider
|
|
274724
|
+
* constraints. These 17 are the major languages the backend confirms are safe
|
|
274725
|
+
* across all four transcription providers — do not reorder or prune without a
|
|
274726
|
+
* backend change.
|
|
274727
|
+
*
|
|
274728
|
+
* Display names are the English endonym-free common names, hardcoded here the
|
|
274729
|
+
* same way the neighbouring realtime `LANGUAGE_OPTIONS` list does it — a
|
|
274730
|
+
* 17-entry translation layer per locale buys nothing an admin would notice.
|
|
274731
|
+
*/
|
|
274732
|
+
const TRANSCRIPTION_LANGUAGE_OPTIONS = [
|
|
274733
|
+
{ value: 'en', label: 'English' },
|
|
274734
|
+
{ value: 'es', label: 'Spanish' },
|
|
274735
|
+
{ value: 'fr', label: 'French' },
|
|
274736
|
+
{ value: 'de', label: 'German' },
|
|
274737
|
+
{ value: 'pt', label: 'Portuguese' },
|
|
274738
|
+
{ value: 'it', label: 'Italian' },
|
|
274739
|
+
{ value: 'nl', label: 'Dutch' },
|
|
274740
|
+
{ value: 'sv', label: 'Swedish' },
|
|
274741
|
+
{ value: 'pl', label: 'Polish' },
|
|
274742
|
+
{ value: 'tr', label: 'Turkish' },
|
|
274743
|
+
{ value: 'ru', label: 'Russian' },
|
|
274744
|
+
{ value: 'ar', label: 'Arabic' },
|
|
274745
|
+
{ value: 'hi', label: 'Hindi' },
|
|
274746
|
+
{ value: 'ja', label: 'Japanese' },
|
|
274747
|
+
{ value: 'ko', label: 'Korean' },
|
|
274748
|
+
{ value: 'zh', label: 'Chinese' },
|
|
274749
|
+
{ value: 'la', label: 'Latin' },
|
|
274750
|
+
];
|
|
274751
|
+
|
|
274580
274752
|
/**
|
|
274581
274753
|
* Display-only card for a single prompt. Mirrors the visual pattern
|
|
274582
274754
|
* used by `AgentPromptsTab` (System Prompt / Proactive Prompt cards):
|
|
@@ -274616,13 +274788,31 @@ function usesVoiceCatalogue(provider) {
|
|
|
274616
274788
|
const SUB_TAB_VALUES = {
|
|
274617
274789
|
voice: 'voice',
|
|
274618
274790
|
callConfig: 'call-config',
|
|
274791
|
+
settings: 'settings',
|
|
274619
274792
|
};
|
|
274793
|
+
/**
|
|
274794
|
+
* Reverse of `SUB_TAB_VALUES`. `<Tabs>` is controlled here (the pinned save
|
|
274795
|
+
* footer needs to know which sub-tab is open), and it hands back the Radix
|
|
274796
|
+
* *value*, which we map back to the `SubTab` key we hold in state.
|
|
274797
|
+
*/
|
|
274798
|
+
const SUB_TAB_KEYS = Object.fromEntries(Object.entries(SUB_TAB_VALUES).map(([key, value]) => [value, key]));
|
|
274620
274799
|
/**
|
|
274621
274800
|
* Soft cap for the voice-instructions textarea. The backend column is an
|
|
274622
274801
|
* unbounded TextField — this is purely a UI guardrail (TTS style prompts
|
|
274623
274802
|
* gain nothing from being longer than this).
|
|
274624
274803
|
*/
|
|
274625
274804
|
const VOICE_INSTRUCTIONS_MAX = 1000;
|
|
274805
|
+
/**
|
|
274806
|
+
* Soft cap for the transcription-hints textarea. Same reasoning as
|
|
274807
|
+
* `VOICE_INSTRUCTIONS_MAX`: the backend column is unbounded, but a hint list
|
|
274808
|
+
* longer than this stops helping the transcriber and starts costing tokens.
|
|
274809
|
+
*/
|
|
274810
|
+
const TRANSCRIPTION_INSTRUCTIONS_MAX = 1000;
|
|
274811
|
+
/**
|
|
274812
|
+
* `<Select>` cannot hold an empty-string item value, so the "not set" choice
|
|
274813
|
+
* needs a sentinel. It is mapped back to `''` before anything is sent.
|
|
274814
|
+
*/
|
|
274815
|
+
const TRANSCRIPTION_LANGUAGE_UNSET = '__unset__';
|
|
274626
274816
|
/**
|
|
274627
274817
|
* Pull a voice **name** out of the mentor settings response, which can
|
|
274628
274818
|
* return a plain string, a numeric id, or a serialized object with a
|
|
@@ -274639,7 +274829,7 @@ function readVoiceName(value) {
|
|
|
274639
274829
|
return null;
|
|
274640
274830
|
}
|
|
274641
274831
|
function AgentVoiceTab({ labels: labelsOverride, defaultSubTab = 'voice', renderPromptContent, tenantKey: tenantKeyProp, mentorId: mentorIdProp, username: usernameProp, enableRBAC: enableRBACProp, }) {
|
|
274642
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r;
|
|
274832
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u;
|
|
274643
274833
|
const ctx = useAgentSettingsOptional();
|
|
274644
274834
|
const tenantKey = (_a = tenantKeyProp !== null && tenantKeyProp !== void 0 ? tenantKeyProp : ctx === null || ctx === void 0 ? void 0 : ctx.tenantKey) !== null && _a !== void 0 ? _a : '';
|
|
274645
274835
|
const mentorId = (_b = mentorIdProp !== null && mentorIdProp !== void 0 ? mentorIdProp : ctx === null || ctx === void 0 ? void 0 : ctx.mentorId) !== null && _b !== void 0 ? _b : '';
|
|
@@ -274684,6 +274874,14 @@ function AgentVoiceTab({ labels: labelsOverride, defaultSubTab = 'voice', render
|
|
|
274684
274874
|
name: savedIblaiName,
|
|
274685
274875
|
});
|
|
274686
274876
|
const savedInstructions = typeof (mentorSettings === null || mentorSettings === void 0 ? void 0 : mentorSettings.voice_instructions) === 'string' ? mentorSettings.voice_instructions : '';
|
|
274877
|
+
// Transcription (speech-to-text) — an unset language is a first-class
|
|
274878
|
+
// state, so it stays `''` rather than defaulting to English.
|
|
274879
|
+
const savedTranscriptionLanguage = typeof (mentorSettings === null || mentorSettings === void 0 ? void 0 : mentorSettings.transcription_language) === 'string'
|
|
274880
|
+
? mentorSettings.transcription_language
|
|
274881
|
+
: '';
|
|
274882
|
+
const savedTranscriptionInstructions = typeof (mentorSettings === null || mentorSettings === void 0 ? void 0 : mentorSettings.transcription_instructions) === 'string'
|
|
274883
|
+
? mentorSettings.transcription_instructions
|
|
274884
|
+
: '';
|
|
274687
274885
|
// Picked voices override the resolved server values once the user
|
|
274688
274886
|
// makes a choice. Null means "use what came from the server".
|
|
274689
274887
|
const [provider, setProvider] = React__default.useState(initialProvider);
|
|
@@ -274691,13 +274889,20 @@ function AgentVoiceTab({ labels: labelsOverride, defaultSubTab = 'voice', render
|
|
|
274691
274889
|
const [pickedGoogleVoice, setPickedGoogleVoice] = React__default.useState(null);
|
|
274692
274890
|
const [pickedIblaiVoice, setPickedIblaiVoice] = React__default.useState(null);
|
|
274693
274891
|
const [instructions, setInstructions] = React__default.useState(savedInstructions);
|
|
274892
|
+
const [transcriptionLanguage, setTranscriptionLanguage] = React__default.useState(savedTranscriptionLanguage);
|
|
274893
|
+
const [transcriptionInstructions, setTranscriptionInstructions] = React__default.useState(savedTranscriptionInstructions);
|
|
274694
274894
|
const [selectedPrompt, setSelectedPrompt] = React__default.useState(null);
|
|
274895
|
+
// Controlled so the pinned footer below the scroll area knows which
|
|
274896
|
+
// sub-tab's Save it should be rendering.
|
|
274897
|
+
const [subTab, setSubTab] = React__default.useState(defaultSubTab);
|
|
274695
274898
|
React__default.useEffect(() => {
|
|
274696
274899
|
setProvider(initialProvider);
|
|
274697
274900
|
setPickedOpenaiVoice(null);
|
|
274698
274901
|
setPickedGoogleVoice(null);
|
|
274699
274902
|
setPickedIblaiVoice(null);
|
|
274700
274903
|
setInstructions(savedInstructions);
|
|
274904
|
+
setTranscriptionLanguage(savedTranscriptionLanguage);
|
|
274905
|
+
setTranscriptionInstructions(savedTranscriptionInstructions);
|
|
274701
274906
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
274702
274907
|
}, [mentorId, rawMentorSettings]);
|
|
274703
274908
|
const effectiveOpenaiVoice = (_j = pickedOpenaiVoice !== null && pickedOpenaiVoice !== void 0 ? pickedOpenaiVoice : resolvedOpenaiVoice) !== null && _j !== void 0 ? _j : null;
|
|
@@ -274735,11 +274940,46 @@ function AgentVoiceTab({ labels: labelsOverride, defaultSubTab = 'voice', render
|
|
|
274735
274940
|
setIsTogglingVoiceCall(false);
|
|
274736
274941
|
}
|
|
274737
274942
|
};
|
|
274943
|
+
// "Dictation" master toggle. Tracked separately from the voice-call
|
|
274944
|
+
// toggle — sharing `isTogglingVoiceCall` would make flipping one switch
|
|
274945
|
+
// disable the other.
|
|
274946
|
+
const serverVoiceRecordEnabled = (_o = mentorSettings === null || mentorSettings === void 0 ? void 0 : mentorSettings.show_voice_record) !== null && _o !== void 0 ? _o : true;
|
|
274947
|
+
const [voiceRecordEnabled, setVoiceRecordEnabled] = React__default.useState(serverVoiceRecordEnabled);
|
|
274948
|
+
const [isTogglingVoiceRecord, setIsTogglingVoiceRecord] = React__default.useState(false);
|
|
274949
|
+
React__default.useEffect(() => {
|
|
274950
|
+
setVoiceRecordEnabled(serverVoiceRecordEnabled);
|
|
274951
|
+
}, [serverVoiceRecordEnabled]);
|
|
274952
|
+
const handleToggleVoiceRecord = async (checked) => {
|
|
274953
|
+
setVoiceRecordEnabled(checked); // optimistic
|
|
274954
|
+
setIsTogglingVoiceRecord(true);
|
|
274955
|
+
try {
|
|
274956
|
+
await editMentor({
|
|
274957
|
+
mentor: mentorId,
|
|
274958
|
+
org: tenantKey,
|
|
274959
|
+
// @ts-expect-error userId is accepted at runtime
|
|
274960
|
+
userId: username,
|
|
274961
|
+
formData: { show_voice_record: checked },
|
|
274962
|
+
}).unwrap();
|
|
274963
|
+
toast.success(labels.toasts.transcriptionSaved);
|
|
274964
|
+
}
|
|
274965
|
+
catch (error) {
|
|
274966
|
+
console.error('[AgentVoiceTab] toggle dictation error', error);
|
|
274967
|
+
setVoiceRecordEnabled(!checked); // roll back
|
|
274968
|
+
toast.error(labels.toasts.transcriptionError);
|
|
274969
|
+
}
|
|
274970
|
+
finally {
|
|
274971
|
+
setIsTogglingVoiceRecord(false);
|
|
274972
|
+
}
|
|
274973
|
+
};
|
|
274738
274974
|
const isDisabled = isMentorSettingsLoading || isSavingMentor;
|
|
274739
274975
|
const instructionsDirty = instructions !== savedInstructions;
|
|
274740
274976
|
// Soft cap only — the modal editor doesn't enforce a max length, so we
|
|
274741
274977
|
// block Save instead of truncating what the user wrote.
|
|
274742
274978
|
const instructionsOverCap = instructions.length > VOICE_INSTRUCTIONS_MAX;
|
|
274979
|
+
const transcriptionLanguageDirty = transcriptionLanguage !== savedTranscriptionLanguage;
|
|
274980
|
+
const transcriptionInstructionsDirty = transcriptionInstructions !== savedTranscriptionInstructions;
|
|
274981
|
+
const transcriptionOverCap = transcriptionInstructions.length > TRANSCRIPTION_INSTRUCTIONS_MAX;
|
|
274982
|
+
const transcriptionDirty = transcriptionLanguageDirty || transcriptionInstructionsDirty;
|
|
274743
274983
|
const isDirty = provider !== initialProvider ||
|
|
274744
274984
|
pickedOpenaiVoice != null ||
|
|
274745
274985
|
pickedGoogleVoice != null ||
|
|
@@ -274820,6 +275060,31 @@ function AgentVoiceTab({ labels: labelsOverride, defaultSubTab = 'voice', render
|
|
|
274820
275060
|
toast.error(labels.toasts.voiceError);
|
|
274821
275061
|
}
|
|
274822
275062
|
};
|
|
275063
|
+
const handleSaveTranscription = async () => {
|
|
275064
|
+
try {
|
|
275065
|
+
// Same "absent = keep" contract as the voice save above: only send
|
|
275066
|
+
// what the admin actually touched.
|
|
275067
|
+
const formData = {};
|
|
275068
|
+
if (transcriptionLanguageDirty) {
|
|
275069
|
+
formData.transcription_language = transcriptionLanguage;
|
|
275070
|
+
}
|
|
275071
|
+
if (transcriptionInstructionsDirty) {
|
|
275072
|
+
formData.transcription_instructions = transcriptionInstructions;
|
|
275073
|
+
}
|
|
275074
|
+
await editMentor({
|
|
275075
|
+
mentor: mentorId,
|
|
275076
|
+
org: tenantKey,
|
|
275077
|
+
// @ts-expect-error userId is accepted at runtime
|
|
275078
|
+
userId: username,
|
|
275079
|
+
formData,
|
|
275080
|
+
}).unwrap();
|
|
275081
|
+
toast.success(labels.toasts.transcriptionSaved);
|
|
275082
|
+
}
|
|
275083
|
+
catch (error) {
|
|
275084
|
+
console.error('[AgentVoiceTab] save transcription error', error);
|
|
275085
|
+
toast.error(labels.toasts.transcriptionError);
|
|
275086
|
+
}
|
|
275087
|
+
};
|
|
274823
275088
|
// Only `browser` has no voice to show -- it uses the listener's OS voice.
|
|
274824
275089
|
const selectedVoice = provider === 'openai'
|
|
274825
275090
|
? effectiveOpenaiVoice
|
|
@@ -274843,47 +275108,51 @@ function AgentVoiceTab({ labels: labelsOverride, defaultSubTab = 'voice', render
|
|
|
274843
275108
|
return renderPromptContent(text);
|
|
274844
275109
|
return jsx("p", { className: "text-sm whitespace-pre-wrap text-gray-700", children: text });
|
|
274845
275110
|
};
|
|
274846
|
-
return (jsxs(Fragment$1, { children: [jsx("div", { className: "flex h-[73px] flex-shrink-0 items-center border-b border-gray-200 bg-white p-4 lg:block", children: jsxs("div", { children: [jsx("h3", { className: "mb-1 text-base font-medium text-gray-900", children: labels.header.title }), jsx("p", { className: "text-xs text-gray-600", children: labels.header.description })] }) }), jsx("div", { className: "flex-1 space-y-4 p-3 lg:p-4", style: { overflowY: 'auto', overflowX: 'hidden' }, "data-testid": "voice-tab-body", children: isMentorSettingsLoading ? (jsx("div", { className: "flex items-center justify-center py-12", "data-testid": "voice-tab-loading", children: jsx(Spinner, {}) })) : (jsxs(CapabilityGate, { title: labels.capability.title, description: labels.capability.description, offHint: labels.capability.offHint, enabled: voiceCallEnabled, onToggle: handleToggleVoiceCall, disabled: isDisabled || isTogglingVoiceCall, ariaLabel: labels.capability.title, toggleTestId: "voice-capability-toggle", children: [jsxs(Tabs, {
|
|
274847
|
-
|
|
274848
|
-
|
|
274849
|
-
|
|
274850
|
-
|
|
274851
|
-
|
|
274852
|
-
|
|
274853
|
-
|
|
274854
|
-
|
|
274855
|
-
|
|
274856
|
-
|
|
274857
|
-
|
|
274858
|
-
|
|
274859
|
-
|
|
274860
|
-
|
|
274861
|
-
|
|
274862
|
-
|
|
274863
|
-
|
|
274864
|
-
|
|
274865
|
-
|
|
274866
|
-
|
|
274867
|
-
|
|
274868
|
-
|
|
274869
|
-
|
|
274870
|
-
|
|
274871
|
-
|
|
274872
|
-
|
|
274873
|
-
|
|
274874
|
-
|
|
274875
|
-
|
|
274876
|
-
|
|
274877
|
-
|
|
274878
|
-
|
|
274879
|
-
|
|
274880
|
-
|
|
274881
|
-
|
|
274882
|
-
|
|
274883
|
-
|
|
274884
|
-
|
|
274885
|
-
setSelectedPrompt(null)
|
|
274886
|
-
|
|
275111
|
+
return (jsxs(Fragment$1, { children: [jsx("div", { className: "flex h-[73px] flex-shrink-0 items-center border-b border-gray-200 bg-white p-4 lg:block", children: jsxs("div", { children: [jsx("h3", { className: "mb-1 text-base font-medium text-gray-900", children: labels.header.title }), jsx("p", { className: "text-xs text-gray-600", children: labels.header.description })] }) }), jsxs("div", { className: "flex flex-1 flex-col overflow-hidden", children: [jsx("div", { className: "flex-1 space-y-4 p-3 lg:p-4", style: { overflowY: 'auto', overflowX: 'hidden' }, "data-testid": "voice-tab-body", children: isMentorSettingsLoading ? (jsx("div", { className: "flex items-center justify-center py-12", "data-testid": "voice-tab-loading", children: jsx(Spinner, {}) })) : (jsx(Fragment$1, { children: jsxs(CapabilityGate, { title: labels.capability.title, description: labels.capability.description, offHint: labels.capability.offHint, enabled: voiceCallEnabled, onToggle: handleToggleVoiceCall, disabled: isDisabled || isTogglingVoiceCall, ariaLabel: labels.capability.title, toggleTestId: "voice-capability-toggle", children: [jsxs(Tabs, { value: SUB_TAB_VALUES[subTab], onValueChange: (value) => setSubTab(SUB_TAB_KEYS[value]), className: "w-full", children: [jsxs(TabsList, { "aria-label": labels.header.title, "data-testid": "voice-sub-tabs", children: [jsx(TabsTrigger, { value: SUB_TAB_VALUES.voice, "data-testid": "voice-sub-tab-voice", children: labels.subTabs.voice }), jsx(TabsTrigger, { value: SUB_TAB_VALUES.callConfig, "data-testid": "voice-sub-tab-call-config", children: labels.subTabs.callConfig }), jsx(TabsTrigger, { value: SUB_TAB_VALUES.settings, "data-testid": "voice-sub-tab-settings", children: labels.subTabs.settings })] }), jsxs(TabsContent, { value: SUB_TAB_VALUES.voice, className: "mt-4 space-y-4", children: [jsx("p", { className: "text-xs text-gray-600", children: labels.mentorVoice.description }), jsx(WithFormPermissions, { name: "voice_provider",
|
|
275112
|
+
// @ts-expect-error permissions.field is opaque
|
|
275113
|
+
permissions: (_p = mentorSettings === null || mentorSettings === void 0 ? void 0 : mentorSettings.permissions) === null || _p === void 0 ? void 0 : _p.field, enableRBAC: enableRBAC, children: ({ disabled }) => (jsxs("div", { className: "space-y-2", children: [jsxs("div", { className: "flex items-center gap-2", children: [jsx(Label$1, { className: "text-sm font-medium text-[#646464]", children: labels.mentorVoice.providerLabel }), jsx(FieldTooltip, { text: labels.mentorVoice.providerTooltip })] }), jsx("div", { className: "grid grid-cols-1 gap-3 sm:grid-cols-2 lg:grid-cols-4", role: "radiogroup", "aria-label": labels.mentorVoice.providerLabel, children: providerOptions.map((option) => {
|
|
275114
|
+
const isSelected = provider === option.value;
|
|
275115
|
+
const isDisabledOption = isDisabled || disabled;
|
|
275116
|
+
return (jsxs("button", { type: "button", role: "radio", "aria-checked": isSelected, "aria-label": option.label, disabled: isDisabledOption, "data-testid": `voice-provider-${option.value}`, "data-voice-provider": option.value, onClick: () => setProvider(option.value), className: cn('flex flex-col items-start gap-2 rounded-lg border-2 p-3 text-left transition-all hover:shadow-sm', isSelected
|
|
275117
|
+
? 'border-blue-500 bg-blue-50/40'
|
|
275118
|
+
: 'border-gray-200 bg-white hover:border-gray-300', isDisabledOption && 'cursor-not-allowed opacity-60'), children: [jsxs("div", { className: "flex items-center gap-2", children: [jsx("span", { className: "flex h-6 w-6 flex-shrink-0 items-center justify-center", children: option.logo.type === 'image' ? (jsx(Image$4, { src: option.logo.src, alt: option.logo.alt, width: 24, height: 24, className: "h-6 w-6 object-contain" })) : (jsx(option.logo.Icon, { className: "h-5 w-5 text-blue-600", "aria-hidden": "true" })) }), jsx("span", { className: "text-sm font-medium text-gray-900", children: option.label })] }), jsx("p", { className: "text-xs text-gray-500", children: option.description })] }, option.value));
|
|
275119
|
+
}) })] })) }), usesVoiceCatalogue(provider) && (jsx(WithFormPermissions, { name: `${provider}_voice`,
|
|
275120
|
+
// @ts-expect-error permissions.field is opaque
|
|
275121
|
+
permissions: (_q = mentorSettings === null || mentorSettings === void 0 ? void 0 : mentorSettings.permissions) === null || _q === void 0 ? void 0 : _q.field, enableRBAC: enableRBAC, children: ({ disabled }) => (jsxs("div", { className: "space-y-2", children: [jsx(Label$1, { className: "text-sm font-medium text-[#646464]", children: t('tabsVoiceTab.voiceLabel') }), jsx(VoicePickerTrigger, { org: tenantKey, userId: username, provider: provider, selectedVoice: selectedVoice, onSelect: onSelectVoice, disabled: isDisabled || disabled, labels: labels.mentorVoice, modalTitle: t('tabsVoiceTab.selectVoiceModalTitle', {
|
|
275122
|
+
voiceType: labels.mentorVoice.voicePickerLabel[provider],
|
|
275123
|
+
}), modalDescription: t('tabsVoiceTab.selectVoiceModalDescription'), testId: "mentor-voice-trigger" })] })) })), (provider === 'openai' || provider === 'google') && (jsx(WithFormPermissions, { name: "voice_instructions",
|
|
275124
|
+
// @ts-expect-error permissions.field is opaque
|
|
275125
|
+
permissions: (_r = mentorSettings === null || mentorSettings === void 0 ? void 0 : mentorSettings.permissions) === null || _r === void 0 ? void 0 : _r.field, enableRBAC: enableRBAC, children: ({ disabled }) => {
|
|
275126
|
+
const isFieldDisabled = isDisabled || disabled;
|
|
275127
|
+
const presetKeys = ['warm', 'calm', 'energetic'];
|
|
275128
|
+
return (jsxs("div", { className: "space-y-2", children: [jsx(PromptCard$1, { label: labels.mentorVoice.instructions.label, placeholder: labels.mentorVoice.instructions.placeholder, value: instructions, disabled: isFieldDisabled, renderContent: renderInstructionsContent, testId: "voice-instructions-card", headerExtra: jsx(FieldTooltip, { text: labels.mentorVoice.instructions.tooltip }), onEdit: () => setSelectedPrompt({
|
|
275129
|
+
label: labels.mentorVoice.instructions.label,
|
|
275130
|
+
isSystem: true,
|
|
275131
|
+
name: 'voice_instructions',
|
|
275132
|
+
prompt: instructions,
|
|
275133
|
+
allowEmpty: true,
|
|
275134
|
+
hideEditorLabel: true,
|
|
275135
|
+
}) }), jsxs("div", { className: "flex items-start justify-between gap-3", children: [jsx("p", { id: "voice-instructions-help", className: "text-xs text-gray-500", children: labels.mentorVoice.instructions.helpText }), jsxs("span", { id: "voice-instructions-counter", "aria-live": "polite", "data-testid": "voice-instructions-counter", className: cn('flex-shrink-0 text-xs text-gray-400', instructionsOverCap && 'text-red-500'), children: [instructions.length, "/", VOICE_INSTRUCTIONS_MAX] })] }), jsxs("div", { className: "flex flex-wrap items-center gap-2", role: "group", "aria-label": labels.mentorVoice.instructions.presetsLabel, children: [jsxs("span", { className: "text-xs text-gray-500", children: [labels.mentorVoice.instructions.presetsLabel, ":"] }), presetKeys.map((key) => (jsx("button", { type: "button", disabled: isFieldDisabled, "data-testid": `voice-instructions-preset-${key}`, onClick: () => setInstructions(labels.mentorVoice.instructions.presets[key].text), className: cn('inline-flex items-center rounded-full border border-gray-300 bg-white px-3 py-1 text-xs text-gray-700 transition-colors hover:bg-gray-50', isFieldDisabled && 'cursor-not-allowed opacity-50'), children: labels.mentorVoice.instructions.presets[key].label }, key)))] })] }));
|
|
275136
|
+
} })), jsx("div", { className: "flex items-center justify-end border-t border-gray-100 pt-3", children: jsx(Button$1, { type: "button", onClick: handleSaveVoice, disabled: isDisabled || !isDirty || instructionsOverCap, "data-testid": "voice-save-button", className: "bg-gradient-to-r from-[#2563EB] to-[#93C5FD] text-white hover:opacity-90", children: isSavingMentor
|
|
275137
|
+
? labels.mentorVoice.savingButton
|
|
275138
|
+
: labels.mentorVoice.saveButton }) })] }), jsxs(TabsContent, { value: SUB_TAB_VALUES.callConfig, className: "mt-4 space-y-4", children: [jsx("p", { className: "text-xs text-gray-600", children: labels.callConfig.description }), mentorId && username && tenantKey && (jsx(CallConfigSection, { org: tenantKey, userId: username, mentorId: mentorId, isDisabled: isDisabled, labels: labels.callConfig, voicePickerLabels: labels.mentorVoice, initialConfig: (_s = mentorSettings === null || mentorSettings === void 0 ? void 0 : mentorSettings.call_configuration) !== null && _s !== void 0 ? _s : null, renderPromptContent: renderPromptContent, toastLabels: {
|
|
275139
|
+
saved: labels.toasts.callConfigSaved,
|
|
275140
|
+
error: labels.toasts.callConfigError,
|
|
275141
|
+
} }))] }), jsx(TabsContent, { value: SUB_TAB_VALUES.settings, className: "mt-4 space-y-4", children: jsxs("div", { className: "space-y-4", "data-testid": "transcription-section", children: [jsxs("div", { className: "space-y-1", children: [jsxs("div", { className: "flex items-center justify-between gap-4", children: [jsxs("div", { className: "flex items-center gap-2", children: [jsx("span", { className: "text-sm font-medium text-[#646464]", children: labels.transcription.toggle.label }), jsx(FieldTooltip, { text: labels.transcription.toggle.tooltip })] }), jsx(CustomSwitch, { checked: voiceRecordEnabled, onCheckedChange: handleToggleVoiceRecord, disabled: isDisabled || isTogglingVoiceRecord, "aria-label": labels.transcription.toggle.label, "data-testid": "voice-record-capability-toggle", className: "flex-shrink-0" })] }), jsx("p", { className: "text-xs text-gray-500", children: labels.transcription.toggle.helpText })] }), jsx(WithFormPermissions, { name: "transcription_language",
|
|
275142
|
+
// @ts-expect-error permissions.field is opaque
|
|
275143
|
+
permissions: (_t = mentorSettings === null || mentorSettings === void 0 ? void 0 : mentorSettings.permissions) === null || _t === void 0 ? void 0 : _t.field, enableRBAC: enableRBAC, children: ({ disabled }) => (jsxs("div", { className: "space-y-2", "data-testid": "transcription-language-field", children: [jsxs("div", { className: "flex items-center gap-2", children: [jsx(Label$1, { className: "text-sm font-medium text-[#646464]", children: labels.transcription.language.label }), jsx(FieldTooltip, { text: labels.transcription.language.tooltip })] }), jsxs(Select$1, { value: transcriptionLanguage || TRANSCRIPTION_LANGUAGE_UNSET, onValueChange: (value) => setTranscriptionLanguage(value === TRANSCRIPTION_LANGUAGE_UNSET ? '' : value), disabled: isDisabled || disabled, children: [jsx(SelectTrigger, { "aria-label": labels.transcription.language.label, "data-testid": "transcription-language-select", children: jsx(SelectValue, { placeholder: labels.transcription.language.placeholder }) }), jsxs(SelectContent, { children: [jsx(SelectItem, { value: TRANSCRIPTION_LANGUAGE_UNSET, children: labels.transcription.language.placeholder }), TRANSCRIPTION_LANGUAGE_OPTIONS.map((option) => (jsx(SelectItem, { value: option.value, children: option.label }, option.value)))] })] })] })) }), jsx(WithFormPermissions, { name: "transcription_instructions",
|
|
275144
|
+
// @ts-expect-error permissions.field is opaque
|
|
275145
|
+
permissions: (_u = mentorSettings === null || mentorSettings === void 0 ? void 0 : mentorSettings.permissions) === null || _u === void 0 ? void 0 : _u.field, enableRBAC: enableRBAC, children: ({ disabled }) => (jsxs("div", { className: "space-y-2", children: [jsxs("div", { className: "flex items-center gap-2", children: [jsx(Label$1, { htmlFor: "transcription-instructions", className: "text-sm font-medium text-[#646464]", children: labels.transcription.instructions.label }), jsx(FieldTooltip, { text: labels.transcription.instructions.tooltip })] }), jsx(Textarea, { id: "transcription-instructions", rows: 4, value: transcriptionInstructions, onChange: (event) => setTranscriptionInstructions(event.target.value), placeholder: labels.transcription.instructions.placeholder, disabled: isDisabled || disabled, "aria-label": labels.transcription.instructions.label, "aria-describedby": "transcription-instructions-help", "data-testid": "transcription-instructions-textarea" }), jsxs("div", { className: "flex items-start justify-between gap-3", children: [jsx("p", { id: "transcription-instructions-help", className: "text-xs text-gray-500", children: labels.transcription.instructions.helpText }), jsxs("span", { "aria-live": "polite", "data-testid": "transcription-instructions-counter", className: cn('flex-shrink-0 text-xs text-gray-400', transcriptionOverCap && 'text-red-500'), children: [transcriptionInstructions.length, "/", TRANSCRIPTION_INSTRUCTIONS_MAX] })] })] })) })] }) })] }), selectedPrompt && (
|
|
275146
|
+
// `EditPromptModal` calls strict `useAgentSettings()`. The host
|
|
275147
|
+
// may not have wrapped this tab in `<AgentSettingsProvider>`
|
|
275148
|
+
// (older integrations pass identity via props), so re-provide
|
|
275149
|
+
// whatever we resolved — same pattern as `AgentScreenShareTab`.
|
|
275150
|
+
jsx(AgentSettingsProvider, { tenantKey: tenantKey, mentorId: mentorId, username: username, enableRBAC: enableRBAC, rbacPermissions: ctx === null || ctx === void 0 ? void 0 : ctx.rbacPermissions, executeGatedAction: ctx === null || ctx === void 0 ? void 0 : ctx.executeGatedAction, visibilityOptions: ctx === null || ctx === void 0 ? void 0 : ctx.visibilityOptions, children: jsx(EditPromptModal$1, { isOpen: true, onClose: () => setSelectedPrompt(null), selectedPrompt: selectedPrompt, isEditing: isSavingMentor, handleSave: (prompt, values) => {
|
|
275151
|
+
if (prompt.name === 'voice_instructions') {
|
|
275152
|
+
setInstructions(values.prompt);
|
|
275153
|
+
}
|
|
275154
|
+
setSelectedPrompt(null);
|
|
275155
|
+
} }) }))] }) })) }), !isMentorSettingsLoading && subTab === 'settings' && (jsx("div", { className: "flex flex-shrink-0 justify-end gap-2 border-t border-gray-200 bg-white px-3 py-4", children: jsx(Button$1, { type: "button", onClick: handleSaveTranscription, disabled: isDisabled || !transcriptionDirty || transcriptionOverCap, "aria-label": labels.transcription.saveButton, "data-testid": "transcription-save-button", className: "bg-gradient-to-r from-[#2563EB] to-[#93C5FD] text-white hover:opacity-90", children: isSavingMentor ? (jsxs("span", { className: "flex items-center gap-2", children: [jsx(Spinner, { size: "sm", className: "text-white" }), labels.transcription.savingButton] })) : (labels.transcription.saveButton) }) }))] })] }));
|
|
274887
275156
|
}
|
|
274888
275157
|
function FieldTooltip({ text }) {
|
|
274889
275158
|
const t = useT();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@iblai/iblai-js",
|
|
3
|
-
"version": "2.7.
|
|
3
|
+
"version": "2.7.9",
|
|
4
4
|
"description": "Unified JavaScript SDK for IBL.ai — re-exports data-layer, web-containers, and web-utils under a single package",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"engines": {
|
|
@@ -76,10 +76,10 @@
|
|
|
76
76
|
"axios": "1.13.6",
|
|
77
77
|
"dotenv": "16.6.1",
|
|
78
78
|
"winston": "3.19.0",
|
|
79
|
-
"@iblai/web-utils": "2.2.2-reconnect.2",
|
|
80
79
|
"@iblai/data-layer": "1.13.0",
|
|
81
|
-
"@iblai/
|
|
82
|
-
"@iblai/
|
|
80
|
+
"@iblai/mcp": "1.12.3",
|
|
81
|
+
"@iblai/web-containers": "1.19.6",
|
|
82
|
+
"@iblai/web-utils": "2.2.2-reconnect.2"
|
|
83
83
|
},
|
|
84
84
|
"peerDependencies": {
|
|
85
85
|
"@iblai/iblai-api": "4.166.0-ai",
|