@iblai/iblai-js 2.37.1 → 2.38.0

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.
@@ -93067,12 +93067,12 @@ var shimExports = shim.exports;
93067
93067
  // src/use-is-hydrated.tsx
93068
93068
  function useIsHydrated() {
93069
93069
  return shimExports.useSyncExternalStore(
93070
- subscribe$2,
93070
+ subscribe$3,
93071
93071
  () => true,
93072
93072
  () => false
93073
93073
  );
93074
93074
  }
93075
- function subscribe$2() {
93075
+ function subscribe$3() {
93076
93076
  return () => {
93077
93077
  };
93078
93078
  }
@@ -103422,20 +103422,48 @@ var chat$3 = {
103422
103422
  copied: "Copied",
103423
103423
  share: "Share"
103424
103424
  },
103425
+ chatCodeActivity: {
103426
+ steps: "{count, plural, one {# step} other {# steps}}",
103427
+ aFile: "a file",
103428
+ statusRunning: "Running",
103429
+ statusDone: "Done",
103430
+ statusFailed: "Didn’t go through",
103431
+ statusStopped: "Stopped",
103432
+ read: "{form, select, running {Reading {file}} done {Read {file}} failed {Couldn’t read {file}} other {Code wants to read {file}}}",
103433
+ create: "{form, select, running {Creating {file}} done {Created {file}} failed {Couldn’t create {file}} other {Code wants to create {file}}}",
103434
+ edit: "{form, select, running {Changing {file}} done {Changed {file}} failed {Couldn’t change {file}} other {Code wants to change {file}}}",
103435
+ editMany: "{form, select, running {Changing {count} files} done {Changed {count} files} failed {Couldn’t change {count} files} other {Code wants to change {count} files}}",
103436
+ remove: "{form, select, running {Removing {file}} done {Removed {file}} failed {Couldn’t remove {file}} other {Code wants to remove {file}}}",
103437
+ removeMany: "{form, select, running {Removing {count} files} done {Removed {count} files} failed {Couldn’t remove {count} files} other {Code wants to remove {count} files}}",
103438
+ move: "{form, select, running {Moving {file}} done {Moved {file}} failed {Couldn’t move {file}} other {Code wants to move {file}}}",
103439
+ search: "{form, select, running {Looking through the app’s files} done {Looked through the app’s files} failed {Couldn’t look through the app’s files} other {Code wants to look through the app’s files}}",
103440
+ run: "{form, select, running {Running a command} done {Ran a command} failed {A command didn’t go through} other {Code wants to run a command}}",
103441
+ runDescribed: "{form, select, running {Running a command: {description}} done {Ran a command: {description}} failed {A command didn’t go through: {description}} other {Code wants to run a command: {description}}}",
103442
+ install: "{form, select, running {Installing what the app needs} done {Installed what the app needs} failed {Couldn’t install what the app needs} other {Code wants to install what the app needs}}",
103443
+ preview: "{form, select, running {Starting the preview} done {Started the preview} failed {Couldn’t start the preview} other {Code wants to start the preview}}",
103444
+ open: "{form, select, running {Opening {host}} done {Opened {host}} failed {Couldn’t open {host}} other {Code wants to open {host}}}",
103445
+ openPreview: "{form, select, running {Checking the preview} done {Checked the preview} failed {Couldn’t reach the preview} other {Code wants to check the preview}}",
103446
+ web: "{form, select, running {Searching the web for “{query}”} done {Searched the web for “{query}”} failed {Couldn’t search the web for “{query}”} other {Code wants to search the web for “{query}”}}",
103447
+ helper: "{form, select, running {Working on a side task: {description}} done {Finished a side task: {description}} failed {A side task didn’t go through: {description}} other {Code wants to start a side task: {description}}}",
103448
+ helperPlain: "{form, select, running {Working on a side task} done {Finished a side task} failed {A side task didn’t go through} other {Code wants to start a side task}}",
103449
+ skill: "{form, select, running {Looking up how to do this} done {Looked up how to do this} failed {Couldn’t look up how to do this} other {Code wants to look up how to do this}}",
103450
+ plan: "{form, select, running {Updating its task list} done {Updated its task list} failed {Couldn’t update its task list} other {Code wants to update its task list}}",
103451
+ approve: "{form, select, running {Asking to go ahead with its plan} done {Got the go-ahead for its plan} failed {Didn’t get the go-ahead} other {Code wants to go ahead with its plan}}",
103452
+ ask: "{form, select, running {Asking you a question} done {Asked you a question} failed {Couldn’t ask its question} other {Code wants to ask you a question}}",
103453
+ connector: "{form, select, running {Using {name}} done {Used {name}} failed {Couldn’t use {name}} other {Code wants to use {name}}}",
103454
+ think: "{form, select, running {Working something out} done {Worked something out} failed {Couldn’t work it out} other {Code wants to think this through}}",
103455
+ other: "{form, select, running {Working on a step} done {Finished a step} failed {A step didn’t go through} other {Code wants to do something it didn’t describe}}"
103456
+ },
103457
+ chatCodeErrors: {
103458
+ stopped: "Code stopped unexpectedly. Send your message again.",
103459
+ noAnswer: "Code took too long to answer. Try again.",
103460
+ noModel: "Pick a model in the top-left, then send again.",
103461
+ couldNotStart: "Code couldn’t start. Try again, and restart the app if it keeps happening.",
103462
+ signedOut: "Sign in to use Code."
103463
+ },
103425
103464
  chatCodePermissionCard: {
103426
103465
  title: "Code needs your permission",
103427
103466
  unnamedAction: "An action it didn’t name",
103428
- kind: {
103429
- read: "read",
103430
- write: "write",
103431
- exec: "exec",
103432
- "delete": "delete",
103433
- move: "move",
103434
- search: "search",
103435
- fetch: "fetch",
103436
- think: "think",
103437
- other: "action"
103438
- },
103439
103467
  allow: "Allow",
103440
103468
  deny: "Deny"
103441
103469
  },
@@ -111726,20 +111754,48 @@ var chat$2 = {
111726
111754
  copied: "Copié",
111727
111755
  share: "Partager"
111728
111756
  },
111757
+ chatCodeActivity: {
111758
+ steps: "{count, plural, one {# étape} other {# étapes}}",
111759
+ aFile: "un fichier",
111760
+ statusRunning: "En cours",
111761
+ statusDone: "Terminé",
111762
+ statusFailed: "N’a pas abouti",
111763
+ statusStopped: "Interrompu",
111764
+ read: "{form, select, running {Lecture de {file}} done {A lu {file}} failed {N’a pas pu lire {file}} other {Code veut lire {file}}}",
111765
+ create: "{form, select, running {Création de {file}} done {A créé {file}} failed {N’a pas pu créer {file}} other {Code veut créer {file}}}",
111766
+ edit: "{form, select, running {Modification de {file}} done {A modifié {file}} failed {N’a pas pu modifier {file}} other {Code veut modifier {file}}}",
111767
+ editMany: "{form, select, running {Modification de {count} fichiers} done {A modifié {count} fichiers} failed {N’a pas pu modifier {count} fichiers} other {Code veut modifier {count} fichiers}}",
111768
+ remove: "{form, select, running {Suppression de {file}} done {A supprimé {file}} failed {N’a pas pu supprimer {file}} other {Code veut supprimer {file}}}",
111769
+ removeMany: "{form, select, running {Suppression de {count} fichiers} done {A supprimé {count} fichiers} failed {N’a pas pu supprimer {count} fichiers} other {Code veut supprimer {count} fichiers}}",
111770
+ move: "{form, select, running {Déplacement de {file}} done {A déplacé {file}} failed {N’a pas pu déplacer {file}} other {Code veut déplacer {file}}}",
111771
+ search: "{form, select, running {Parcourt les fichiers de l’app} done {A parcouru les fichiers de l’app} failed {N’a pas pu parcourir les fichiers de l’app} other {Code veut parcourir les fichiers de l’app}}",
111772
+ run: "{form, select, running {Exécution d’une commande} done {A exécuté une commande} failed {Une commande n’a pas abouti} other {Code veut exécuter une commande}}",
111773
+ runDescribed: "{form, select, running {Exécution d’une commande : {description}} done {A exécuté une commande : {description}} failed {Une commande n’a pas abouti : {description}} other {Code veut exécuter une commande : {description}}}",
111774
+ install: "{form, select, running {Installation de ce dont l’app a besoin} done {A installé ce dont l’app a besoin} failed {N’a pas pu installer ce dont l’app a besoin} other {Code veut installer ce dont l’app a besoin}}",
111775
+ preview: "{form, select, running {Lancement de l’aperçu} done {A lancé l’aperçu} failed {N’a pas pu lancer l’aperçu} other {Code veut lancer l’aperçu}}",
111776
+ open: "{form, select, running {Ouverture de {host}} done {A ouvert {host}} failed {N’a pas pu ouvrir {host}} other {Code veut ouvrir {host}}}",
111777
+ openPreview: "{form, select, running {Vérification de l’aperçu} done {A vérifié l’aperçu} failed {N’a pas pu joindre l’aperçu} other {Code veut vérifier l’aperçu}}",
111778
+ web: "{form, select, running {Recherche sur le web de « {query} »} done {A cherché sur le web « {query} »} failed {N’a pas pu chercher sur le web « {query} »} other {Code veut chercher sur le web « {query} »}}",
111779
+ helper: "{form, select, running {Travaille sur une tâche annexe : {description}} done {A terminé une tâche annexe : {description}} failed {Une tâche annexe n’a pas abouti : {description}} other {Code veut lancer une tâche annexe : {description}}}",
111780
+ helperPlain: "{form, select, running {Travaille sur une tâche annexe} done {A terminé une tâche annexe} failed {Une tâche annexe n’a pas abouti} other {Code veut lancer une tâche annexe}}",
111781
+ skill: "{form, select, running {Consulte la marche à suivre} done {A consulté la marche à suivre} failed {N’a pas pu consulter la marche à suivre} other {Code veut consulter la marche à suivre}}",
111782
+ plan: "{form, select, running {Mise à jour de sa liste de tâches} done {A mis à jour sa liste de tâches} failed {N’a pas pu mettre à jour sa liste de tâches} other {Code veut mettre à jour sa liste de tâches}}",
111783
+ approve: "{form, select, running {Demande le feu vert pour son plan} done {A reçu le feu vert pour son plan} failed {N’a pas reçu le feu vert} other {Code veut poursuivre son plan}}",
111784
+ ask: "{form, select, running {Vous pose une question} done {Vous a posé une question} failed {N’a pas pu poser sa question} other {Code veut vous poser une question}}",
111785
+ connector: "{form, select, running {Utilisation de {name}} done {A utilisé {name}} failed {N’a pas pu utiliser {name}} other {Code veut utiliser {name}}}",
111786
+ think: "{form, select, running {Réfléchit à quelque chose} done {A réfléchi à quelque chose} failed {N’a pas pu trancher} other {Code veut y réfléchir}}",
111787
+ other: "{form, select, running {Travaille sur une étape} done {A terminé une étape} failed {Une étape n’a pas abouti} other {Code veut faire quelque chose qu’il n’a pas décrit}}"
111788
+ },
111789
+ chatCodeErrors: {
111790
+ stopped: "Code s’est arrêté de façon inattendue. Renvoyez votre message.",
111791
+ noAnswer: "Code a mis trop de temps à répondre. Réessayez.",
111792
+ noModel: "Choisissez un modèle en haut à gauche, puis renvoyez votre message.",
111793
+ couldNotStart: "Code n’a pas pu démarrer. Réessayez, et redémarrez l’app si cela continue.",
111794
+ signedOut: "Connectez-vous pour utiliser Code."
111795
+ },
111729
111796
  chatCodePermissionCard: {
111730
111797
  title: "Code a besoin de votre autorisation",
111731
111798
  unnamedAction: "Une action non nommée",
111732
- kind: {
111733
- read: "lire",
111734
- write: "écrire",
111735
- exec: "exécuter",
111736
- "delete": "supprimer",
111737
- move: "déplacer",
111738
- search: "chercher",
111739
- fetch: "récupérer",
111740
- think: "réfléchir",
111741
- other: "action"
111742
- },
111743
111799
  allow: "Autoriser",
111744
111800
  deny: "Refuser"
111745
111801
  },
@@ -120030,20 +120086,48 @@ var chat$1 = {
120030
120086
  copied: "Copiado",
120031
120087
  share: "Compartir"
120032
120088
  },
120089
+ chatCodeActivity: {
120090
+ steps: "{count, plural, one {# paso} other {# pasos}}",
120091
+ aFile: "un archivo",
120092
+ statusRunning: "En curso",
120093
+ statusDone: "Hecho",
120094
+ statusFailed: "No se completó",
120095
+ statusStopped: "Detenido",
120096
+ read: "{form, select, running {Leyendo {file}} done {Leyó {file}} failed {No pudo leer {file}} other {Código quiere leer {file}}}",
120097
+ create: "{form, select, running {Creando {file}} done {Creó {file}} failed {No pudo crear {file}} other {Código quiere crear {file}}}",
120098
+ edit: "{form, select, running {Cambiando {file}} done {Cambió {file}} failed {No pudo cambiar {file}} other {Código quiere cambiar {file}}}",
120099
+ editMany: "{form, select, running {Cambiando {count} archivos} done {Cambió {count} archivos} failed {No pudo cambiar {count} archivos} other {Código quiere cambiar {count} archivos}}",
120100
+ remove: "{form, select, running {Eliminando {file}} done {Eliminó {file}} failed {No pudo eliminar {file}} other {Código quiere eliminar {file}}}",
120101
+ removeMany: "{form, select, running {Eliminando {count} archivos} done {Eliminó {count} archivos} failed {No pudo eliminar {count} archivos} other {Código quiere eliminar {count} archivos}}",
120102
+ move: "{form, select, running {Moviendo {file}} done {Movió {file}} failed {No pudo mover {file}} other {Código quiere mover {file}}}",
120103
+ search: "{form, select, running {Revisando los archivos de la app} done {Revisó los archivos de la app} failed {No pudo revisar los archivos de la app} other {Código quiere revisar los archivos de la app}}",
120104
+ run: "{form, select, running {Ejecutando un comando} done {Ejecutó un comando} failed {Un comando no se completó} other {Código quiere ejecutar un comando}}",
120105
+ runDescribed: "{form, select, running {Ejecutando un comando: {description}} done {Ejecutó un comando: {description}} failed {Un comando no se completó: {description}} other {Código quiere ejecutar un comando: {description}}}",
120106
+ install: "{form, select, running {Instalando lo que la app necesita} done {Instaló lo que la app necesita} failed {No pudo instalar lo que la app necesita} other {Código quiere instalar lo que la app necesita}}",
120107
+ preview: "{form, select, running {Iniciando la vista previa} done {Inició la vista previa} failed {No pudo iniciar la vista previa} other {Código quiere iniciar la vista previa}}",
120108
+ open: "{form, select, running {Abriendo {host}} done {Abrió {host}} failed {No pudo abrir {host}} other {Código quiere abrir {host}}}",
120109
+ openPreview: "{form, select, running {Comprobando la vista previa} done {Comprobó la vista previa} failed {No pudo acceder a la vista previa} other {Código quiere comprobar la vista previa}}",
120110
+ web: "{form, select, running {Buscando en la web “{query}”} done {Buscó en la web “{query}”} failed {No pudo buscar en la web “{query}”} other {Código quiere buscar en la web “{query}”}}",
120111
+ helper: "{form, select, running {Trabajando en una tarea aparte: {description}} done {Terminó una tarea aparte: {description}} failed {Una tarea aparte no se completó: {description}} other {Código quiere iniciar una tarea aparte: {description}}}",
120112
+ helperPlain: "{form, select, running {Trabajando en una tarea aparte} done {Terminó una tarea aparte} failed {Una tarea aparte no se completó} other {Código quiere iniciar una tarea aparte}}",
120113
+ skill: "{form, select, running {Consultando cómo hacerlo} done {Consultó cómo hacerlo} failed {No pudo consultar cómo hacerlo} other {Código quiere consultar cómo hacerlo}}",
120114
+ plan: "{form, select, running {Actualizando su lista de tareas} done {Actualizó su lista de tareas} failed {No pudo actualizar su lista de tareas} other {Código quiere actualizar su lista de tareas}}",
120115
+ approve: "{form, select, running {Pidiendo permiso para seguir con su plan} done {Recibió permiso para seguir con su plan} failed {No recibió permiso para seguir} other {Código quiere seguir con su plan}}",
120116
+ ask: "{form, select, running {Haciéndote una pregunta} done {Te hizo una pregunta} failed {No pudo hacer su pregunta} other {Código quiere hacerte una pregunta}}",
120117
+ connector: "{form, select, running {Usando {name}} done {Usó {name}} failed {No pudo usar {name}} other {Código quiere usar {name}}}",
120118
+ think: "{form, select, running {Resolviendo algo} done {Resolvió algo} failed {No pudo resolverlo} other {Código quiere pensarlo}}",
120119
+ other: "{form, select, running {Trabajando en un paso} done {Terminó un paso} failed {Un paso no se completó} other {Código quiere hacer algo que no describió}}"
120120
+ },
120121
+ chatCodeErrors: {
120122
+ stopped: "Código se detuvo de forma inesperada. Envía tu mensaje de nuevo.",
120123
+ noAnswer: "Código tardó demasiado en responder. Inténtalo de nuevo.",
120124
+ noModel: "Elige un modelo arriba a la izquierda y vuelve a enviar.",
120125
+ couldNotStart: "Código no pudo iniciarse. Inténtalo de nuevo y reinicia la app si sigue pasando.",
120126
+ signedOut: "Inicia sesión para usar Código."
120127
+ },
120033
120128
  chatCodePermissionCard: {
120034
120129
  title: "Código necesita tu permiso",
120035
120130
  unnamedAction: "Una acción sin nombre",
120036
- kind: {
120037
- read: "leer",
120038
- write: "escribir",
120039
- exec: "ejecutar",
120040
- "delete": "eliminar",
120041
- move: "mover",
120042
- search: "buscar",
120043
- fetch: "obtener",
120044
- think: "pensar",
120045
- other: "acción"
120046
- },
120047
120131
  allow: "Permitir",
120048
120132
  deny: "Denegar"
120049
120133
  },
@@ -128334,20 +128418,48 @@ var chat = {
128334
128418
  copied: "已复制",
128335
128419
  share: "分享"
128336
128420
  },
128421
+ chatCodeActivity: {
128422
+ steps: "{count, plural, other {# 个步骤}}",
128423
+ aFile: "一个文件",
128424
+ statusRunning: "进行中",
128425
+ statusDone: "已完成",
128426
+ statusFailed: "未成功",
128427
+ statusStopped: "已中断",
128428
+ read: "{form, select, running {正在读取 {file}} done {已读取 {file}} failed {无法读取 {file}} other {代码模式想读取 {file}}}",
128429
+ create: "{form, select, running {正在创建 {file}} done {已创建 {file}} failed {无法创建 {file}} other {代码模式想创建 {file}}}",
128430
+ edit: "{form, select, running {正在修改 {file}} done {已修改 {file}} failed {无法修改 {file}} other {代码模式想修改 {file}}}",
128431
+ editMany: "{form, select, running {正在修改 {count} 个文件} done {已修改 {count} 个文件} failed {无法修改 {count} 个文件} other {代码模式想修改 {count} 个文件}}",
128432
+ remove: "{form, select, running {正在删除 {file}} done {已删除 {file}} failed {无法删除 {file}} other {代码模式想删除 {file}}}",
128433
+ removeMany: "{form, select, running {正在删除 {count} 个文件} done {已删除 {count} 个文件} failed {无法删除 {count} 个文件} other {代码模式想删除 {count} 个文件}}",
128434
+ move: "{form, select, running {正在移动 {file}} done {已移动 {file}} failed {无法移动 {file}} other {代码模式想移动 {file}}}",
128435
+ search: "{form, select, running {正在查看应用的文件} done {已查看应用的文件} failed {无法查看应用的文件} other {代码模式想查看应用的文件}}",
128436
+ run: "{form, select, running {正在运行一条命令} done {已运行一条命令} failed {一条命令未成功} other {代码模式想运行一条命令}}",
128437
+ runDescribed: "{form, select, running {正在运行一条命令:{description}} done {已运行一条命令:{description}} failed {一条命令未成功:{description}} other {代码模式想运行一条命令:{description}}}",
128438
+ install: "{form, select, running {正在安装应用所需的内容} done {已安装应用所需的内容} failed {无法安装应用所需的内容} other {代码模式想安装应用所需的内容}}",
128439
+ preview: "{form, select, running {正在启动预览} done {已启动预览} failed {无法启动预览} other {代码模式想启动预览}}",
128440
+ open: "{form, select, running {正在打开 {host}} done {已打开 {host}} failed {无法打开 {host}} other {代码模式想打开 {host}}}",
128441
+ openPreview: "{form, select, running {正在检查预览} done {已检查预览} failed {无法访问预览} other {代码模式想检查预览}}",
128442
+ web: "{form, select, running {正在网上搜索“{query}”} done {已在网上搜索“{query}”} failed {无法在网上搜索“{query}”} other {代码模式想在网上搜索“{query}”}}",
128443
+ helper: "{form, select, running {正在处理一项附带任务:{description}} done {已完成一项附带任务:{description}} failed {一项附带任务未成功:{description}} other {代码模式想开始一项附带任务:{description}}}",
128444
+ helperPlain: "{form, select, running {正在处理一项附带任务} done {已完成一项附带任务} failed {一项附带任务未成功} other {代码模式想开始一项附带任务}}",
128445
+ skill: "{form, select, running {正在查阅操作方法} done {已查阅操作方法} failed {无法查阅操作方法} other {代码模式想查阅操作方法}}",
128446
+ plan: "{form, select, running {正在更新任务清单} done {已更新任务清单} failed {无法更新任务清单} other {代码模式想更新任务清单}}",
128447
+ approve: "{form, select, running {正在请求按计划继续} done {已获准按计划继续} failed {未获准继续} other {代码模式想按计划继续}}",
128448
+ ask: "{form, select, running {正在向你提问} done {已向你提问} failed {无法提出问题} other {代码模式想向你提问}}",
128449
+ connector: "{form, select, running {正在使用 {name}} done {已使用 {name}} failed {无法使用 {name}} other {代码模式想使用 {name}}}",
128450
+ think: "{form, select, running {正在思考} done {已想清楚} failed {没能想清楚} other {代码模式想先思考一下}}",
128451
+ other: "{form, select, running {正在处理一个步骤} done {已完成一个步骤} failed {一个步骤未成功} other {代码模式想做一件没有说明的事}}"
128452
+ },
128453
+ chatCodeErrors: {
128454
+ stopped: "代码模式意外停止了。请再发送一次你的消息。",
128455
+ noAnswer: "代码模式响应太慢。请再试一次。",
128456
+ noModel: "请先在左上角选择一个模型,然后再发送。",
128457
+ couldNotStart: "代码模式无法启动。请再试一次;如果持续出现,请重启应用。",
128458
+ signedOut: "请先登录再使用代码模式。"
128459
+ },
128337
128460
  chatCodePermissionCard: {
128338
128461
  title: "代码模式需要你的许可",
128339
128462
  unnamedAction: "一项未命名的操作",
128340
- kind: {
128341
- read: "读取",
128342
- write: "写入",
128343
- exec: "执行",
128344
- "delete": "删除",
128345
- move: "移动",
128346
- search: "搜索",
128347
- fetch: "获取",
128348
- think: "思考",
128349
- other: "操作"
128350
- },
128351
128463
  allow: "允许",
128352
128464
  deny: "拒绝"
128353
128465
  },
@@ -184967,7 +185079,7 @@ class Style {
184967
185079
  * Get a text or display version of this style.
184968
185080
  */
184969
185081
  text() {
184970
- return styles[text$1[this.id]];
185082
+ return styles[text$1$1[this.id]];
184971
185083
  }
184972
185084
  /**
184973
185085
  * Return true if this style is tightly spaced (scriptstyle/scriptscriptstyle)
@@ -184993,7 +185105,7 @@ var sub$1 = [Sc$1, Sc$1, Sc$1, Sc$1, SSc, SSc, SSc, SSc];
184993
185105
  var fracNum = [T$1, Tc, S, Sc$1, SS, SSc, SS, SSc];
184994
185106
  var fracDen = [Tc, Tc, Sc$1, Sc$1, SSc, SSc, SSc, SSc];
184995
185107
  var cramp = [Dc, Dc, Tc, Tc, Sc$1, Sc$1, SSc, SSc];
184996
- var text$1 = [D$1, Dc, T$1, Tc, T$1, Tc, T$1, Tc];
185108
+ var text$1$1 = [D$1, Dc, T$1, Tc, T$1, Tc, T$1, Tc];
184997
185109
  // We only export some of the styles.
184998
185110
  var Style$1 = {
184999
185111
  DISPLAY: styles[D$1],
@@ -243093,7 +243205,7 @@ function chatTextPreview(text) {
243093
243205
  .trim();
243094
243206
  }
243095
243207
 
243096
- const clean$2 = (value) => typeof value === 'string' && value.trim() ? value.trim() : undefined;
243208
+ const clean$3 = (value) => typeof value === 'string' && value.trim() ? value.trim() : undefined;
243097
243209
  /** The first human turn of a conversation, from an array or its JSON string form. */
243098
243210
  function firstHumanMessage(messages) {
243099
243211
  let turns = messages;
@@ -243108,7 +243220,7 @@ function firstHumanMessage(messages) {
243108
243220
  if (!Array.isArray(turns))
243109
243221
  return undefined;
243110
243222
  const first = turns[0];
243111
- return clean$2(first === null || first === void 0 ? void 0 : first.human);
243223
+ return clean$3(first === null || first === void 0 ? void 0 : first.human);
243112
243224
  }
243113
243225
  const preview = (value) => (typeof value === 'string' && chatTextPreview(value)) || undefined;
243114
243226
  /**
@@ -247706,7 +247818,7 @@ function one(state, node, key) {
247706
247818
  }
247707
247819
 
247708
247820
  if (node.type === 'text') {
247709
- return text(state, node)
247821
+ return text$1(state, node)
247710
247822
  }
247711
247823
  }
247712
247824
 
@@ -247870,7 +247982,7 @@ function root(state, node, key) {
247870
247982
  * @returns {Child | undefined}
247871
247983
  * Child, optional.
247872
247984
  */
247873
- function text(_, node) {
247985
+ function text$1(_, node) {
247874
247986
  return node.value
247875
247987
  }
247876
247988
 
@@ -283258,7 +283370,7 @@ const OVERVIEW_LLM_RANGE = '30d';
283258
283370
  const OVERVIEW_ENROLLMENT_PAGE_SIZE = 50;
283259
283371
  /** Models fetched for the breakdown; the tab folds the tail into "Other". */
283260
283372
  const OVERVIEW_MODEL_LIMIT = 10;
283261
- const statusOf = (error) => error && typeof error === 'object' ? error.status : undefined;
283373
+ const statusOf$1 = (error) => error && typeof error === 'object' ? error.status : undefined;
283262
283374
  /**
283263
283375
  * Everything the Overview tab shows, read through the same endpoints the
283264
283376
  * individual tabs use so the two never disagree. Each section is requested
@@ -283335,7 +283447,7 @@ function useOverviewData(org, username, sections) {
283335
283447
  enabled: sections.chatHistory,
283336
283448
  isLoading: sections.chatHistory && historyQ.isLoading,
283337
283449
  isError: historyQ.isError,
283338
- isForbidden: statusOf(historyQ.error) === 403,
283450
+ isForbidden: statusOf$1(historyQ.error) === 403,
283339
283451
  count: (_b = (_a = historyQ.data) === null || _a === void 0 ? void 0 : _a.count) !== null && _b !== void 0 ? _b : 0,
283340
283452
  recent: (_d = (_c = historyQ.data) === null || _c === void 0 ? void 0 : _c.results) !== null && _d !== void 0 ? _d : [],
283341
283453
  });
@@ -285780,7 +285892,7 @@ const deepLink = (url, snippet) => {
285780
285892
  return url;
285781
285893
  return `${url.split('#')[0]}#:~:text=${encodeURIComponent(text)}`;
285782
285894
  };
285783
- const hostOf = (value) => {
285895
+ const hostOf$1 = (value) => {
285784
285896
  try {
285785
285897
  return new URL(value).host;
285786
285898
  }
@@ -285800,7 +285912,7 @@ function RetrievedDocumentRow({ doc }) {
285800
285912
  const [previewOpen, setPreviewOpen] = React.useState(false);
285801
285913
  const source = ((_a = doc.source) !== null && _a !== void 0 ? _a : '').trim();
285802
285914
  const url = isHttpUrl(source) ? source : null;
285803
- const title = doc.title || (url ? hostOf(url) : source);
285915
+ const title = doc.title || (url ? hostOf$1(url) : source);
285804
285916
  const relevance = relevancePercent(doc.score);
285805
285917
  const openHref = url ? deepLink(url, doc.snippet) : null;
285806
285918
  // Preview only what a browser can show; Office files, archives and
@@ -286163,7 +286275,7 @@ function useLlmProviderCatalogue({ org, userId, mentorId }) {
286163
286275
  };
286164
286276
  }, [rowsByName, rowsByLooseName, rowForModel]);
286165
286277
  }
286166
- const clean$1 = (value) => (value === null || value === void 0 ? void 0 : value.trim()) || undefined;
286278
+ const clean$2 = (value) => (value === null || value === void 0 ? void 0 : value.trim()) || undefined;
286167
286279
  /**
286168
286280
  * The label to show for a model.
286169
286281
  *
@@ -286180,7 +286292,7 @@ const clean$1 = (value) => (value === null || value === void 0 ? void 0 : value.
286180
286292
  */
286181
286293
  function useLlmDisplayName({ llmName, llmConfig, org, userId, mentorId, }) {
286182
286294
  var _a;
286183
- const fromConfig = clean$1(llmConfig === null || llmConfig === void 0 ? void 0 : llmConfig.display_name);
286295
+ const fromConfig = clean$2(llmConfig === null || llmConfig === void 0 ? void 0 : llmConfig.display_name);
286184
286296
  const skip = Boolean(fromConfig) || !llmName || !org || !userId || !mentorId;
286185
286297
  const { data: providers } = useGetLlmsQuery({
286186
286298
  org: org !== null && org !== void 0 ? org : '',
@@ -286195,7 +286307,7 @@ function useLlmDisplayName({ llmName, llmConfig, org, userId, mentorId, }) {
286195
286307
  const wanted = modelKey(llmName);
286196
286308
  for (const provider of providers) {
286197
286309
  const match = (_a = provider === null || provider === void 0 ? void 0 : provider.chat_models) === null || _a === void 0 ? void 0 : _a.find((model) => modelKey(model === null || model === void 0 ? void 0 : model.llm_name) === wanted || modelKey(model === null || model === void 0 ? void 0 : model.display_name) === wanted);
286198
- const label = clean$1(match === null || match === void 0 ? void 0 : match.display_name);
286310
+ const label = clean$2(match === null || match === void 0 ? void 0 : match.display_name);
286199
286311
  if (label)
286200
286312
  return label;
286201
286313
  }
@@ -289549,7 +289661,7 @@ function parseMetadataValue(raw) {
289549
289661
  return undefined;
289550
289662
  }
289551
289663
  }
289552
- function isRecord(value) {
289664
+ function isRecord$1(value) {
289553
289665
  return !!value && typeof value === 'object' && !Array.isArray(value);
289554
289666
  }
289555
289667
  /** A blank form for a platform that has never configured onboarding. */
@@ -289567,7 +289679,7 @@ function emptyUserOnboardingForm(title = '') {
289567
289679
  function coerceOnboardingAgent(raw) {
289568
289680
  var _a, _b;
289569
289681
  const value = parseMetadataValue(raw);
289570
- if (!isRecord(value))
289682
+ if (!isRecord$1(value))
289571
289683
  return null;
289572
289684
  const id = (_b = (_a = value.mentor_unique_id) !== null && _a !== void 0 ? _a : value.unique_id) !== null && _b !== void 0 ? _b : value.mentor;
289573
289685
  if (typeof id !== 'string' || !id.trim())
@@ -289612,10 +289724,10 @@ function coerceOnboardingAgents(rawAgents, rawAgent) {
289612
289724
  function coerceUserOnboardingForm(raw) {
289613
289725
  var _a;
289614
289726
  const value = parseMetadataValue(raw);
289615
- if (!isRecord(value))
289727
+ if (!isRecord$1(value))
289616
289728
  return emptyUserOnboardingForm();
289617
289729
  const sections = Array.isArray(value.sections)
289618
- ? value.sections.filter((section) => isRecord(section) && Array.isArray(section.fields))
289730
+ ? value.sections.filter((section) => isRecord$1(section) && Array.isArray(section.fields))
289619
289731
  : [];
289620
289732
  const agents = coerceOnboardingAgents(value.agents, value.agent);
289621
289733
  return {
@@ -300316,7 +300428,7 @@ const isEmailLike = (value) => {
300316
300428
  return dot > 0 && !domain.endsWith('.');
300317
300429
  };
300318
300430
  /** Trimmed string, or undefined for blanks, non-strings and placeholders. */
300319
- const clean = (value) => {
300431
+ const clean$1 = (value) => {
300320
300432
  if (typeof value !== 'string')
300321
300433
  return undefined;
300322
300434
  const trimmed = value.trim();
@@ -300324,7 +300436,7 @@ const clean = (value) => {
300324
300436
  };
300325
300437
  const firstOf = (...candidates) => {
300326
300438
  for (const candidate of candidates) {
300327
- const value = clean(candidate);
300439
+ const value = clean$1(candidate);
300328
300440
  if (value)
300329
300441
  return value;
300330
300442
  }
@@ -300360,12 +300472,12 @@ function resolveUserIdentity(source, options = {}) {
300360
300472
  // A bare `user` value is a username — unless it is a numeric id, which
300361
300473
  // names nobody: transcript rows carry `user: 1` beside `username: null`,
300362
300474
  // and showing "1" for that person is worse than "Anonymous".
300363
- const bareString = typeof record.user === 'string' ? clean(record.user) : undefined;
300475
+ const bareString = typeof record.user === 'string' ? clean$1(record.user) : undefined;
300364
300476
  const bareUser = bareString && !/^\d+$/.test(bareString) ? bareString : undefined;
300365
300477
  let email = firstOf(record.lti_email, record.email, record.user_email, inner === null || inner === void 0 ? void 0 : inner.lti_email, inner === null || inner === void 0 ? void 0 : inner.email, inner === null || inner === void 0 ? void 0 : inner.user_email);
300366
300478
  const platformUsername = firstOf(record.username, record.student, record.user_username, inner === null || inner === void 0 ? void 0 : inner.username, inner === null || inner === void 0 ? void 0 : inner.student, inner === null || inner === void 0 ? void 0 : inner.user_username, bareUser && !isEmailLike(bareUser) ? bareUser : undefined);
300367
300479
  let username = firstOf(record.lti_username, inner === null || inner === void 0 ? void 0 : inner.lti_username, platformUsername);
300368
- const composed = [clean(record.first_name), clean(record.last_name)].filter(Boolean).join(' ');
300480
+ const composed = [clean$1(record.first_name), clean$1(record.last_name)].filter(Boolean).join(' ');
300369
300481
  const name = firstOf(record.user_full_name, record.full_name, record.name, composed, inner === null || inner === void 0 ? void 0 : inner.user_full_name, inner === null || inner === void 0 ? void 0 : inner.full_name, inner === null || inner === void 0 ? void 0 : inner.name);
300370
300482
  // A bare string that looks like an email is an email, and so is a
300371
300483
  // "username" field that actually carries one.
@@ -303660,14 +303772,14 @@ function writeCoworkApprovals(mode) {
303660
303772
  }
303661
303773
  }
303662
303774
  /** True inside the Tauri desktop/mobile shell. */
303663
- const isTauriApp$3 = () => {
303775
+ const isTauriApp$4 = () => {
303664
303776
  if (typeof window === 'undefined')
303665
303777
  return false;
303666
303778
  return '__TAURI_INTERNALS__' in window || '__TAURI__' in window;
303667
303779
  };
303668
303780
  /** True on Tauri iOS/Android; false outside Tauri or without the OS plugin. */
303669
303781
  const isTauriMobile = async () => {
303670
- if (!isTauriApp$3())
303782
+ if (!isTauriApp$4())
303671
303783
  return false;
303672
303784
  try {
303673
303785
  const { platform } = await import('@tauri-apps/plugin-os');
@@ -303701,7 +303813,7 @@ function useChatMentorSettings(props = {}) {
303701
303813
  const COMMUNITY_MENTOR_VISIBILITY = MentorVisibilityEnum.VIEWABLE_BY_ANYONE;
303702
303814
  const isLoggedIn = Boolean(username);
303703
303815
  // Check if we're in Tauri offline mode
303704
- const isOffline = isTauriApp$3() && isTauriOfflineMode$1();
303816
+ const isOffline = isTauriApp$4() && isTauriOfflineMode$1();
303705
303817
  // Get cached data for offline mode
303706
303818
  const [cachedSettings, setCachedSettings] = useState(null);
303707
303819
  const [cachedPublicSettings, setCachedPublicSettings] = useState(null);
@@ -303744,12 +303856,12 @@ function useChatMentorSettings(props = {}) {
303744
303856
  });
303745
303857
  // Cache responses when online for offline use
303746
303858
  useEffect(() => {
303747
- if (isTauriApp$3() && !isOffline && mentorSettings && mentorId && tenantKey && username) {
303859
+ if (isTauriApp$4() && !isOffline && mentorSettings && mentorId && tenantKey && username) {
303748
303860
  setCachedApiResponse(CacheKeys.mentorSettings(tenantKey, mentorId, username), mentorSettings, { org: tenantKey, mentor: mentorId, userId: username });
303749
303861
  }
303750
303862
  }, [mentorSettings, mentorId, tenantKey, username, isOffline]);
303751
303863
  useEffect(() => {
303752
- if (isTauriApp$3() && !isOffline && mentorPublicSettings && mentorId && tenantKey) {
303864
+ if (isTauriApp$4() && !isOffline && mentorPublicSettings && mentorId && tenantKey) {
303753
303865
  setCachedApiResponse(CacheKeys.mentorPublicSettings(tenantKey, mentorId), mentorPublicSettings, { org: tenantKey, mentor: mentorId });
303754
303866
  }
303755
303867
  }, [mentorPublicSettings, mentorId, tenantKey, isOffline]);
@@ -305020,7 +305132,7 @@ const initialModelDownloadState = {
305020
305132
  * In Tauri 2.0, the global is __TAURI_INTERNALS__ (with withGlobalTauri: true)
305021
305133
  * We also check for __TAURI__ for backwards compatibility
305022
305134
  */
305023
- const isTauriApp$2 = () => {
305135
+ const isTauriApp$3 = () => {
305024
305136
  if (typeof window === 'undefined')
305025
305137
  return false;
305026
305138
  return '__TAURI_INTERNALS__' in window || '__TAURI__' in window;
@@ -305129,7 +305241,7 @@ function useTauri() {
305129
305241
  const [apis, setApis] = useState(null);
305130
305242
  useEffect(() => {
305131
305243
  // Check if we're in a Tauri environment
305132
- const inTauri = isTauriApp$2();
305244
+ const inTauri = isTauriApp$3();
305133
305245
  if (inTauri) {
305134
305246
  getTauriAPIs().then((result) => {
305135
305247
  setApis(result);
@@ -305574,7 +305686,7 @@ function useCuaDriver() {
305574
305686
  };
305575
305687
  }, [isAvailable, checkStatus]);
305576
305688
  // Only expose the feature as available inside the desktop (Tauri) app.
305577
- const finalIsAvailable = isAvailable && isTauriApp$2();
305689
+ const finalIsAvailable = isAvailable && isTauriApp$3();
305578
305690
  // Deliberately `=== true`, not `?? true`: until the first status check lands
305579
305691
  // we do not know whether this desktop session is one the driver can drive, and
305580
305692
  // offering Cowork optimistically would show the toggle to (say) a KDE user for
@@ -311400,7 +311512,7 @@ function useModelDownload() {
311400
311512
  (ollamaStatus === null || ollamaStatus === void 0 ? void 0 : ollamaStatus.installed) &&
311401
311513
  !(ollamaStatus === null || ollamaStatus === void 0 ? void 0 : ollamaStatus.model_installed) &&
311402
311514
  state.status === 'idle';
311403
- const finalIsAvailable = isAvailable && isTauriApp$2();
311515
+ const finalIsAvailable = isAvailable && isTauriApp$3();
311404
311516
  return {
311405
311517
  // State
311406
311518
  isAvailable: finalIsAvailable,
@@ -317455,7 +317567,7 @@ function AgentLLMTab({ showConfigurationHeader = true, mentorId: mentorIdOverrid
317455
317567
  // are absent, and a provider card that opens onto an empty picker is worse
317456
317568
  // than no card.
317457
317569
  const localOnlyProviders = React__default.useMemo(() => {
317458
- if (!isTauriApp$2())
317570
+ if (!isTauriApp$3())
317459
317571
  return [];
317460
317572
  const cloudKeys = new Set((llmProviders !== null && llmProviders !== void 0 ? llmProviders : []).map((p) => getProviderName(p.name)));
317461
317573
  const seen = new Set();
@@ -317477,7 +317589,7 @@ function AgentLLMTab({ showConfigurationHeader = true, mentorId: mentorIdOverrid
317477
317589
  // match the desktop catalog (openai, google, mistral…). Both inputs are fixed
317478
317590
  // for the life of the webview, so this never goes stale.
317479
317591
  const localProviderKeys = React__default.useMemo(() => {
317480
- if (!isTauriApp$2())
317592
+ if (!isTauriApp$3())
317481
317593
  return new Set();
317482
317594
  return new Set(localModelsForThisDevice().map((m) => getProviderName(m.provider)));
317483
317595
  }, []);
@@ -329717,6 +329829,9 @@ function WorkingIndicator({ phase, restatedByVisibleRow = false, content, classN
329717
329829
  // over as the progress indicator.
329718
329830
  const isStreamOnScreen = isWriting && (content !== null && content !== void 0 ? content : '').trim().length > 0;
329719
329831
  const [showReassurance, setShowReassurance] = useState(false);
329832
+ const rawLabel = phaseLabel(phase, t);
329833
+ // A new label is a sign of life (a Code turn moves step to step without
329834
+ // ever writing), so it restarts the clock.
329720
329835
  useEffect(() => {
329721
329836
  if (!isActive || isWriting) {
329722
329837
  setShowReassurance(false);
@@ -329724,13 +329839,13 @@ function WorkingIndicator({ phase, restatedByVisibleRow = false, content, classN
329724
329839
  }
329725
329840
  const timer = setTimeout(() => setShowReassurance(true), LONG_TURN_REASSURANCE_DELAY_MS);
329726
329841
  return () => clearTimeout(timer);
329727
- }, [isActive, isWriting]);
329842
+ }, [isActive, isWriting, rawLabel]);
329728
329843
  // The phase sticks at `writing` after the last token — it only moves when
329729
329844
  // some other signal arrives — so a mid-turn grind looks identical to a
329730
329845
  // healthy stream from the phase alone. The content clock is what separates
329731
329846
  // them, and it is why this component must not be unmounted while hidden.
329732
329847
  const isStreamStalled = useStalledStream(content, isActive, isWriting) && isStreamOnScreen;
329733
- const label = useThrottledPhaseLabel(phaseLabel(phase, t), isActive);
329848
+ const label = useThrottledPhaseLabel(rawLabel, isActive);
329734
329849
  // Nothing to add: the turn is over, a visible row already says this, or the
329735
329850
  // answer text is moving on its own.
329736
329851
  if (!isActive || restatedByVisibleRow || (isStreamOnScreen && !isStreamStalled)) {
@@ -329864,7 +329979,7 @@ function bubbleTodos(toolCalls, showReasoning) {
329864
329979
  * call to decide whether the standalone working placeholder is still needed, so
329865
329980
  * the two must stay in lockstep: exactly one agent frame per turn, never two.
329866
329981
  */
329867
- function hasVisibleBubbleContent({ content, message, reasoningContent, toolCalls, showReasoning, hasPermissionPrompts, }) {
329982
+ function hasVisibleBubbleContent({ content, message, reasoningContent, toolCalls, showReasoning, hasPermissionPrompts, hasCodeActivity, }) {
329868
329983
  var _a, _b;
329869
329984
  const hasReasoningToShow = !!(showReasoning && reasoningContent);
329870
329985
  const hasToolCallsToShow = hasGenericToolCalls(toolCalls, showReasoning);
@@ -329878,6 +329993,8 @@ function hasVisibleBubbleContent({ content, message, reasoningContent, toolCalls
329878
329993
  // silently stalled — and the standalone placeholder would keep its own
329879
329994
  // frame up alongside the prompt.
329880
329995
  !!hasPermissionPrompts ||
329996
+ // Likewise a plan that arrives before the first step (Codex plans first).
329997
+ !!hasCodeActivity ||
329881
329998
  !!((_b = message === null || message === void 0 ? void 0 : message.actions) === null || _b === void 0 ? void 0 : _b.length) ||
329882
329999
  hasArtifactVersions(message));
329883
330000
  }
@@ -329900,6 +330017,416 @@ function AIWorkingMessage({ phase, profileImage, mentorName, timestamp, }) {
329900
330017
  return (jsx("div", { "data-testid": "chat-working-message", children: jsx(AIMessageFrame, { profileImage: profileImage, mentorName: mentorName, timestamp: timestamp, children: jsx("div", { className: "mb-1.5 rounded-2xl bg-gray-100 p-3 wrap-anywhere", children: jsx(WorkingIndicator, { phase: phase }) }) }) }));
329901
330018
  }
329902
330019
 
330020
+ const MAX_INPUT_STRING = 2000;
330021
+ const MAX_ERROR = 500;
330022
+ const PREVIEW_HOSTS = new Set(['localhost', '127.0.0.1', '[::1]']);
330023
+ // C0/C1 controls, zero-widths and the bidi controls that could fake a file's extension.
330024
+ const UNSAFE_CHARS = /[\u0000-\u001f\u007f-\u009f\u061c\u200b-\u200f\u202a-\u202e\u2060\u2066-\u2069\ufeff]/g;
330025
+ // The same set minus tab and newline, for literals shown whole: a command keeps its own
330026
+ // lines and gains none (U+2028/9 break lines without being newlines).
330027
+ const UNSAFE_DETAIL_CHARS = /[\u0000-\u0008\u000b-\u001f\u007f-\u009f\u061c\u200b-\u200f\u2028-\u202e\u2060\u2066-\u2069\ufeff]/g;
330028
+ function isRecord(value) {
330029
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
330030
+ }
330031
+ function text(value) {
330032
+ return typeof value === 'string' && value.trim() ? value : undefined;
330033
+ }
330034
+ /** Display-safe: controls stripped, whitespace collapsed, cut by code points. */
330035
+ function clean(value, max) {
330036
+ const chars = Array.from(value.replace(UNSAFE_CHARS, '').replace(/\s+/g, ' ').trim());
330037
+ return chars.length > max ? `${chars.slice(0, max).join('')}…` : chars.join('');
330038
+ }
330039
+ /** A command, path or failure text the user will judge: nothing that hides or reorders it. */
330040
+ function safeDetail(value) {
330041
+ return (value === null || value === void 0 ? void 0 : value.replace(UNSAFE_DETAIL_CHARS, '')) || undefined;
330042
+ }
330043
+ /** `about/page.tsx`: Next apps are full of `page.tsx`, so one segment is ambiguous. */
330044
+ function shortPath(path) {
330045
+ const parts = path.split(/[\\/]+/).filter(Boolean);
330046
+ return clean(parts.slice(-2).join('/'), 48);
330047
+ }
330048
+ function hostOf(url) {
330049
+ try {
330050
+ return new URL(url).hostname.replace(/^www\./, '') || undefined;
330051
+ }
330052
+ catch (_a) {
330053
+ return undefined;
330054
+ }
330055
+ }
330056
+ // ponytail: two command shapes recognised (install, preview); add a third when a row reads too vaguely.
330057
+ function commandAction(command) {
330058
+ let bare = command.trim();
330059
+ for (let i = 0; i < 4; i += 1) {
330060
+ const next = bare
330061
+ .replace(/^cd\s+\S+\s*&&\s*/, '')
330062
+ .replace(/^[A-Za-z_][A-Za-z0-9_]*=\S*\s+/, '');
330063
+ if (next === bare)
330064
+ break;
330065
+ bare = next;
330066
+ }
330067
+ if (/^(?:npm|pnpm|yarn|bun)\s+(?:i|install|add|ci)\b/.test(bare)) {
330068
+ return 'install';
330069
+ }
330070
+ if (/^(?:npm|pnpm|yarn|bun)\s+(?:run\s+)?(?:dev|start|preview)\b/.test(bare) ||
330071
+ /^(?:npx\s+)?(?:next\s+dev|vite)\b/.test(bare)) {
330072
+ return 'preview';
330073
+ }
330074
+ return 'run';
330075
+ }
330076
+ /** Finished steps stay finished; pending, in_progress and the unknown all run. */
330077
+ function statusOf(raw, prev) {
330078
+ if (prev !== 'running')
330079
+ return prev;
330080
+ if (raw === 'completed')
330081
+ return 'done';
330082
+ if (raw === 'failed')
330083
+ return 'failed';
330084
+ return 'running';
330085
+ }
330086
+ // ponytail: top-level strings only; clip nested payloads if a turn's facts ever weigh.
330087
+ function clipStrings(input) {
330088
+ return Object.fromEntries(Object.entries(input).map(([key, value]) => [
330089
+ key,
330090
+ typeof value === 'string' && value.length > MAX_INPUT_STRING
330091
+ ? `${value.slice(0, MAX_INPUT_STRING)}…`
330092
+ : value,
330093
+ ]));
330094
+ }
330095
+ function diffsOf(content) {
330096
+ if (!Array.isArray(content))
330097
+ return [];
330098
+ const diffs = [];
330099
+ for (const item of content) {
330100
+ if (isRecord(item) && item.type === 'diff' && text(item.path)) {
330101
+ diffs.push({ path: item.path, isNew: item.oldText == null });
330102
+ }
330103
+ }
330104
+ return diffs;
330105
+ }
330106
+ function errorOf(content) {
330107
+ if (typeof content === 'string')
330108
+ return text(content);
330109
+ if (!Array.isArray(content))
330110
+ return undefined;
330111
+ const lines = content.flatMap((item) => isRecord(item) &&
330112
+ item.type === 'content' &&
330113
+ isRecord(item.content) &&
330114
+ typeof item.content.text === 'string'
330115
+ ? [item.content.text]
330116
+ : []);
330117
+ return text(lines.join('\n'));
330118
+ }
330119
+ function pathsOf(update, input, diffs) {
330120
+ const paths = new Set();
330121
+ if (Array.isArray(update.locations)) {
330122
+ for (const location of update.locations) {
330123
+ const path = isRecord(location) ? text(location.path) : undefined;
330124
+ if (path)
330125
+ paths.add(path);
330126
+ }
330127
+ }
330128
+ for (const diff of diffs)
330129
+ paths.add(diff.path);
330130
+ for (const key of ['file_path', 'filePath', 'path']) {
330131
+ const path = text(input[key]);
330132
+ if (path)
330133
+ paths.add(path);
330134
+ }
330135
+ return [...paths];
330136
+ }
330137
+ /**
330138
+ * ACP ToolCallUpdate semantics, hardened: only present, non-blank fields
330139
+ * overwrite (Claude's result update has no title or kind), the tool name is
330140
+ * set once (opencode's pending title IS the tool name), `content` and
330141
+ * `locations` replace but never blank a subject already known, and nothing
330142
+ * from `_meta` or a tool's output is kept.
330143
+ */
330144
+ function mergeToolCall(prev, update) {
330145
+ var _a, _b, _c, _d, _e, _f, _g;
330146
+ const base = prev !== null && prev !== void 0 ? prev : {
330147
+ status: 'running',
330148
+ input: {},
330149
+ paths: [],
330150
+ diffs: [],
330151
+ };
330152
+ const meta = isRecord(update._meta) ? update._meta : {};
330153
+ const claude = isRecord(meta.claudeCode) ? meta.claudeCode : {};
330154
+ const input = isRecord(update.rawInput) && Object.keys(update.rawInput).length > 0
330155
+ ? clipStrings(update.rawInput)
330156
+ : base.input;
330157
+ const freshDiffs = diffsOf(update.content);
330158
+ const diffs = freshDiffs.length > 0 ? freshDiffs : base.diffs;
330159
+ const found = pathsOf(update, input, diffs);
330160
+ const status = statusOf(update.status, base.status);
330161
+ return {
330162
+ name: (_c = (_b = (_a = base.name) !== null && _a !== void 0 ? _a : text(claude.toolName)) !== null && _b !== void 0 ? _b : text(update.name)) !== null && _c !== void 0 ? _c : text(update.title),
330163
+ title: (_d = text(update.title)) !== null && _d !== void 0 ? _d : base.title,
330164
+ kind: (_e = text(update.kind)) !== null && _e !== void 0 ? _e : base.kind,
330165
+ status,
330166
+ input,
330167
+ paths: found.length > 0 ? found : base.paths,
330168
+ diffs,
330169
+ error: status === 'failed'
330170
+ ? ((_g = (_f = errorOf(update.content)) === null || _f === void 0 ? void 0 : _f.slice(0, MAX_ERROR)) !== null && _g !== void 0 ? _g : base.error)
330171
+ : undefined,
330172
+ };
330173
+ }
330174
+ /** The plain-words reading of a tool call. Never null: the vaguest is `other`. */
330175
+ function describeStep(facts, id) {
330176
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o;
330177
+ const name = ((_a = facts.name) !== null && _a !== void 0 ? _a : '').toLowerCase();
330178
+ const kind = ((_b = facts.kind) !== null && _b !== void 0 ? _b : '').toLowerCase();
330179
+ const title = (_c = facts.title) !== null && _c !== void 0 ? _c : '';
330180
+ const { input, paths, diffs } = facts;
330181
+ const is = (...names) => names.includes(name) || names.includes(kind);
330182
+ const file = paths[0] ? { file: shortPath(paths[0]) } : {};
330183
+ const allPaths = paths.join('\n') || undefined;
330184
+ const step = (action, values = {}, details) => ({
330185
+ id,
330186
+ action,
330187
+ status: facts.status,
330188
+ values,
330189
+ details: safeDetail([details, facts.error].filter(Boolean).join('\n')),
330190
+ });
330191
+ if (Array.isArray(input.todos) || is('todowrite', 'todoread')) {
330192
+ return step('plan');
330193
+ }
330194
+ const mcp = (_d = name.match(/^mcp__(.+?)__(.+)$/)) !== null && _d !== void 0 ? _d : title.match(/^mcp\.([^.]+)\.(.+)$/);
330195
+ if (mcp) {
330196
+ return step('connector', { name: clean(mcp[2].replace(/_/g, ' '), 48) }, title);
330197
+ }
330198
+ if (is('skill') || text(input.skill)) {
330199
+ return step('skill', {}, (_f = (_e = text(input.skill)) !== null && _e !== void 0 ? _e : text(input.name)) !== null && _f !== void 0 ? _f : title);
330200
+ }
330201
+ const description = text(input.description);
330202
+ if (is('task', 'agent') || text(input.subagent_type) || text(input.agentThreadId)) {
330203
+ const prompt = text(input.prompt);
330204
+ const excerpt = prompt ? clean(prompt, 300) : undefined;
330205
+ return description
330206
+ ? step('helper', { description: clean(description, 120) }, excerpt)
330207
+ : step('helperPlain', {}, excerpt);
330208
+ }
330209
+ if (is('exitplanmode') || kind === 'switch_mode') {
330210
+ return step('approve', {}, text(input.plan));
330211
+ }
330212
+ if (is('askuserquestion'))
330213
+ return step('ask', {}, title);
330214
+ const command = (_h = (_g = text(input.command)) !== null && _g !== void 0 ? _g : text(input.cmd)) !== null && _h !== void 0 ? _h : text(input.script);
330215
+ if (command || is('bash', 'shell', 'powershell')) {
330216
+ if (description) {
330217
+ return step('runDescribed', { description: clean(description, 120) }, command);
330218
+ }
330219
+ return step(command ? commandAction(command) : 'run', {}, command);
330220
+ }
330221
+ const query = (_j = text(input.query)) !== null && _j !== void 0 ? _j : (_k = title.match(/^Web search: (.+)$/)) === null || _k === void 0 ? void 0 : _k[1];
330222
+ const url = (_m = (_l = text(input.url)) !== null && _l !== void 0 ? _l : (isRecord(input.action) ? text(input.action.url) : undefined)) !== null && _m !== void 0 ? _m : (_o = title.match(/^Open page: (.+)$/)) === null || _o === void 0 ? void 0 : _o[1];
330223
+ if (is('websearch') || (query && !url && is('search', 'fetch'))) {
330224
+ return step('web', { query: clean(query !== null && query !== void 0 ? query : title, 60) });
330225
+ }
330226
+ if (url || is('fetch', 'webfetch')) {
330227
+ const host = url ? hostOf(url) : undefined;
330228
+ if (!host)
330229
+ return step('other', {}, url !== null && url !== void 0 ? url : title);
330230
+ return PREVIEW_HOSTS.has(host)
330231
+ ? step('openPreview', {}, url)
330232
+ : step('open', { host: clean(host, 48) }, url);
330233
+ }
330234
+ // ACP's command kind, once a command or an address would have been read above.
330235
+ if (kind === 'execute')
330236
+ return step('run', {}, title);
330237
+ if (is('delete')) {
330238
+ return paths.length > 1
330239
+ ? step('removeMany', { count: paths.length }, allPaths)
330240
+ : step('remove', file, allPaths);
330241
+ }
330242
+ if (kind === 'move')
330243
+ return step('move', file, allPaths);
330244
+ if (is('edit', 'write', 'patch', 'apply_patch', 'multiedit', 'notebookedit')) {
330245
+ const creates = diffs.length > 0 ? diffs.every((d) => d.isNew) : is('write');
330246
+ if (creates)
330247
+ return step('create', file, allPaths);
330248
+ if (paths.length > 1)
330249
+ return step('editMany', { count: paths.length }, allPaths);
330250
+ return step('edit', file, allPaths);
330251
+ }
330252
+ const listing = /^list\b/.test(name) || /^list files/i.test(title);
330253
+ if (is('read') && !listing)
330254
+ return step('read', file, allPaths);
330255
+ if (listing || is('glob', 'grep', 'codesearch', 'list', 'search')) {
330256
+ return step('search', {}, text(input.pattern));
330257
+ }
330258
+ if (kind === 'think')
330259
+ return step('think', {}, title);
330260
+ return step('other', {}, title);
330261
+ }
330262
+ function stepSentence(t, step, form) {
330263
+ return t(`chat.chatCodeActivity.${step.action}`, {
330264
+ form,
330265
+ file: t('chat.chatCodeActivity.aFile'),
330266
+ count: 0,
330267
+ description: '',
330268
+ host: '',
330269
+ query: '',
330270
+ name: '',
330271
+ ...step.values,
330272
+ });
330273
+ }
330274
+ /**
330275
+ * The working line's phase for a Code turn: reply text first (so the stalled-
330276
+ * reply reassurance still works when a step never reports completion), then
330277
+ * the latest step while it runs (an older stuck step never shows stale), else
330278
+ * thinking. `workflow` rather than `tool`: the line narrates, no row animates.
330279
+ */
330280
+ function codeTurnPhase(steps, content, t) {
330281
+ if ((content !== null && content !== void 0 ? content : '').trim())
330282
+ return { kind: 'writing' };
330283
+ const last = steps[steps.length - 1];
330284
+ if ((last === null || last === void 0 ? void 0 : last.status) === 'running') {
330285
+ return { kind: 'workflow', detail: stepSentence(t, last, 'running') };
330286
+ }
330287
+ return { kind: 'thinking' };
330288
+ }
330289
+ // ---------------------------------------------------------------------------
330290
+ // Shared store
330291
+ // ---------------------------------------------------------------------------
330292
+ const EMPTY_TURN = { steps: [] };
330293
+ // ponytail: kept for the app session like the SDK's tool calls; 200 turns is a few MB at worst.
330294
+ const MAX_TURNS = 200;
330295
+ const turns = new Map();
330296
+ const facts = new Map();
330297
+ const subscribers$1 = new Set();
330298
+ let listening$1 = false;
330299
+ function publish$1() {
330300
+ subscribers$1.forEach((notify) => notify());
330301
+ }
330302
+ function turnFor(generationId) {
330303
+ const existing = turns.get(generationId);
330304
+ if (existing)
330305
+ return existing;
330306
+ if (turns.size >= MAX_TURNS) {
330307
+ const oldest = turns.keys().next().value;
330308
+ if (oldest !== undefined) {
330309
+ turns.delete(oldest);
330310
+ facts.delete(oldest);
330311
+ }
330312
+ }
330313
+ turns.set(generationId, EMPTY_TURN);
330314
+ return EMPTY_TURN;
330315
+ }
330316
+ /** ACP plan entries and opencode's `todowrite` rows through the SDK's normaliser. */
330317
+ function todosOf(entries) {
330318
+ if (!Array.isArray(entries))
330319
+ return undefined;
330320
+ return extractLatestTodos([
330321
+ {
330322
+ id: '',
330323
+ name: WRITE_TODOS_TOOL,
330324
+ input: { todos: entries },
330325
+ log: '',
330326
+ result: '',
330327
+ },
330328
+ ]);
330329
+ }
330330
+ function applyToolCall(generationId, update) {
330331
+ var _a;
330332
+ const id = update ? text(update.toolCallId) : undefined;
330333
+ if (!generationId || !id || !update)
330334
+ return;
330335
+ const turn = turnFor(generationId);
330336
+ const byId = (_a = facts.get(generationId)) !== null && _a !== void 0 ? _a : new Map();
330337
+ facts.set(generationId, byId);
330338
+ const merged = mergeToolCall(byId.get(id), update);
330339
+ byId.set(id, merged);
330340
+ const step = describeStep(merged, id);
330341
+ let next;
330342
+ if (step.action === 'plan') {
330343
+ // A todo tool recognised only once its input arrived may already sit in the list as a row.
330344
+ const steps = turn.steps.filter((s) => s.id !== id);
330345
+ const plan = Array.isArray(merged.input.todos) ? todosOf(merged.input.todos) : turn.plan;
330346
+ if (plan !== turn.plan || steps.length !== turn.steps.length) {
330347
+ next = { ...turn, steps, plan };
330348
+ }
330349
+ }
330350
+ else {
330351
+ const index = turn.steps.findIndex((s) => s.id === id);
330352
+ if (index < 0) {
330353
+ next = { ...turn, steps: [...turn.steps, step] };
330354
+ }
330355
+ else if (JSON.stringify(turn.steps[index]) !== JSON.stringify(step)) {
330356
+ const steps = turn.steps.slice();
330357
+ steps[index] = step;
330358
+ next = { ...turn, steps };
330359
+ }
330360
+ }
330361
+ if (!next)
330362
+ return;
330363
+ turns.set(generationId, next);
330364
+ publish$1();
330365
+ }
330366
+ function applyPlan(generationId, update) {
330367
+ const entries = update === null || update === void 0 ? void 0 : update.entries;
330368
+ if (!generationId || !Array.isArray(entries))
330369
+ return;
330370
+ // An empty list clears the plan, as the SDK's `bubbleTodos` does.
330371
+ turns.set(generationId, { ...turnFor(generationId), plan: todosOf(entries) });
330372
+ publish$1();
330373
+ }
330374
+ /** A crash-respawn into the same generation starts over, as the SDK does. */
330375
+ function clearTurn(generationId) {
330376
+ if (!generationId || !turns.delete(generationId))
330377
+ return;
330378
+ facts.delete(generationId);
330379
+ publish$1();
330380
+ }
330381
+ function isTauriApp$2() {
330382
+ return typeof window !== 'undefined' && '__TAURI__' in window;
330383
+ }
330384
+ async function startListening$1() {
330385
+ if (listening$1 || !isTauriApp$2())
330386
+ return;
330387
+ listening$1 = true;
330388
+ const { listen } = await import('@tauri-apps/api/event');
330389
+ await listen('opencode:tool_call', (evt) => applyToolCall(evt.payload.generation_id, evt.payload.update));
330390
+ await listen('opencode:plan', (evt) => applyPlan(evt.payload.generation_id, evt.payload.update));
330391
+ await listen('ollama:restart', (evt) => clearTurn(evt.payload.generation_id));
330392
+ }
330393
+ // A new chat's first step lands before any bubble mounts, and the listeners
330394
+ // deliberately outlive every subscriber, as the permission store's do.
330395
+ void startListening$1();
330396
+ function subscribe$2(notify) {
330397
+ subscribers$1.add(notify);
330398
+ void startListening$1();
330399
+ return () => {
330400
+ subscribers$1.delete(notify);
330401
+ };
330402
+ }
330403
+ function useCodeTurn(generationId) {
330404
+ return useSyncExternalStore(subscribe$2, () => (generationId && turns.get(generationId)) || EMPTY_TURN, () => EMPTY_TURN);
330405
+ }
330406
+ /** Distinct shapes, never colour alone (WCAG 1.4.1), with an sr-only label. */
330407
+ const ROW_META = {
330408
+ running: { Icon: CircleDot$1, labelKey: 'statusRunning' },
330409
+ done: { Icon: CircleCheck, labelKey: 'statusDone' },
330410
+ failed: { Icon: CircleX, labelKey: 'statusFailed' },
330411
+ stopped: { Icon: Circle, labelKey: 'statusStopped' },
330412
+ };
330413
+ const StepRow = React__default.memo(function StepRow({ step, stale, }) {
330414
+ const t = useChatT();
330415
+ const status = stale ? 'stopped' : step.status;
330416
+ const { Icon, labelKey } = ROW_META[status];
330417
+ const body = (jsxs(Fragment$1, { children: [jsx(Icon, { "aria-hidden": "true", className: "mt-0.5 h-3 w-3 shrink-0 text-gray-400" }), jsx("span", { className: "sr-only", children: t(`chat.chatCodeActivity.${labelKey}`) }), jsx("span", { className: "min-w-0 flex-1 text-gray-700 dark:text-gray-300", children: stepSentence(t, step, step.status) })] }));
330418
+ return (jsx("li", { "data-testid": "code-activity-step", "data-status": status, children: step.details ? (jsxs("details", { children: [jsx("summary", { className: "flex cursor-pointer list-none items-start gap-1.5 [&::-webkit-details-marker]:hidden", children: body }), jsx("code", { "data-testid": "code-activity-details", className: "mt-1 ml-[18px] block rounded bg-gray-200 px-1.5 py-1 font-mono break-all whitespace-pre-wrap text-gray-700", children: step.details })] })) : (jsx("div", { className: "flex items-start gap-1.5", children: body })) }));
330419
+ });
330420
+ function CodeActivity({ generationId, isCurrentlyStreaming = false, }) {
330421
+ const t = useChatT();
330422
+ const { steps } = useCodeTurn(generationId);
330423
+ // Folded by default and never animated: the working line narrates the live step.
330424
+ const [isOpen, setIsOpen] = useState(false);
330425
+ if (steps.length === 0)
330426
+ return null;
330427
+ return (jsxs(Collapsible, { open: isOpen, onOpenChange: setIsOpen, className: "mb-2", "data-testid": "code-activity", children: [jsxs(CollapsibleTrigger, { className: "flex cursor-pointer items-center gap-1 pt-1 text-xs text-gray-500 transition-colors hover:text-gray-600 dark:text-gray-400 dark:hover:text-gray-300", "data-testid": "code-activity-trigger", children: [jsx(ChevronRight, { className: cn('h-3 w-3 shrink-0 transition-transform duration-200', isOpen && 'rotate-90') }), jsx("span", { className: "font-medium", children: t('chat.chatCodeActivity.steps', { count: steps.length }) })] }), jsx(CollapsibleContent, { className: "pb-2 pl-4", children: jsx("ol", { className: "space-y-1.5 border-l-2 border-gray-200 pt-2 pl-3 text-xs leading-relaxed dark:border-gray-700", "data-testid": "code-activity-steps", children: steps.map((step) => (jsx(StepRow, { step: step, stale: !isCurrentlyStreaming && step.status === 'running' }, step.id))) }) })] }));
330428
+ }
330429
+
329903
330430
  function isTauriApp$1() {
329904
330431
  return typeof window !== 'undefined' && '__TAURI__' in window;
329905
330432
  }
@@ -329989,17 +330516,27 @@ function resetCodePermissionsForTests() {
329989
330516
  listening = false;
329990
330517
  subscribers.forEach((notify) => notify());
329991
330518
  }
329992
- /** ACP ToolKind → the i18n key naming the operation, so the user sees what's at stake. */
329993
- const KIND_LABELS = {
329994
- read: 'read',
329995
- edit: 'write',
329996
- delete: 'delete',
329997
- move: 'move',
329998
- search: 'search',
329999
- execute: 'exec',
330000
- fetch: 'fetch',
330001
- think: 'think',
330002
- };
330519
+ /**
330520
+ * A request without a tool call (a paired phone, an older binary, a Browse run)
330521
+ * described from its kind: a phone's `command` holds command patterns for bash,
330522
+ * file patterns for edit, URL patterns for webfetch.
330523
+ */
330524
+ function legacyToolCall(request) {
330525
+ var _a, _b;
330526
+ const kind = (_a = request.kind) !== null && _a !== void 0 ? _a : '';
330527
+ const value = (_b = request.command) !== null && _b !== void 0 ? _b : undefined;
330528
+ if (/^(execute|bash|shell)$/.test(kind)) {
330529
+ return { title: request.title, kind, rawInput: { command: value } };
330530
+ }
330531
+ if (/^(fetch|webfetch)$/.test(kind)) {
330532
+ return { title: request.title, kind, rawInput: { url: value } };
330533
+ }
330534
+ return {
330535
+ title: request.title,
330536
+ kind,
330537
+ locations: value === null || value === void 0 ? void 0 : value.split(/\s+/).map((path) => ({ path })),
330538
+ };
330539
+ }
330003
330540
  function CodePermissionCards({ generationId, }) {
330004
330541
  const all = useCodePermissionRequests();
330005
330542
  const requests = all.filter((r) => r.generation_id === generationId);
@@ -330023,20 +330560,28 @@ function CodePermissionCards({ generationId, }) {
330023
330560
  console.error('[code-permission] respond failed', e);
330024
330561
  }
330025
330562
  };
330026
- if (requests.length === 0)
330027
- return null;
330028
330563
  return (
330029
- // Same visual language as ToolCallIndicator directly above it — gray left rail,
330030
- // xs gray text, 18px sub-indent (12px icon + 6px gap). A white bordered card here
330031
- // shouted next to that quiet list; this reads as a continuation of the agent's
330032
- // activity, which is what it is. Only the buttons carry colour.
330033
- jsx("div", { className: "mb-2 space-y-3 border-l-2 border-gray-200 pt-1 pl-3 text-xs leading-relaxed", children: requests.map((request) => {
330034
- var _a, _b;
330035
- return (jsxs("div", { children: [jsxs("div", { className: "flex flex-wrap items-center gap-1.5 text-gray-600 dark:text-gray-300", children: [jsx(ShieldCheck, { className: "h-3 w-3 shrink-0 text-gray-400" }), jsx("span", { className: "font-medium", children: t('chat.chatCodePermissionCard.title') }), jsx("span", { className: "rounded bg-gray-200 px-1 py-px font-mono text-[10px] tracking-wide text-gray-500 uppercase", children: t(`chat.chatCodePermissionCard.kind.${(_b = KIND_LABELS[(_a = request.kind) !== null && _a !== void 0 ? _a : '']) !== null && _b !== void 0 ? _b : 'other'}`) })] }), jsx("div", { className: "mt-0.5 ml-[18px] text-gray-400 dark:text-gray-500", children: request.title || t('chat.chatCodePermissionCard.unnamedAction') }), request.command && (
330036
- // bg-gray-200 is what the bubble already uses for inline code and pre
330037
- // blocks, so the command sits on the same surface as the reply's own.
330038
- jsx("code", { className: "mt-1 ml-[18px] block rounded bg-gray-200 px-1.5 py-1 font-mono break-all text-gray-700", children: request.command })), jsxs("div", { className: "mt-2 ml-[18px] flex items-center gap-2", children: [jsx(Button$1, { size: "sm", type: "button", className: "ibl-button-primary h-7 text-xs", onClick: () => answer(request, request.allow_option_id), children: t('chat.chatCodePermissionCard.allow') }), jsx(Button$1, { variant: "outline", size: "sm", type: "button", className: "h-7 text-xs", onClick: () => answer(request, request.reject_option_id), children: t('chat.chatCodePermissionCard.deny') })] })] }, request.request_id));
330039
- }) }));
330564
+ // Mounted empty for the whole turn, so the first card is a mutation screen
330565
+ // readers announce rather than content they never see arrive.
330566
+ jsx("div", { "aria-live": "polite", "data-testid": "code-permission-cards", children: requests.length > 0 && (
330567
+ // Same visual language as ToolCallIndicator directly above it — gray left rail,
330568
+ // xs gray text, 18px sub-indent (12px icon + 6px gap). A white bordered card here
330569
+ // shouted next to that quiet list; this reads as a continuation of the agent's
330570
+ // activity, which is what it is. Only the buttons carry colour.
330571
+ jsx("div", { className: "mb-2 space-y-3 border-l-2 border-gray-200 pt-1 pl-3 text-xs leading-relaxed", children: requests.map((request) => {
330572
+ var _a, _b, _c, _d;
330573
+ const step = describeStep(mergeToolCall(undefined, (_a = request.tool_call) !== null && _a !== void 0 ? _a : legacyToolCall(request)), request.request_id);
330574
+ // A Browse run (own responder) keeps its own title; anything else described gets a sentence.
330575
+ const named = !request.respond && step.action !== 'other';
330576
+ const shown = (_c = safeDetail((_b = request.command) !== null && _b !== void 0 ? _b : undefined)) !== null && _c !== void 0 ? _c : (named ? step.details : undefined);
330577
+ return (jsxs("div", { children: [jsxs("div", { className: "flex flex-wrap items-center gap-1.5 text-gray-600 dark:text-gray-300", children: [jsx(ShieldCheck, { className: "h-3 w-3 shrink-0 text-gray-400" }), jsx("span", { className: "font-medium", children: t('chat.chatCodePermissionCard.title') })] }), jsx("div", { className: "mt-0.5 ml-[18px] text-gray-400 dark:text-gray-500", children: named
330578
+ ? stepSentence(t, step, 'want')
330579
+ : safeDetail((_d = request.title) !== null && _d !== void 0 ? _d : undefined) ||
330580
+ t('chat.chatCodePermissionCard.unnamedAction') }), shown && (
330581
+ // bg-gray-200 is what the bubble already uses for inline code and pre
330582
+ // blocks, so the command sits on the same surface as the reply's own.
330583
+ jsx("code", { className: "mt-1 ml-[18px] block rounded bg-gray-200 px-1.5 py-1 font-mono break-all whitespace-pre-wrap text-gray-700", children: shown })), jsxs("div", { className: "mt-2 ml-[18px] flex items-center gap-2", children: [jsx(Button$1, { size: "sm", type: "button", className: "ibl-button-primary h-7 text-xs", onClick: () => answer(request, request.allow_option_id), children: t('chat.chatCodePermissionCard.allow') }), jsx(Button$1, { variant: "outline", size: "sm", type: "button", className: "h-7 text-xs", onClick: () => answer(request, request.reject_option_id), children: t('chat.chatCodePermissionCard.deny') })] })] }, request.request_id));
330584
+ }) })) }));
330040
330585
  }
330041
330586
 
330042
330587
  /**
@@ -331150,7 +331695,8 @@ function AgentTodoList({ todos, isCurrentlyStreaming = false }) {
331150
331695
  }
331151
331696
  const summary = t('chat.chatAiMessageBubble.agentTodoProgress', { done, total });
331152
331697
  return (jsxs(Collapsible, { open: isOpen, onOpenChange: setIsOpen, className: "mb-2", "data-testid": "agent-todo-list", children: [jsxs(CollapsibleTrigger, { className: "flex cursor-pointer items-center gap-1 pt-1 text-xs text-gray-500 transition-colors hover:text-gray-600 dark:text-gray-400 dark:hover:text-gray-300", "data-testid": "agent-todo-list-trigger", children: [jsx(ChevronRight, { className: cn('h-3 w-3 shrink-0 transition-transform duration-200', isOpen && 'rotate-90') }), jsx("span", { className: "font-medium", children: t('chat.chatAiMessageBubble.agentTodoListTitle') }), jsxs("span", { className: "text-gray-400 dark:text-gray-500", "data-testid": "agent-todo-list-progress", children: ["\u2014 ", summary] })] }), jsx(CollapsibleContent, { className: "pb-2 pl-4", children: jsx("ol", { className: "space-y-1.5 border-l-2 border-gray-200 pt-2 pl-3 text-xs leading-relaxed dark:border-gray-700", "data-testid": "agent-todo-list-items", children: items.map((todo, index) => {
331153
- const meta = getStatusMeta(todo.status);
331698
+ // An unfinished step after the turn ended must not keep shimmering.
331699
+ const meta = getStatusMeta(todo.status === 'in_progress' && !isCurrentlyStreaming ? 'pending' : todo.status);
331154
331700
  const { Icon } = meta;
331155
331701
  const statusLabel = t(`chat.chatAiMessageBubble.${meta.labelKey}`);
331156
331702
  return (jsxs("li", { className: "flex items-start gap-1.5", "data-testid": "agent-todo-item", "data-status": todo.status, children: [jsx(Icon, { "aria-hidden": "true", className: cn('mt-0.5 h-3 w-3 shrink-0', meta.iconClass) }), jsx("span", { className: "sr-only", children: statusLabel }), jsx("span", { className: cn('min-w-0 flex-1', meta.contentClass), children: todo.content })] }, `${index}-${todo.content}`));
@@ -331170,7 +331716,7 @@ const mapActionToCallback = (key, joinTenant) => ({
331170
331716
  })[key];
331171
331717
  /** The forwarded ref lands on the Copy button (the chat focuses it when a reply settles). */
331172
331718
  const AIMessageBubble = forwardRef(function AIMessageBubble({ content, profileImage, mentorName, timestamp, sessionId, mentorId, onRetry, messages, message, tenantKey, onOpenCanvas, streamingArtifactId, reasoningContent, toolCalls, isCurrentlyStreaming, showReasoning, workingPhase, }, ref) {
331173
- var _a, _b;
331719
+ var _a, _b, _c;
331174
331720
  const t = useChatT();
331175
331721
  const host = useChatHost();
331176
331722
  // OS `redirectToAuthSpaJoinTenant()`: the host's callback, else web-utils'
@@ -331215,7 +331761,14 @@ const AIMessageBubble = forwardRef(function AIMessageBubble({ content, profileIm
331215
331761
  // that spends minutes running commands would otherwise look frozen.
331216
331762
  const isCodeTurn = typeof (message === null || message === void 0 ? void 0 : message.id) === 'string' && message.id.startsWith('opencode-');
331217
331763
  const showAgentActivity = showReasoning || isCodeTurn;
331218
- // The reasoning section and tool-call indicator are gated by that flag.
331764
+ // A Code turn's steps and plan come from the OS store, in plain words; the
331765
+ // generic tool list only ever showed raw agent titles.
331766
+ const codeTurn = useCodeTurn(isCodeTurn ? message.id : undefined);
331767
+ // Code and Browse turns raise permission cards; their live region must exist first.
331768
+ const hostsPermissionCards = !!isCurrentlyStreaming &&
331769
+ typeof (message === null || message === void 0 ? void 0 : message.id) === 'string' &&
331770
+ /^(?:opencode|browse)-/.test(message.id);
331771
+ // The reasoning section and tool-call indicator are gated by `showAgentActivity`.
331219
331772
  // While that's off, an assistant message that is still streaming has no text
331220
331773
  // yet — without the verbose surfaces there would be nothing to show, so the
331221
331774
  // bubble would render as an empty gray box. Skip rendering entirely until the
@@ -331231,24 +331784,31 @@ const AIMessageBubble = forwardRef(function AIMessageBubble({ content, profileIm
331231
331784
  toolCalls,
331232
331785
  showReasoning: showAgentActivity,
331233
331786
  hasPermissionPrompts,
331787
+ hasCodeActivity: codeTurn.steps.length > 0 || !!((_b = codeTurn.plan) === null || _b === void 0 ? void 0 : _b.length),
331234
331788
  });
331235
331789
  if (!hasVisibleContent) {
331236
331790
  return null;
331237
331791
  }
331238
331792
  const showReasoningSection = Boolean(showAgentActivity && reasoningContent);
331239
- const showToolCalls = hasGenericToolCalls(toolCalls, showAgentActivity);
331240
- const todos = bubbleTodos(toolCalls, showAgentActivity);
331793
+ const showToolCalls = isCodeTurn
331794
+ ? codeTurn.steps.length > 0
331795
+ : hasGenericToolCalls(toolCalls, showAgentActivity);
331796
+ const todos = isCodeTurn ? codeTurn.plan : bubbleTodos(toolCalls, showAgentActivity);
331241
331797
  const hasTodosToShow = !!(todos === null || todos === void 0 ? void 0 : todos.length);
331798
+ // The SDK emits no phase for Code turns; the store knows which step runs.
331799
+ const phase = isCodeTurn && workingPhase ? codeTurnPhase(codeTurn.steps, content, t) : workingPhase;
331242
331800
  // A disclosure row is "active" when the phase it depicts is the live one AND
331243
331801
  // the row is actually on screen. These two booleans do double duty, and the
331244
331802
  // symmetry is the point: the active row gets its bouncing dots (it is now the
331245
331803
  // thing conveying progress), and the same fact stands the working line down,
331246
331804
  // because repeating "Thinking…" under a row that says "Thought" puts the same
331247
331805
  // statement on screen twice. Exactly one of them animates.
331248
- const isReasoningRowActive = (workingPhase === null || workingPhase === void 0 ? void 0 : workingPhase.kind) === 'thinking' && showReasoningSection;
331249
- const isToolRowActive = (workingPhase === null || workingPhase === void 0 ? void 0 : workingPhase.kind) === 'tool' && showToolCalls;
331250
- const isRestatedByVisibleRow = isReasoningRowActive || isToolRowActive;
331251
- return (jsx(TooltipProvider, { children: jsx(AIMessageFrame, { profileImage: profileImage, mentorName: mentorName, timestamp: timestamp, children: jsxs(Fragment$1, { children: [jsxs("div", { className: cn('mb-1.5 rounded-2xl bg-gray-100 p-3 wrap-anywhere', CHAT_CSS_CLASS_NAMES.CHAT.AI_MESSAGE_RESPONSE, hasArtifactVersions(message) && 'bg-white p-0'), children: [showReasoningSection && (jsx(ReasoningSection, { reasoningContent: reasoningContent, isActive: isReasoningRowActive })), showToolCalls && (jsx(ToolCallIndicator, { toolCalls: toolCalls, isActive: isToolRowActive })), hasTodosToShow && (jsx(AgentTodoList, { todos: todos, isCurrentlyStreaming: isCurrentlyStreaming })), hasPermissionPrompts && jsx(CodePermissionCards, { generationId: message.id }), jsx("div", { "data-testid": "ai-message-body", className: "overflow-x-auto text-sm/6 text-gray-800 [&_.katex-display]:overflow-x-auto [&_.katex-display]:overflow-y-hidden [&_code]:rounded [&_code]:bg-gray-200 [&_code]:px-1 [&_code]:py-0.5 [&_code]:font-mono [&_em]:italic [&_li]:mb-1 [&_ol]:list-decimal [&_ol]:pl-4 [&_pre]:overflow-x-auto [&_pre]:rounded [&_pre]:bg-gray-200 [&_pre]:p-2 [&_strong]:font-bold [&_ul]:list-disc [&_ul]:pl-4", children: jsx(MessagePreview, { content: content, artifactVersions: message === null || message === void 0 ? void 0 : message.artifactVersions, onOpenCanvas: onOpenCanvas, streamingArtifactId: streamingArtifactId }) }), (message === null || message === void 0 ? void 0 : message.actions) && (jsx("div", { className: "flex flex-wrap", children: message.actions.map((action, index) => (jsx(Button$1, { onClick: mapActionToCallback(action.actionType, joinTenant), className: "ibl-button-primary cursor-pointer", children: action.text }, index))) })), workingPhase && (jsx(WorkingIndicator, { phase: workingPhase, restatedByVisibleRow: isRestatedByVisibleRow, content: content, className: "mt-2" }))] }), jsxs("div", { className: cn('flex items-center space-x-4', isCurrentlyStreaming && 'hidden'), children: [jsx(AIMessageCopy, { ref: ref, content: content }), isLoggedIn() && !showingSharedChat && (jsx(AIMessageRating, { content: content, messages: messages, sessionId: sessionId, mentorId: mentorId, tenantKey: tenantKey })), (((_b = host.config) === null || _b === void 0 ? void 0 : _b.showMessageActionsWhenLoggedOut) || isLoggedIn()) &&
331806
+ const isReasoningRowActive = (phase === null || phase === void 0 ? void 0 : phase.kind) === 'thinking' && showReasoningSection;
331807
+ const isToolRowActive = (phase === null || phase === void 0 ? void 0 : phase.kind) === 'tool' && showToolCalls;
331808
+ // A waiting permission card is the thing needing attention, not the line.
331809
+ const isRestatedByVisibleRow = isReasoningRowActive || isToolRowActive || hasPermissionPrompts;
331810
+ return (jsx(TooltipProvider, { children: jsx(AIMessageFrame, { profileImage: profileImage, mentorName: mentorName, timestamp: timestamp, children: jsxs(Fragment$1, { children: [jsxs("div", { className: cn('mb-1.5 rounded-2xl bg-gray-100 p-3 wrap-anywhere', CHAT_CSS_CLASS_NAMES.CHAT.AI_MESSAGE_RESPONSE, hasArtifactVersions(message) && 'bg-white p-0'), children: [showReasoningSection && (jsx(ReasoningSection, { reasoningContent: reasoningContent, isActive: isReasoningRowActive })), showToolCalls &&
331811
+ (isCodeTurn ? (jsx(CodeActivity, { generationId: message.id, isCurrentlyStreaming: isCurrentlyStreaming })) : (jsx(ToolCallIndicator, { toolCalls: toolCalls, isActive: isToolRowActive }))), hasTodosToShow && (jsx(AgentTodoList, { todos: todos, isCurrentlyStreaming: isCurrentlyStreaming })), (hasPermissionPrompts || hostsPermissionCards) && (jsx(CodePermissionCards, { generationId: message.id })), jsx("div", { "data-testid": "ai-message-body", className: "overflow-x-auto text-sm/6 text-gray-800 [&_.katex-display]:overflow-x-auto [&_.katex-display]:overflow-y-hidden [&_code]:rounded [&_code]:bg-gray-200 [&_code]:px-1 [&_code]:py-0.5 [&_code]:font-mono [&_em]:italic [&_li]:mb-1 [&_ol]:list-decimal [&_ol]:pl-4 [&_pre]:overflow-x-auto [&_pre]:rounded [&_pre]:bg-gray-200 [&_pre]:p-2 [&_strong]:font-bold [&_ul]:list-disc [&_ul]:pl-4", children: jsx(MessagePreview, { content: content, artifactVersions: message === null || message === void 0 ? void 0 : message.artifactVersions, onOpenCanvas: onOpenCanvas, streamingArtifactId: streamingArtifactId }) }), (message === null || message === void 0 ? void 0 : message.actions) && (jsx("div", { className: "flex flex-wrap", children: message.actions.map((action, index) => (jsx(Button$1, { onClick: mapActionToCallback(action.actionType, joinTenant), className: "ibl-button-primary cursor-pointer", children: action.text }, index))) })), phase && (jsx(WorkingIndicator, { phase: phase, restatedByVisibleRow: isRestatedByVisibleRow, content: content, className: "mt-2" }))] }), jsxs("div", { className: cn('flex items-center space-x-4', isCurrentlyStreaming && 'hidden'), children: [jsx(AIMessageCopy, { ref: ref, content: content }), isLoggedIn() && !showingSharedChat && (jsx(AIMessageRating, { content: content, messages: messages, sessionId: sessionId, mentorId: mentorId, tenantKey: tenantKey })), (((_c = host.config) === null || _c === void 0 ? void 0 : _c.showMessageActionsWhenLoggedOut) || isLoggedIn()) &&
331252
331812
  !showingSharedChat &&
331253
331813
  !chatPrivacyActive && (jsxs(Fragment$1, { children: [jsx(AIMessageShare, { sessionId: sessionId, tenantKey: tenantKey }), jsx(AIMessageDownload, { message: message, messages: messages, mentorName: mentorName })] })), isLoggedIn() && !showingSharedChat && isMentorInappropriateContentEnabled && (jsx(AIMessageReportInappropriateContent, { mentorName: mentorName, messages: messages, supportEmail: supportEmail })), jsx(AIMessageSpeak, { message: message, mentorId: mentorId, tenantKey: tenantKey }), isLoggedIn() && !showingSharedChat && (jsxs(Tooltip$1, { children: [jsx(TooltipTrigger, { asChild: true, children: jsxs("button", { onClick: () => {
331254
331814
  const lastUserMessage = getLastUserMessage(messages);
@@ -331897,6 +332457,29 @@ function ChatActionBlockingOverlay({ isOpen, actionType, onStopScreenShare, }) {
331897
332457
  : t('modalsChatActionBlockingOverlay.screenSharingActiveTitle') }), jsx("p", { id: "blocking-overlay-description", className: "mb-6 text-gray-600", children: t('modalsChatActionBlockingOverlay.sessionActiveDescription', { actionLabel }) }), jsx("div", { className: "mb-4 flex flex-col gap-3", children: !isVoiceCall && onStopScreenShare && (jsxs("button", { onClick: onStopScreenShare, className: "flex w-full items-center justify-center gap-2 rounded-lg bg-red-600 px-4 py-3 font-medium text-white transition-colors hover:bg-red-700", children: [jsx(CircleStop, { className: "h-5 w-5" }), jsx("span", { children: t('modalsChatActionBlockingOverlay.stopScreenSharing') })] })) }), jsx("p", { className: "mt-4 text-xs text-gray-500", children: t('modalsChatActionBlockingOverlay.backgroundHandleDescription', { actionLabel }) })] }) }));
331898
332458
  }
331899
332459
 
332460
+ /**
332461
+ * Plain-words keys (`chatCodeErrors.*`) for the Code errors the Rust side and
332462
+ * the SDK surface as raw strings. Only the developer-shaped ones are mapped; a
332463
+ * string that is already a sentence (install, sign-in, a refused model) shows
332464
+ * as it is. First match wins.
332465
+ */
332466
+ const PLAIN_CODE_ERRORS = [
332467
+ [
332468
+ /^opencode error on |opencode closed before responding|failed writing to opencode|no user message to send/,
332469
+ 'stopped',
332470
+ ],
332471
+ // Anchored to the desktop's and the phone's exact wording: every host's chat shares this toast.
332472
+ [/^(?:Codex|Claude Code|opencode) did not answer within \d+s\.$|^turn timed out$/, 'noAnswer'],
332473
+ [/no model selected for Code/, 'noModel'],
332474
+ [/^failed to launch|returned no sessionId|ibl\.ai guidance anchor missing/, 'couldNotStart'],
332475
+ [/Not signed in .*missing tenant or token/, 'signedOut'],
332476
+ ];
332477
+ function plainCodeError(raw) {
332478
+ const text = raw.replace(/^opencode failed: /, '');
332479
+ const hit = PLAIN_CODE_ERRORS.find(([pattern]) => pattern.test(text));
332480
+ return hit ? hit[1] : null;
332481
+ }
332482
+
331900
332483
  const ToastErrorMessage = ({ message, supportEmail, supportPhone, useSupportPhone = false, tenantKey: tenantKeyProp, }) => {
331901
332484
  const t = useChatT();
331902
332485
  const host = useChatHost();
@@ -331904,8 +332487,15 @@ const ToastErrorMessage = ({ message, supportEmail, supportPhone, useSupportPhon
331904
332487
  useEffect(() => {
331905
332488
  console.error(JSON.stringify({ tenant: tenantKey, error: message }));
331906
332489
  }, [message]);
331907
- const plainMessage = markdownToPlainText(message);
331908
- return (jsx("div", { children: jsxs("span", { children: [t('chat.toastErrorMessage.sorryAboutThat'), ' ', String(plainMessage).match(/[.!?]$/) ? plainMessage : `${plainMessage}.`, ' ', t('chat.toastErrorMessage.pleaseTryAgainOr'), ' ', jsx("a", { className: "toast-wrapped-contact-tag text-blue-600 hover:text-blue-800", href: `mailto:${supportEmail}`, children: t('chat.toastErrorMessage.contactUs') }), ".", useSupportPhone && supportPhone ? (jsxs(Fragment$1, { children: [' ', t('chat.toastErrorMessage.textUsAt'), ' ', jsx("a", { className: "toast-wrapped-contact-tag text-blue-600 hover:text-blue-800", href: `tel:${supportPhone}`, children: supportPhone }), "."] })) : null] }) }));
332490
+ // A developer-shaped Code error reads as a plain sentence; the raw text stays in the log above.
332491
+ const codeKey = plainCodeError(message);
332492
+ const plainMessage = String(markdownToPlainText(message));
332493
+ const sentence = codeKey
332494
+ ? t(`chat.chatCodeErrors.${codeKey}`)
332495
+ : plainMessage.match(/[.!?]$/)
332496
+ ? plainMessage
332497
+ : `${plainMessage}.`;
332498
+ return (jsx("div", { children: jsxs("span", { children: [t('chat.toastErrorMessage.sorryAboutThat'), " ", sentence, ' ', t('chat.toastErrorMessage.pleaseTryAgainOr'), ' ', jsx("a", { className: "toast-wrapped-contact-tag text-blue-600 hover:text-blue-800", href: `mailto:${supportEmail}`, children: t('chat.toastErrorMessage.contactUs') }), ".", useSupportPhone && supportPhone ? (jsxs(Fragment$1, { children: [' ', t('chat.toastErrorMessage.textUsAt'), ' ', jsx("a", { className: "toast-wrapped-contact-tag text-blue-600 hover:text-blue-800", href: `tel:${supportPhone}`, children: supportPhone }), "."] })) : null] }) }));
331909
332499
  };
331910
332500
 
331911
332501
  /**
@@ -332169,7 +332759,7 @@ function useHostIsOnline(override) {
332169
332759
  return override !== null && override !== void 0 ? override : providerOnline;
332170
332760
  }
332171
332761
  function ChatInner({ mode = 'default', isPreviewMode = false, hasBorder = true, isInCanvasView = false, }) {
332172
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s;
332762
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t;
332173
332763
  const t = useChatT();
332174
332764
  const { tenantKey, mentorId, username, axdToken, userTenants, visitingTenant, isEmbedMode: isEmbeddedMode, isPublicRoute, redirectToAuthSpa, config: hostConfig, features, } = useChatHost();
332175
332765
  // `Chat` always provides a config; the fallback only satisfies the types.
@@ -333337,6 +333927,7 @@ function ChatInner({ mode = 'default', isPreviewMode = false, hasBorder = true,
333337
333927
  const hasPermissionPrompts = isStreaming &&
333338
333928
  !!streamingMessage &&
333339
333929
  permissionRequests.some((r) => r.generation_id === streamingMessage.id);
333930
+ const streamCodeTurn = useCodeTurn(streamIsCodeTurn ? streamingMessage === null || streamingMessage === void 0 ? void 0 : streamingMessage.id : undefined);
333340
333931
  const isStreamingBubbleVisible = isStreaming &&
333341
333932
  !!streamingMessage &&
333342
333933
  streamingMessage.visible === true &&
@@ -333347,10 +333938,11 @@ function ChatInner({ mode = 'default', isPreviewMode = false, hasBorder = true,
333347
333938
  toolCalls: streamingToolCalls,
333348
333939
  showReasoning: mentorSettings.showReasoning || streamIsCodeTurn,
333349
333940
  hasPermissionPrompts,
333941
+ hasCodeActivity: streamCodeTurn.steps.length > 0 || !!((_f = streamCodeTurn.plan) === null || _f === void 0 ? void 0 : _f.length),
333350
333942
  });
333351
333943
  // The new-chat screen: no messages yet, or only the agent's greeting.
333352
333944
  const isWelcomeVisible = (messages.length === 0 ||
333353
- (!isNewSession.current && messages.length === 1 && ((_f = messages[0]) === null || _f === void 0 ? void 0 : _f.role) === 'assistant')) &&
333945
+ (!isNewSession.current && messages.length === 1 && ((_g = messages[0]) === null || _g === void 0 ? void 0 : _g.role) === 'assistant')) &&
333354
333946
  !isAdvancedMode &&
333355
333947
  !(!isNewSession.current && isLoadingChats && messages.length === 0);
333356
333948
  const workingIndicator = isTurnInFlight && !isStreamingBubbleVisible ? (jsx(AIWorkingMessage, { phase: workingPhase, mentorName: mentorName, profileImage: profileImage, timestamp: turnStartedAtRef.current })) : null;
@@ -333362,7 +333954,7 @@ function ChatInner({ mode = 'default', isPreviewMode = false, hasBorder = true,
333362
333954
  // Fill available space when the messages section won't render
333363
333955
  // (no messages, or only a single assistant greeting/proactive prompt)
333364
333956
  'min-h-0 flex-1': !isCanvasOpen &&
333365
- (messages.length === 0 || (messages.length === 1 && ((_g = messages[0]) === null || _g === void 0 ? void 0 : _g.role) === 'assistant')),
333957
+ (messages.length === 0 || (messages.length === 1 && ((_h = messages[0]) === null || _h === void 0 ? void 0 : _h.role) === 'assistant')),
333366
333958
  // Reserve the same scrollbar gutter as the chat input container so
333367
333959
  // the welcome message stays horizontally aligned with the input.
333368
333960
  // Advanced mode scrolls inside its own panel, so it only needs the
@@ -333371,7 +333963,7 @@ function ChatInner({ mode = 'default', isPreviewMode = false, hasBorder = true,
333371
333963
  'overflow-y-auto': !isAdvancedMode && !isCanvasOpen,
333372
333964
  'overflow-y-hidden': isAdvancedMode && !isCanvasOpen,
333373
333965
  'min-h-0': isCompactMode, // Allow flex shrinking in compact mode
333374
- }), style: isCanvasOpen ? { display: 'none' } : undefined, children: [isAdvancedMode && (jsxs("div", { className: "mx-auto flex h-full w-full flex-col overflow-hidden rounded-lg bg-white", style: { maxWidth: `${chatAreaMaxWidth}px` }, children: [jsx(AdvancedChatHeader, { mentorName: mentorName, profileImage: profileImage, tabs: advancedTabs, activeTab: activeTab, setActiveTab: changeTab, isTyping: isStreaming }), messages.length === 0 && (jsx(AdvancedStaticChatBuilder, { mentorName: mentorName, profileImage: profileImage, sendMessage: sendMessage, activeTab: activeTab, tenantKey: tenantKey, username: username !== null && username !== void 0 ? username : '', sessionId: (_h = cachedSessionId === null || cachedSessionId === void 0 ? void 0 : cachedSessionId[sessionKey]) !== null && _h !== void 0 ? _h : sessionId, mentorId: mentorId, mentorUniqueId: uniqueMentorId, welcomeWsUrl: `${config.baseWsUrl()}/ws/langflow/`, isPublicRoute: isAccessingPublicRoute }))] })), !isAdvancedMode && !isNewSession.current && isLoadingChats && messages.length === 0 && (jsx("div", { className: "flex h-full w-full items-center justify-center", children: jsx(Spinner, { className: "h-14 w-14" }) })), isWelcomeVisible && (jsx(WelcomeChatNew, { mentorName: mentorName, sessionId: (_j = cachedSessionId === null || cachedSessionId === void 0 ? void 0 : cachedSessionId[sessionKey]) !== null && _j !== void 0 ? _j : sessionId, isNewSession: isNewSession.current || (messages.length === 0 && !isLoadingChats), aiWelcomeMessage: messages.length === 1 && ((_k = messages[0]) === null || _k === void 0 ? void 0 : _k.role) === 'assistant' ? (_l = messages[0]) === null || _l === void 0 ? void 0 : _l.content : '', enabledGuidedPrompts: enabledGuidedPrompts, onSubmit: handleSubmit, onScreenSharingClick: handleScreenSharingClick, isScreenSharingModalOpen: isScreenSharingModalOpen, onPhoneCallClick: handlePhoneCallClick, stopGenerating: stopAnyGeneration, tenantKey: tenantKey, username: username !== null && username !== void 0 ? username : '', enableWebBrowsing: enableWebBrowsing, setMessage: setMessage, isStreaming: isStreaming, enableSafetyDisclaimer: enableSafetyDisclaimer, isPreviewMode: isPreviewMode, updateSessionTools: updateSessionTools, setSessionTools: setSessionTools, activeTools: activeTools, screenSharing: screenSharing, deepResearch: deepResearch, studyMode: studyMode, imageGeneration: imageGeneration, codeInterpreter: codeInterpreter, mentorUniqueId: mentorId, profileImage: profileImage, promptsIsEnabled: promptsIsEnabled, googleSlidesIsEnabled: googleSlidesIsEnabled, googleDocumentIsEnabled: googleDocumentIsEnabled, artifactsEnabled: artifactsEnabled, chatAreaMaxWidth: chatAreaMaxWidth, isConnecting: !isConnected, compactMode: isCompactMode }))] }), isCanvasOpen && !isInCanvasView ? (
333966
+ }), style: isCanvasOpen ? { display: 'none' } : undefined, children: [isAdvancedMode && (jsxs("div", { className: "mx-auto flex h-full w-full flex-col overflow-hidden rounded-lg bg-white", style: { maxWidth: `${chatAreaMaxWidth}px` }, children: [jsx(AdvancedChatHeader, { mentorName: mentorName, profileImage: profileImage, tabs: advancedTabs, activeTab: activeTab, setActiveTab: changeTab, isTyping: isStreaming }), messages.length === 0 && (jsx(AdvancedStaticChatBuilder, { mentorName: mentorName, profileImage: profileImage, sendMessage: sendMessage, activeTab: activeTab, tenantKey: tenantKey, username: username !== null && username !== void 0 ? username : '', sessionId: (_j = cachedSessionId === null || cachedSessionId === void 0 ? void 0 : cachedSessionId[sessionKey]) !== null && _j !== void 0 ? _j : sessionId, mentorId: mentorId, mentorUniqueId: uniqueMentorId, welcomeWsUrl: `${config.baseWsUrl()}/ws/langflow/`, isPublicRoute: isAccessingPublicRoute }))] })), !isAdvancedMode && !isNewSession.current && isLoadingChats && messages.length === 0 && (jsx("div", { className: "flex h-full w-full items-center justify-center", children: jsx(Spinner, { className: "h-14 w-14" }) })), isWelcomeVisible && (jsx(WelcomeChatNew, { mentorName: mentorName, sessionId: (_k = cachedSessionId === null || cachedSessionId === void 0 ? void 0 : cachedSessionId[sessionKey]) !== null && _k !== void 0 ? _k : sessionId, isNewSession: isNewSession.current || (messages.length === 0 && !isLoadingChats), aiWelcomeMessage: messages.length === 1 && ((_l = messages[0]) === null || _l === void 0 ? void 0 : _l.role) === 'assistant' ? (_m = messages[0]) === null || _m === void 0 ? void 0 : _m.content : '', enabledGuidedPrompts: enabledGuidedPrompts, onSubmit: handleSubmit, onScreenSharingClick: handleScreenSharingClick, isScreenSharingModalOpen: isScreenSharingModalOpen, onPhoneCallClick: handlePhoneCallClick, stopGenerating: stopAnyGeneration, tenantKey: tenantKey, username: username !== null && username !== void 0 ? username : '', enableWebBrowsing: enableWebBrowsing, setMessage: setMessage, isStreaming: isStreaming, enableSafetyDisclaimer: enableSafetyDisclaimer, isPreviewMode: isPreviewMode, updateSessionTools: updateSessionTools, setSessionTools: setSessionTools, activeTools: activeTools, screenSharing: screenSharing, deepResearch: deepResearch, studyMode: studyMode, imageGeneration: imageGeneration, codeInterpreter: codeInterpreter, mentorUniqueId: mentorId, profileImage: profileImage, promptsIsEnabled: promptsIsEnabled, googleSlidesIsEnabled: googleSlidesIsEnabled, googleDocumentIsEnabled: googleDocumentIsEnabled, artifactsEnabled: artifactsEnabled, chatAreaMaxWidth: chatAreaMaxWidth, isConnecting: !isConnected, compactMode: isCompactMode }))] }), isCanvasOpen && !isInCanvasView ? (
333375
333967
  /* Split layout when canvas is open */
333376
333968
  jsxs("div", { className: "relative flex flex-1 overflow-hidden", ref: resizeRef, style: { minHeight: 0, maxHeight: '100%', height: '100%' }, children: [jsxs("div", { className: "hidden flex-shrink-0 flex-col overflow-hidden border-r border-gray-200 md:flex", style: { width: `${chatWidth}%`, minHeight: 0, maxHeight: '100%' }, children: [jsx("div", { ref: chatContainerRef, onScroll: handleScroll, className: "flex-1 overflow-y-auto [scrollbar-gutter:stable]", children: jsxs("div", { className: "px-3 py-4", children: [isLoadingOlderMessages && (jsx("div", { className: "flex justify-center py-2", "data-testid": "loading-older-messages", children: jsx(Spinner, { className: "h-5 w-5" }) })), jsxs(ErrorBoundary, { children: [messages.length > 0 ? (jsx(ChatMessages, { ref: lastAIMessageCopyButtonRef, messages: messages, highlightedMessageId: highlightedMessageId, profileImage: profileImage, mentorName: mentorName, sessionId: sessionId, mentorId: mentorId, tenantKey: tenantKey, handleHighlightMessage: handleHighlightMessage, handleSubmit: handleSubmit, onReply: (message) => {
333377
333969
  setReplyingToMessage(message);
@@ -333383,10 +333975,10 @@ function ChatInner({ mode = 'default', isPreviewMode = false, hasBorder = true,
333383
333975
  height: '100%',
333384
333976
  }, children: [jsx(CanvasView, { canvasTitle: canvasState.title, canvasContent: canvasState.content, canvasType: canvasState.type, artifactId: canvasState.artifactId, org: canvasState.org, userId: canvasState.userId, fileExtension: canvasState.fileExtension, metadata: canvasState.metadata, sessionId: sessionId, tenantKey: tenantKey, activeTools: activeTools, artifactsEnabled: artifactsEnabled, refreshTrigger: canvasRefreshTrigger, sendMessage: (text, options) => {
333385
333977
  sendMessage(activeTab, text, options);
333386
- }, onClose: handleCloseCanvas }, `${(_m = canvasState.artifactId) !== null && _m !== void 0 ? _m : 'canvas'}-${canvasRefreshTrigger}`), jsx("div", { className: "flex-shrink-0 border-t border-gray-200 bg-white p-3 md:hidden", children: jsx(ChatInputForm, { variant: "redesign", stopStreamingButtonRef: stopStreamingButtonRef, sessionId: sessionId, onSubmit: handleSubmit, stopGenerating: stopAnyGeneration, onScreenSharingClick: handleScreenSharingClick, isScreenSharingModalOpen: isScreenSharingModalOpen, onPhoneCallClick: handlePhoneCallClick, tenantKey: tenantKey, username: username !== null && username !== void 0 ? username : '', setMessage: setMessage, enableSafetyDisclaimer: enableSafetyDisclaimer, isPreviewMode: isPreviewMode, enableWebBrowsing: enableWebBrowsing, isStreaming: isStreaming, updateSessionTools: updateSessionTools, setSessionTools: setSessionTools, activeTools: activeTools, screenSharing: screenSharing, deepResearch: deepResearch, studyMode: studyMode, imageGeneration: imageGeneration, codeInterpreter: codeInterpreter, promptsIsEnabled: promptsIsEnabled, googleSlidesIsEnabled: googleSlidesIsEnabled, googleDocumentIsEnabled: googleDocumentIsEnabled, artifactsEnabled: artifactsEnabled, compactMode: isCompactMode, isConnecting: !isConnected }) })] })] })) : (
333978
+ }, onClose: handleCloseCanvas }, `${(_o = canvasState.artifactId) !== null && _o !== void 0 ? _o : 'canvas'}-${canvasRefreshTrigger}`), jsx("div", { className: "flex-shrink-0 border-t border-gray-200 bg-white p-3 md:hidden", children: jsx(ChatInputForm, { variant: "redesign", stopStreamingButtonRef: stopStreamingButtonRef, sessionId: sessionId, onSubmit: handleSubmit, stopGenerating: stopAnyGeneration, onScreenSharingClick: handleScreenSharingClick, isScreenSharingModalOpen: isScreenSharingModalOpen, onPhoneCallClick: handlePhoneCallClick, tenantKey: tenantKey, username: username !== null && username !== void 0 ? username : '', setMessage: setMessage, enableSafetyDisclaimer: enableSafetyDisclaimer, isPreviewMode: isPreviewMode, enableWebBrowsing: enableWebBrowsing, isStreaming: isStreaming, updateSessionTools: updateSessionTools, setSessionTools: setSessionTools, activeTools: activeTools, screenSharing: screenSharing, deepResearch: deepResearch, studyMode: studyMode, imageGeneration: imageGeneration, codeInterpreter: codeInterpreter, promptsIsEnabled: promptsIsEnabled, googleSlidesIsEnabled: googleSlidesIsEnabled, googleDocumentIsEnabled: googleDocumentIsEnabled, artifactsEnabled: artifactsEnabled, compactMode: isCompactMode, isConnecting: !isConnected }) })] })] })) : (
333387
333979
  /* Normal chat layout when canvas is closed */
333388
333980
  messages.length > 0 &&
333389
- (messages[0].role === 'assistant' ? messages.slice(1) : messages).length > 0 && (jsx("div", { ref: chatContainerRef, onScroll: handleScroll, className: "min-h-0 flex-1 overflow-y-auto", children: jsxs("div", { className: "mx-auto w-full py-6", style: { maxWidth: `${chatAreaMaxWidth}px` }, children: [isLoadingOlderMessages && (jsx("div", { className: "flex justify-center py-2", "data-testid": "loading-older-messages", children: jsx(Spinner, { className: "h-5 w-5" }) })), jsxs(ErrorBoundary, { children: [jsx(ChatMessages, { ref: lastAIMessageCopyButtonRef, messages: messages[0].role === 'assistant' ? messages.slice(1) : messages, highlightedMessageId: highlightedMessageId, profileImage: profileImage, mentorName: mentorName, sessionId: (_o = cachedSessionId === null || cachedSessionId === void 0 ? void 0 : cachedSessionId[sessionKey]) !== null && _o !== void 0 ? _o : sessionId, mentorId: mentorId, tenantKey: tenantKey, handleHighlightMessage: handleHighlightMessage, handleSubmit: handleSubmit, onReply: (message) => {
333981
+ (messages[0].role === 'assistant' ? messages.slice(1) : messages).length > 0 && (jsx("div", { ref: chatContainerRef, onScroll: handleScroll, className: "min-h-0 flex-1 overflow-y-auto", children: jsxs("div", { className: "mx-auto w-full py-6", style: { maxWidth: `${chatAreaMaxWidth}px` }, children: [isLoadingOlderMessages && (jsx("div", { className: "flex justify-center py-2", "data-testid": "loading-older-messages", children: jsx(Spinner, { className: "h-5 w-5" }) })), jsxs(ErrorBoundary, { children: [jsx(ChatMessages, { ref: lastAIMessageCopyButtonRef, messages: messages[0].role === 'assistant' ? messages.slice(1) : messages, highlightedMessageId: highlightedMessageId, profileImage: profileImage, mentorName: mentorName, sessionId: (_p = cachedSessionId === null || cachedSessionId === void 0 ? void 0 : cachedSessionId[sessionKey]) !== null && _p !== void 0 ? _p : sessionId, mentorId: mentorId, tenantKey: tenantKey, handleHighlightMessage: handleHighlightMessage, handleSubmit: handleSubmit, onReply: (message) => {
333390
333982
  setReplyingToMessage(message);
333391
333983
  focusPromptTextarea();
333392
333984
  }, onOpenCanvas: handleOpenCanvas, streamingArtifactId: streamingArtifactId, isStreaming: isStreaming, streamingReasoningContent: streamingReasoningContent, streamingToolCalls: streamingToolCalls, showReasoning: mentorSettings.showReasoning, currentStreamingMessageId: currentStreamingMsg === null || currentStreamingMsg === void 0 ? void 0 : currentStreamingMsg.id, workingPhase: isTurnInFlight ? workingPhase : undefined }), jsx("div", { "aria-live": "polite", role: "status", className: "sr-only", children: mentorAccessibilityMessage }), workingIndicator, !showingSharedChat && guidedPrompts] })] }) }))), isScrolledUp && !isPreviewMode && messages.length > 0 && !isCanvasOpen && (jsx("div", { className: "pointer-events-none sticky bottom-4 z-10 flex h-0 w-full justify-center bg-transparent", children: jsxs(Tooltip$1, { children: [jsx(TooltipTrigger, { asChild: true, children: jsxs(Button$1, { onClick: (event) => {
@@ -333397,11 +333989,11 @@ function ChatInner({ mode = 'default', isPreviewMode = false, hasBorder = true,
333397
333989
  (isAdvancedMode ||
333398
333990
  isEmbeddedMode ||
333399
333991
  (messages.length > 0 &&
333400
- (messages[0].role === 'assistant' ? messages.slice(1) : messages).length > 0)) && (jsx("div", { className: "flex-shrink-0 overflow-y-auto pb-3.5 [scrollbar-gutter:stable]", children: jsx(ChatInputForm, { variant: "redesign", stopStreamingButtonRef: stopStreamingButtonRef, sessionId: (_p = cachedSessionId === null || cachedSessionId === void 0 ? void 0 : cachedSessionId[sessionKey]) !== null && _p !== void 0 ? _p : sessionId, onSubmit: handleSubmit, stopGenerating: stopAnyGeneration, onScreenSharingClick: handleScreenSharingClick, isScreenSharingModalOpen: isScreenSharingModalOpen, onPhoneCallClick: handlePhoneCallClick, tenantKey: tenantKey, username: username !== null && username !== void 0 ? username : '', setMessage: setMessage, enableSafetyDisclaimer: enableSafetyDisclaimer, isPreviewMode: isPreviewMode, enableWebBrowsing: enableWebBrowsing, isStreaming: isStreaming, updateSessionTools: updateSessionTools, setSessionTools: setSessionTools, activeTools: activeTools, screenSharing: screenSharing, deepResearch: deepResearch, studyMode: studyMode, imageGeneration: imageGeneration, codeInterpreter: codeInterpreter, promptsIsEnabled: promptsIsEnabled, googleSlidesIsEnabled: googleSlidesIsEnabled, googleDocumentIsEnabled: googleDocumentIsEnabled, artifactsEnabled: artifactsEnabled, compactMode: isCompactMode,
333992
+ (messages[0].role === 'assistant' ? messages.slice(1) : messages).length > 0)) && (jsx("div", { className: "flex-shrink-0 overflow-y-auto pb-3.5 [scrollbar-gutter:stable]", children: jsx(ChatInputForm, { variant: "redesign", stopStreamingButtonRef: stopStreamingButtonRef, sessionId: (_q = cachedSessionId === null || cachedSessionId === void 0 ? void 0 : cachedSessionId[sessionKey]) !== null && _q !== void 0 ? _q : sessionId, onSubmit: handleSubmit, stopGenerating: stopAnyGeneration, onScreenSharingClick: handleScreenSharingClick, isScreenSharingModalOpen: isScreenSharingModalOpen, onPhoneCallClick: handlePhoneCallClick, tenantKey: tenantKey, username: username !== null && username !== void 0 ? username : '', setMessage: setMessage, enableSafetyDisclaimer: enableSafetyDisclaimer, isPreviewMode: isPreviewMode, enableWebBrowsing: enableWebBrowsing, isStreaming: isStreaming, updateSessionTools: updateSessionTools, setSessionTools: setSessionTools, activeTools: activeTools, screenSharing: screenSharing, deepResearch: deepResearch, studyMode: studyMode, imageGeneration: imageGeneration, codeInterpreter: codeInterpreter, promptsIsEnabled: promptsIsEnabled, googleSlidesIsEnabled: googleSlidesIsEnabled, googleDocumentIsEnabled: googleDocumentIsEnabled, artifactsEnabled: artifactsEnabled, compactMode: isCompactMode,
333401
333993
  // The embed composer widens with its frame up to ~680px (#2586 Embed v2 / LTI).
333402
333994
  chatAreaMaxWidth: isEmbeddedMode
333403
333995
  ? Math.min(chatAreaMaxWidth, EMBED_COMPOSER_MAX_WIDTH)
333404
- : chatAreaMaxWidth, promptsAbove: isEmbeddedMode && isWelcomeVisible ? (jsx(EmbedStarterPrompts, { onPromptSelect: handleSubmit, enabledGuidedPrompts: enabledGuidedPrompts, sessionId: (_q = cachedSessionId === null || cachedSessionId === void 0 ? void 0 : cachedSessionId[sessionKey]) !== null && _q !== void 0 ? _q : sessionId })) : undefined }) })), isPhoneCallModalOpen && (jsx(LiveKitChat$1, { tenantKey: tenantKey, mentorUniqueId: uniqueMentorId, sessionId: (_r = cachedSessionId === null || cachedSessionId === void 0 ? void 0 : cachedSessionId[sessionKey]) !== null && _r !== void 0 ? _r : sessionId, username: username !== null && username !== void 0 ? username : '',
333996
+ : chatAreaMaxWidth, promptsAbove: isEmbeddedMode && isWelcomeVisible ? (jsx(EmbedStarterPrompts, { onPromptSelect: handleSubmit, enabledGuidedPrompts: enabledGuidedPrompts, sessionId: (_r = cachedSessionId === null || cachedSessionId === void 0 ? void 0 : cachedSessionId[sessionKey]) !== null && _r !== void 0 ? _r : sessionId })) : undefined }) })), isPhoneCallModalOpen && (jsx(LiveKitChat$1, { tenantKey: tenantKey, mentorUniqueId: uniqueMentorId, sessionId: (_s = cachedSessionId === null || cachedSessionId === void 0 ? void 0 : cachedSessionId[sessionKey]) !== null && _s !== void 0 ? _s : sessionId, username: username !== null && username !== void 0 ? username : '',
333405
333997
  // Labels the agent's transcript lines with the mentor's real name
333406
333998
  // and face, so call captions match the chat thread behind them.
333407
333999
  mentorName: mentorName, mentorImage: profileImage, isOpen: isPhoneCallModalOpen, onClose: () => {
@@ -333415,7 +334007,7 @@ function ChatInner({ mode = 'default', isPreviewMode = false, hasBorder = true,
333415
334007
  // this mirrors the screen-sharing handler below.
333416
334008
  refetchChats();
333417
334009
  }
333418
- } })), isScreenSharingModalOpen && (jsx(LiveKitScreenSharing$1, { tenantKey: tenantKey, mentorUniqueId: uniqueMentorId, sessionId: (_s = cachedSessionId === null || cachedSessionId === void 0 ? void 0 : cachedSessionId[sessionKey]) !== null && _s !== void 0 ? _s : sessionId, username: username !== null && username !== void 0 ? username : '', isOpen: isScreenSharingModalOpen, mentorName: mentorName, onClose: () => {
334010
+ } })), isScreenSharingModalOpen && (jsx(LiveKitScreenSharing$1, { tenantKey: tenantKey, mentorUniqueId: uniqueMentorId, sessionId: (_t = cachedSessionId === null || cachedSessionId === void 0 ? void 0 : cachedSessionId[sessionKey]) !== null && _t !== void 0 ? _t : sessionId, username: username !== null && username !== void 0 ? username : '', isOpen: isScreenSharingModalOpen, mentorName: mentorName, onClose: () => {
333419
334011
  if (window.opener) {
333420
334012
  window.close();
333421
334013
  }