@iblai/iblai-js 1.25.2 → 1.26.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.
@@ -52891,7 +52891,7 @@ function useCallbackRef$1(initialValue, callback) {
52891
52891
  return ref.facade;
52892
52892
  }
52893
52893
 
52894
- var useIsomorphicLayoutEffect$2 = typeof window !== 'undefined' ? React.useLayoutEffect : React.useEffect;
52894
+ var useIsomorphicLayoutEffect$3 = typeof window !== 'undefined' ? React.useLayoutEffect : React.useEffect;
52895
52895
  var currentValues = new WeakMap();
52896
52896
  /**
52897
52897
  * Merges two or more refs together providing a single interface to set their value
@@ -52912,7 +52912,7 @@ function useMergeRefs(refs, defaultValue) {
52912
52912
  return refs.forEach(function (ref) { return assignRef(ref, newValue); });
52913
52913
  });
52914
52914
  // handle refs changes - added or removed
52915
- useIsomorphicLayoutEffect$2(function () {
52915
+ useIsomorphicLayoutEffect$3(function () {
52916
52916
  var oldValue = currentValues.get(callbackRef);
52917
52917
  if (oldValue) {
52918
52918
  var prevRefs_1 = new Set(oldValue);
@@ -59731,6 +59731,7 @@ var advancePagination$3 = {
59731
59731
  var advancedAdvanced$3 = {
59732
59732
  failedToUpdateSetting: "Failed to update setting",
59733
59733
  settingUpdatedSuccessfully: "Setting updated successfully",
59734
+ save: "Save",
59734
59735
  agentSettingUpdatedSuccessfully: "Agent setting updated successfully",
59735
59736
  chatAreaSizeUpdatedSuccessfully: "Chat area size updated successfully",
59736
59737
  moreInfoAbout: "More info about {label}",
@@ -61101,11 +61102,16 @@ var clawSandboxAgentConfigPrompts$3 = {
61101
61102
  updateSuccess: "{label} updated successfully",
61102
61103
  updateError: "Failed to update {label}",
61103
61104
  moreInfoAriaLabel: "More info about {label}",
61104
- edit: "Edit"
61105
+ edit: "Edit",
61106
+ connectSandboxPrompt: "Connect a sandbox instance in the Sandbox tab to manage agent prompts.",
61107
+ enableSandboxPrompt: "Enable the dedicated sandbox on the Sandbox tab and connect it to an instance to manage agent prompts.",
61108
+ sandboxTabLabel: "Sandbox tab"
61105
61109
  };
61106
61110
  var clawSandboxAgentSkills$3 = {
61107
61111
  loadingSkills: "Loading skills...",
61108
61112
  connectSandboxPrompt: "Connect a sandbox instance in the Sandbox tab to manage skills.",
61113
+ enableSandboxPrompt: "Enable the dedicated sandbox on the Sandbox tab and connect it to an instance to manage skills.",
61114
+ sandboxTabLabel: "Sandbox tab",
61109
61115
  newSkill: "New Skill",
61110
61116
  noSkillsAvailable: "No skills available for this platform. Create one to get started.",
61111
61117
  moreInfoAbout: "More info about {name}",
@@ -62303,7 +62309,8 @@ var modalsPaywallModal$3 = {
62303
62309
  subscribeToGetAccess: "Subscribe to get access to {itemName}",
62304
62310
  redirecting: "Redirecting...",
62305
62311
  pay: "Pay",
62306
- thisIncludes: "This includes:"
62312
+ thisIncludes: "This includes:",
62313
+ secureCheckout: "Secure checkout"
62307
62314
  };
62308
62315
  var modalsPromptGalleryModal$3 = {
62309
62316
  promptGallery: "Prompt Gallery",
@@ -62624,6 +62631,11 @@ var privacyTabLabels$3 = {
62624
62631
  title: "Privacy",
62625
62632
  description: "Detect and filter personally identifiable information from chat messages."
62626
62633
  },
62634
+ capability: {
62635
+ title: "PII filtering",
62636
+ description: "Automatically find and hide personal information — names, emails, phone numbers and more — in messages before the agent sees them. When on, choose what to detect and how to handle it below.",
62637
+ offHint: "Turn it on to detect and hide personal information in messages."
62638
+ },
62627
62639
  fields: {
62628
62640
  enableRouter: {
62629
62641
  label: "Enable Privacy Router",
@@ -62635,12 +62647,14 @@ var privacyTabLabels$3 = {
62635
62647
  options: {
62636
62648
  redact: "Redact",
62637
62649
  mask: "Mask",
62638
- block: "Block"
62650
+ block: "Block",
62651
+ allow: "Allow"
62639
62652
  },
62640
62653
  descriptions: {
62641
62654
  redact: "PII is replaced with its type — e.g. \"Email [EMAIL_ADDRESS]\".",
62642
62655
  mask: "PII is hidden behind asterisks — e.g. \"Email ***********\".",
62643
- block: "The message is rejected and your block message is shown to the user."
62656
+ block: "The message is rejected and your block message is shown to the user.",
62657
+ allow: "PII is detected but left untouched — the message passes through unchanged. Use this to monitor or audit personal information without altering messages."
62644
62658
  }
62645
62659
  },
62646
62660
  blockMessage: {
@@ -63330,6 +63344,11 @@ var screenshareTabLabels$3 = {
63330
63344
  title: "Screen Share",
63331
63345
  description: "How your agent behaves when a user shares their screen during a voice call."
63332
63346
  },
63347
+ capability: {
63348
+ title: "Screen sharing",
63349
+ description: "Let people share their screen during a voice call so the agent can see what they're doing and guide them step by step. When on, set the screen-sharing prompts below.",
63350
+ offHint: "Turn it on to let people share their screen during a call and edit these prompts."
63351
+ },
63333
63352
  disabledHint: "Screen sharing is currently turned off for this agent. These prompts will be saved but only take effect once it’s turned on.",
63334
63353
  fields: {
63335
63354
  systemPrompt: {
@@ -64096,7 +64115,8 @@ var tabsVoiceTab$3 = {
64096
64115
  var tasksTabLabels$3 = {
64097
64116
  header: {
64098
64117
  title: "Tasks",
64099
- description: "Configure automated tasks for your agent."
64118
+ description: "Configure automated tasks for your agent.",
64119
+ infoBox: "Let your agent work on its own schedule. Set up recurring tasks it runs automatically — like daily summaries or reminders — without anyone having to ask."
64100
64120
  },
64101
64121
  toolbar: {
64102
64122
  searchPlaceholder: "Search all tasks...",
@@ -64238,11 +64258,54 @@ var voiceTabCallConfigSection$3 = {
64238
64258
  refreshingAriaLabel: "Refreshing",
64239
64259
  moreInfoAbout: "More info about {label}"
64240
64260
  };
64261
+ var analyticsTabLabels$3 = {
64262
+ header: {
64263
+ title: "Analytics",
64264
+ description: "Usage reports and insights for this agent."
64265
+ },
64266
+ infoBox: "See how this agent is being used — who's chatting with it, what they talk about, what it costs, and more. Pick a report below to dive in.",
64267
+ openAria: "Open {label}",
64268
+ tabs: {
64269
+ overview: {
64270
+ label: "Overview",
64271
+ description: "A high-level snapshot of usage and engagement over time."
64272
+ },
64273
+ users: {
64274
+ label: "Users",
64275
+ description: "See who's chatting with this agent and how active they are."
64276
+ },
64277
+ topics: {
64278
+ label: "Topics",
64279
+ description: "The subjects people bring up most across conversations."
64280
+ },
64281
+ transcripts: {
64282
+ label: "Transcripts",
64283
+ description: "Read full conversation transcripts message by message."
64284
+ },
64285
+ financial: {
64286
+ label: "Costs",
64287
+ description: "Track token usage and what this agent is costing you."
64288
+ },
64289
+ audit: {
64290
+ label: "Audit",
64291
+ description: "Review the log of changes and activity for this agent."
64292
+ },
64293
+ reports: {
64294
+ label: "Data Reports",
64295
+ description: "Generate and download detailed reports to share or archive."
64296
+ }
64297
+ }
64298
+ };
64241
64299
  var voiceTabLabels$3 = {
64242
64300
  header: {
64243
64301
  title: "Voice",
64244
64302
  description: "Choose the voice your agent uses and how voice calls work."
64245
64303
  },
64304
+ capability: {
64305
+ title: "Voice calls",
64306
+ description: "Let people talk to this agent out loud and hear it reply, like a phone call. When on, pick the voice and fine-tune how calls behave below.",
64307
+ offHint: "Turn it on to let people start voice conversations with this agent."
64308
+ },
64246
64309
  subTabs: {
64247
64310
  voice: "Voice",
64248
64311
  callConfig: "Voice call"
@@ -64490,6 +64553,13 @@ var ltiTabLabels$3 = {
64490
64553
  title: "LTI",
64491
64554
  description: "Manage LTI agent links, signing keys, tools, and platform endpoints."
64492
64555
  },
64556
+ capability: {
64557
+ title: "LTI launches",
64558
+ description: "Let this agent be added to a Learning Management System (Canvas, Brightspace, Blackboard or Moodle) so students can open it right inside their course. When on, create the links, signing keys, and tools your LMS needs below.",
64559
+ offHint: "Turn it on to let this agent be embedded in an LMS and set up its links and keys.",
64560
+ toggleSuccess: "LTI setting updated",
64561
+ toggleError: "Couldn't update LTI setting"
64562
+ },
64493
64563
  subTabs: {
64494
64564
  agentLinks: "Links",
64495
64565
  keys: "Keys",
@@ -64893,6 +64963,7 @@ var en = {
64893
64963
  userProfileDropdownIndex: userProfileDropdownIndex$3,
64894
64964
  version: version$4,
64895
64965
  voiceTabCallConfigSection: voiceTabCallConfigSection$3,
64966
+ analyticsTabLabels: analyticsTabLabels$3,
64896
64967
  voiceTabLabels: voiceTabLabels$3,
64897
64968
  voiceTabVoicePicker: voiceTabVoicePicker$3,
64898
64969
  welcomeChatConversationStarters: welcomeChatConversationStarters$3,
@@ -65041,6 +65112,7 @@ var advancePagination$2 = {
65041
65112
  var advancedAdvanced$2 = {
65042
65113
  failedToUpdateSetting: "Échec de la mise à jour du paramètre",
65043
65114
  settingUpdatedSuccessfully: "Paramètre mis à jour avec succès",
65115
+ save: "Enregistrer",
65044
65116
  agentSettingUpdatedSuccessfully: "Paramètre de l'agent mis à jour avec succès",
65045
65117
  chatAreaSizeUpdatedSuccessfully: "Taille de la zone de discussion mise à jour avec succès",
65046
65118
  moreInfoAbout: "Plus d'informations sur {label}",
@@ -66411,11 +66483,16 @@ var clawSandboxAgentConfigPrompts$2 = {
66411
66483
  updateSuccess: "{label} mis à jour avec succès",
66412
66484
  updateError: "Échec de la mise à jour de {label}",
66413
66485
  moreInfoAriaLabel: "Plus d'informations sur {label}",
66414
- edit: "Modifier"
66486
+ edit: "Modifier",
66487
+ connectSandboxPrompt: "Connectez une instance de sandbox dans l'onglet Sandbox pour gérer les invites de l'agent.",
66488
+ enableSandboxPrompt: "Activez le bac à sable dédié dans l'onglet Sandbox et connectez-le à une instance pour gérer les invites de l'agent.",
66489
+ sandboxTabLabel: "onglet Sandbox"
66415
66490
  };
66416
66491
  var clawSandboxAgentSkills$2 = {
66417
66492
  loadingSkills: "Chargement des compétences...",
66418
66493
  connectSandboxPrompt: "Connectez une instance sandbox dans l'onglet Sandbox pour gérer les compétences.",
66494
+ enableSandboxPrompt: "Activez le bac à sable dédié dans l'onglet Sandbox et connectez-le à une instance pour gérer les compétences.",
66495
+ sandboxTabLabel: "onglet Sandbox",
66419
66496
  newSkill: "Nouvelle compétence",
66420
66497
  noSkillsAvailable: "Aucune compétence disponible pour cette plateforme. Créez-en une pour commencer.",
66421
66498
  moreInfoAbout: "Plus d'informations sur {name}",
@@ -67613,7 +67690,8 @@ var modalsPaywallModal$2 = {
67613
67690
  subscribeToGetAccess: "Abonnez-vous pour accéder à {itemName}",
67614
67691
  redirecting: "Redirection en cours...",
67615
67692
  pay: "Payer",
67616
- thisIncludes: "Cela comprend :"
67693
+ thisIncludes: "Cela comprend :",
67694
+ secureCheckout: "Paiement sécurisé"
67617
67695
  };
67618
67696
  var modalsPromptGalleryModal$2 = {
67619
67697
  promptGallery: "Galerie d'invites",
@@ -67934,6 +68012,11 @@ var privacyTabLabels$2 = {
67934
68012
  title: "Confidentialité",
67935
68013
  description: "Détectez et filtrez les informations personnellement identifiables des messages de chat."
67936
68014
  },
68015
+ capability: {
68016
+ title: "Filtrage des données personnelles",
68017
+ description: "Détectez et masquez automatiquement les informations personnelles — noms, e-mails, numéros de téléphone et plus — dans les messages avant que l'agent ne les voie. Une fois activé, choisissez ci-dessous ce qu'il faut détecter et comment le traiter.",
68018
+ offHint: "Activez-le pour détecter et masquer les informations personnelles dans les messages."
68019
+ },
67937
68020
  fields: {
67938
68021
  enableRouter: {
67939
68022
  label: "Activer le routeur de confidentialité",
@@ -67945,12 +68028,14 @@ var privacyTabLabels$2 = {
67945
68028
  options: {
67946
68029
  redact: "Masquer",
67947
68030
  mask: "Flouter",
67948
- block: "Bloquer"
68031
+ block: "Bloquer",
68032
+ allow: "Autoriser"
67949
68033
  },
67950
68034
  descriptions: {
67951
68035
  redact: "Les PII sont remplacées par leur type — ex. \"Email [EMAIL_ADDRESS]\".",
67952
68036
  mask: "Les PII sont masquées par des astérisques — ex. \"Email ***********\".",
67953
- block: "Le message est rejeté et votre message de blocage est affiché à l'utilisateur."
68037
+ block: "Le message est rejeté et votre message de blocage est affiché à l'utilisateur.",
68038
+ allow: "Les PII sont détectées mais laissées intactes — le message passe sans modification. Utilisez cette option pour surveiller ou auditer les informations personnelles sans altérer les messages."
67954
68039
  }
67955
68040
  },
67956
68041
  blockMessage: {
@@ -68640,6 +68725,11 @@ var screenshareTabLabels$2 = {
68640
68725
  title: "Partage d’écran",
68641
68726
  description: "Comment votre agent se comporte lorsqu’un utilisateur partage son écran pendant un appel vocal."
68642
68727
  },
68728
+ capability: {
68729
+ title: "Partage d’écran",
68730
+ description: "Permettez aux utilisateurs de partager leur écran pendant un appel vocal afin que l'agent voie ce qu'ils font et les guide étape par étape. Une fois activé, définissez les invites de partage d'écran ci-dessous.",
68731
+ offHint: "Activez-le pour permettre le partage d'écran pendant un appel et modifier ces invites."
68732
+ },
68643
68733
  disabledHint: "Le partage d’écran est actuellement désactivé pour cet agent. Ces invites seront enregistrées mais ne prendront effet qu’une fois activé.",
68644
68734
  fields: {
68645
68735
  systemPrompt: {
@@ -69406,7 +69496,8 @@ var tabsVoiceTab$2 = {
69406
69496
  var tasksTabLabels$2 = {
69407
69497
  header: {
69408
69498
  title: "Tâches",
69409
- description: "Configurez les tâches automatisées pour votre agent."
69499
+ description: "Configurez les tâches automatisées pour votre agent.",
69500
+ infoBox: "Laissez votre agent travailler selon son propre calendrier. Configurez des tâches récurrentes qu'il exécute automatiquement — comme des résumés quotidiens ou des rappels — sans que personne ait à le demander."
69410
69501
  },
69411
69502
  toolbar: {
69412
69503
  searchPlaceholder: "Rechercher toutes les tâches...",
@@ -69548,11 +69639,54 @@ var voiceTabCallConfigSection$2 = {
69548
69639
  refreshingAriaLabel: "Actualisation en cours",
69549
69640
  moreInfoAbout: "Plus d'infos sur {label}"
69550
69641
  };
69642
+ var analyticsTabLabels$2 = {
69643
+ header: {
69644
+ title: "Analytique",
69645
+ description: "Rapports d'utilisation et insights pour cet agent."
69646
+ },
69647
+ infoBox: "Découvrez comment cet agent est utilisé — qui discute avec lui, de quoi les gens parlent, combien il coûte, et plus encore. Choisissez un rapport ci-dessous pour approfondir.",
69648
+ openAria: "Ouvrir {label}",
69649
+ tabs: {
69650
+ overview: {
69651
+ label: "Vue d’ensemble",
69652
+ description: "Un aperçu global de l'utilisation et de l'engagement dans le temps."
69653
+ },
69654
+ users: {
69655
+ label: "Utilisateurs",
69656
+ description: "Voyez qui discute avec cet agent et à quel point ils sont actifs."
69657
+ },
69658
+ topics: {
69659
+ label: "Sujets",
69660
+ description: "Les sujets que les gens abordent le plus dans les conversations."
69661
+ },
69662
+ transcripts: {
69663
+ label: "Transcriptions",
69664
+ description: "Lisez les transcriptions complètes des conversations, message par message."
69665
+ },
69666
+ financial: {
69667
+ label: "Coûts",
69668
+ description: "Suivez l'utilisation des jetons et ce que cet agent vous coûte."
69669
+ },
69670
+ audit: {
69671
+ label: "Audit",
69672
+ description: "Consultez le journal des modifications et de l'activité de cet agent."
69673
+ },
69674
+ reports: {
69675
+ label: "Rapports de données",
69676
+ description: "Générez et téléchargez des rapports détaillés à partager ou à archiver."
69677
+ }
69678
+ }
69679
+ };
69551
69680
  var voiceTabLabels$2 = {
69552
69681
  header: {
69553
69682
  title: "Voix",
69554
69683
  description: "Choisissez la voix utilisée par votre agent et le fonctionnement des appels vocaux."
69555
69684
  },
69685
+ capability: {
69686
+ title: "Appels vocaux",
69687
+ description: "Permettez aux utilisateurs de parler à cet agent à voix haute et d'entendre sa réponse, comme lors d'un appel téléphonique. Une fois activé, choisissez la voix et affinez le comportement des appels ci-dessous.",
69688
+ offHint: "Activez-le pour permettre aux utilisateurs de démarrer des conversations vocales avec cet agent."
69689
+ },
69556
69690
  subTabs: {
69557
69691
  voice: "Voix",
69558
69692
  callConfig: "Appel vocal"
@@ -69800,6 +69934,13 @@ var ltiTabLabels$2 = {
69800
69934
  title: "LTI",
69801
69935
  description: "Gérez les liens LTI de l'agent, les clés de signature, les outils et les endpoints de la plateforme."
69802
69936
  },
69937
+ capability: {
69938
+ title: "Lancements LTI",
69939
+ description: "Permettez d'ajouter cet agent à un système de gestion de l'apprentissage (Canvas, Brightspace, Blackboard ou Moodle) afin que les étudiants puissent l'ouvrir directement dans leur cours. Une fois activé, créez ci-dessous les liens, les clés de signature et les outils dont votre LMS a besoin.",
69940
+ offHint: "Activez-le pour permettre l'intégration de cet agent dans un LMS et configurer ses liens et ses clés.",
69941
+ toggleSuccess: "Paramètre LTI mis à jour",
69942
+ toggleError: "Impossible de mettre à jour le paramètre LTI"
69943
+ },
69803
69944
  subTabs: {
69804
69945
  agentLinks: "Liens",
69805
69946
  keys: "Clés",
@@ -70203,6 +70344,7 @@ var fr = {
70203
70344
  userProfileDropdownIndex: userProfileDropdownIndex$2,
70204
70345
  version: version$3,
70205
70346
  voiceTabCallConfigSection: voiceTabCallConfigSection$2,
70347
+ analyticsTabLabels: analyticsTabLabels$2,
70206
70348
  voiceTabLabels: voiceTabLabels$2,
70207
70349
  voiceTabVoicePicker: voiceTabVoicePicker$2,
70208
70350
  welcomeChatConversationStarters: welcomeChatConversationStarters$2,
@@ -70351,6 +70493,7 @@ var advancePagination$1 = {
70351
70493
  var advancedAdvanced$1 = {
70352
70494
  failedToUpdateSetting: "Error al actualizar la configuración",
70353
70495
  settingUpdatedSuccessfully: "Configuración actualizada correctamente",
70496
+ save: "Guardar",
70354
70497
  agentSettingUpdatedSuccessfully: "Configuración del agente actualizada correctamente",
70355
70498
  chatAreaSizeUpdatedSuccessfully: "Tamaño del área de chat actualizado correctamente",
70356
70499
  moreInfoAbout: "Más información sobre {label}",
@@ -71721,11 +71864,16 @@ var clawSandboxAgentConfigPrompts$1 = {
71721
71864
  updateSuccess: "{label} actualizado correctamente",
71722
71865
  updateError: "Error al actualizar {label}",
71723
71866
  moreInfoAriaLabel: "Más información sobre {label}",
71724
- edit: "Editar"
71867
+ edit: "Editar",
71868
+ connectSandboxPrompt: "Conecta una instancia de sandbox en la pestaña Sandbox para gestionar las indicaciones del agente.",
71869
+ enableSandboxPrompt: "Activa el sandbox dedicado en la pestaña Sandbox y conéctalo a una instancia para gestionar las indicaciones del agente.",
71870
+ sandboxTabLabel: "pestaña Sandbox"
71725
71871
  };
71726
71872
  var clawSandboxAgentSkills$1 = {
71727
71873
  loadingSkills: "Cargando habilidades...",
71728
71874
  connectSandboxPrompt: "Conecta una instancia de sandbox en la pestaña Sandbox para gestionar habilidades.",
71875
+ enableSandboxPrompt: "Activa el sandbox dedicado en la pestaña Sandbox y conéctalo a una instancia para gestionar habilidades.",
71876
+ sandboxTabLabel: "pestaña Sandbox",
71729
71877
  newSkill: "Nueva habilidad",
71730
71878
  noSkillsAvailable: "No hay habilidades disponibles para esta plataforma. Crea una para empezar.",
71731
71879
  moreInfoAbout: "Más información sobre {name}",
@@ -72923,7 +73071,8 @@ var modalsPaywallModal$1 = {
72923
73071
  subscribeToGetAccess: "Suscríbete para acceder a {itemName}",
72924
73072
  redirecting: "Redirigiendo...",
72925
73073
  pay: "Pagar",
72926
- thisIncludes: "Esto incluye:"
73074
+ thisIncludes: "Esto incluye:",
73075
+ secureCheckout: "Pago seguro"
72927
73076
  };
72928
73077
  var modalsPromptGalleryModal$1 = {
72929
73078
  promptGallery: "Galería de instrucciones",
@@ -73244,6 +73393,11 @@ var privacyTabLabels$1 = {
73244
73393
  title: "Privacidad",
73245
73394
  description: "Detecta y filtra información de identificación personal de los mensajes del chat."
73246
73395
  },
73396
+ capability: {
73397
+ title: "Filtrado de datos personales",
73398
+ description: "Detecta y oculta automáticamente la información personal — nombres, correos, números de teléfono y más — en los mensajes antes de que el agente los vea. Cuando esté activado, elige a continuación qué detectar y cómo tratarlo.",
73399
+ offHint: "Actívalo para detectar y ocultar la información personal en los mensajes."
73400
+ },
73247
73401
  fields: {
73248
73402
  enableRouter: {
73249
73403
  label: "Activar enrutador de privacidad",
@@ -73255,12 +73409,14 @@ var privacyTabLabels$1 = {
73255
73409
  options: {
73256
73410
  redact: "Redactar",
73257
73411
  mask: "Enmascarar",
73258
- block: "Bloquear"
73412
+ block: "Bloquear",
73413
+ allow: "Permitir"
73259
73414
  },
73260
73415
  descriptions: {
73261
73416
  redact: "La PII se reemplaza por su tipo — ej. \"Email [EMAIL_ADDRESS]\".",
73262
73417
  mask: "La PII se oculta con asteriscos — ej. \"Email ***********\".",
73263
- block: "El mensaje es rechazado y se muestra al usuario el mensaje de bloqueo."
73418
+ block: "El mensaje es rechazado y se muestra al usuario el mensaje de bloqueo.",
73419
+ allow: "La PII se detecta pero se deja intacta — el mensaje pasa sin cambios. Use esta opción para supervisar o auditar la información personal sin alterar los mensajes."
73264
73420
  }
73265
73421
  },
73266
73422
  blockMessage: {
@@ -73950,6 +74106,11 @@ var screenshareTabLabels$1 = {
73950
74106
  title: "Pantalla compartida",
73951
74107
  description: "Cómo se comporta tu agente cuando un usuario comparte su pantalla durante una llamada de voz."
73952
74108
  },
74109
+ capability: {
74110
+ title: "Pantalla compartida",
74111
+ description: "Permite que las personas compartan su pantalla durante una llamada de voz para que el agente vea lo que hacen y las guíe paso a paso. Cuando esté activado, define las indicaciones de pantalla compartida a continuación.",
74112
+ offHint: "Actívalo para permitir compartir la pantalla durante una llamada y editar estas indicaciones."
74113
+ },
73953
74114
  disabledHint: "El uso compartido de pantalla está actualmente desactivado para este agente. Estas instrucciones se guardarán, pero solo surtirán efecto una vez que se active.",
73954
74115
  fields: {
73955
74116
  systemPrompt: {
@@ -74716,7 +74877,8 @@ var tabsVoiceTab$1 = {
74716
74877
  var tasksTabLabels$1 = {
74717
74878
  header: {
74718
74879
  title: "Tareas",
74719
- description: "Configure las tareas automatizadas para su agente."
74880
+ description: "Configure las tareas automatizadas para su agente.",
74881
+ infoBox: "Deja que tu agente trabaje según su propio calendario. Configura tareas recurrentes que ejecuta automáticamente —como resúmenes diarios o recordatorios— sin que nadie tenga que pedírselo."
74720
74882
  },
74721
74883
  toolbar: {
74722
74884
  searchPlaceholder: "Buscar todas las tareas...",
@@ -74858,11 +75020,54 @@ var voiceTabCallConfigSection$1 = {
74858
75020
  refreshingAriaLabel: "Actualizando",
74859
75021
  moreInfoAbout: "Más información sobre {label}"
74860
75022
  };
75023
+ var analyticsTabLabels$1 = {
75024
+ header: {
75025
+ title: "Analíticas",
75026
+ description: "Informes de uso e insights para este agente."
75027
+ },
75028
+ infoBox: "Descubre cómo se usa este agente: quién chatea con él, de qué hablan, cuánto cuesta y más. Elige un informe a continuación para profundizar.",
75029
+ openAria: "Abrir {label}",
75030
+ tabs: {
75031
+ overview: {
75032
+ label: "Resumen",
75033
+ description: "Una vista general del uso y la participación a lo largo del tiempo."
75034
+ },
75035
+ users: {
75036
+ label: "Usuarios",
75037
+ description: "Mira quién chatea con este agente y qué tan activos son."
75038
+ },
75039
+ topics: {
75040
+ label: "Temas",
75041
+ description: "Los temas que la gente menciona más en las conversaciones."
75042
+ },
75043
+ transcripts: {
75044
+ label: "Transcripciones",
75045
+ description: "Lee las transcripciones completas de las conversaciones, mensaje a mensaje."
75046
+ },
75047
+ financial: {
75048
+ label: "Costos",
75049
+ description: "Controla el uso de tokens y lo que te cuesta este agente."
75050
+ },
75051
+ audit: {
75052
+ label: "Auditoría",
75053
+ description: "Revisa el registro de cambios y actividad de este agente."
75054
+ },
75055
+ reports: {
75056
+ label: "Informes de datos",
75057
+ description: "Genera y descarga informes detallados para compartir o archivar."
75058
+ }
75059
+ }
75060
+ };
74861
75061
  var voiceTabLabels$1 = {
74862
75062
  header: {
74863
75063
  title: "Voz",
74864
75064
  description: "Elige la voz que usa tu agente y cómo funcionan las llamadas de voz."
74865
75065
  },
75066
+ capability: {
75067
+ title: "Llamadas de voz",
75068
+ description: "Permite que las personas hablen con este agente en voz alta y escuchen su respuesta, como en una llamada telefónica. Cuando esté activado, elige la voz y ajusta el comportamiento de las llamadas a continuación.",
75069
+ offHint: "Actívalo para permitir que las personas inicien conversaciones de voz con este agente."
75070
+ },
74866
75071
  subTabs: {
74867
75072
  voice: "Voz",
74868
75073
  callConfig: "Llamada de voz"
@@ -75110,6 +75315,13 @@ var ltiTabLabels$1 = {
75110
75315
  title: "LTI",
75111
75316
  description: "Gestiona los enlaces LTI del agente, las claves de firma, las herramientas y los endpoints de la plataforma."
75112
75317
  },
75318
+ capability: {
75319
+ title: "Lanzamientos LTI",
75320
+ description: "Permite añadir este agente a un sistema de gestión del aprendizaje (Canvas, Brightspace, Blackboard o Moodle) para que los estudiantes puedan abrirlo directamente en su curso. Cuando esté activado, crea a continuación los enlaces, las claves de firma y las herramientas que necesita tu LMS.",
75321
+ offHint: "Actívalo para permitir que este agente se integre en un LMS y configurar sus enlaces y claves.",
75322
+ toggleSuccess: "Ajuste de LTI actualizado",
75323
+ toggleError: "No se pudo actualizar el ajuste de LTI"
75324
+ },
75113
75325
  subTabs: {
75114
75326
  agentLinks: "Enlaces",
75115
75327
  keys: "Claves",
@@ -75513,6 +75725,7 @@ var es = {
75513
75725
  userProfileDropdownIndex: userProfileDropdownIndex$1,
75514
75726
  version: version$2,
75515
75727
  voiceTabCallConfigSection: voiceTabCallConfigSection$1,
75728
+ analyticsTabLabels: analyticsTabLabels$1,
75516
75729
  voiceTabLabels: voiceTabLabels$1,
75517
75730
  voiceTabVoicePicker: voiceTabVoicePicker$1,
75518
75731
  welcomeChatConversationStarters: welcomeChatConversationStarters$1,
@@ -75661,6 +75874,7 @@ var advancePagination = {
75661
75874
  var advancedAdvanced = {
75662
75875
  failedToUpdateSetting: "更新设置失败",
75663
75876
  settingUpdatedSuccessfully: "设置已成功更新",
75877
+ save: "保存",
75664
75878
  agentSettingUpdatedSuccessfully: "代理设置已成功更新",
75665
75879
  chatAreaSizeUpdatedSuccessfully: "聊天区域大小已成功更新",
75666
75880
  moreInfoAbout: "关于 {label} 的更多信息",
@@ -77031,11 +77245,16 @@ var clawSandboxAgentConfigPrompts = {
77031
77245
  updateSuccess: "{label} 更新成功",
77032
77246
  updateError: "更新 {label} 失败",
77033
77247
  moreInfoAriaLabel: "关于 {label} 的更多信息",
77034
- edit: "编辑"
77248
+ edit: "编辑",
77249
+ connectSandboxPrompt: "在沙盒选项卡中连接沙盒实例以管理智能体提示词。",
77250
+ enableSandboxPrompt: "在沙盒选项卡中启用专用沙盒并连接到实例,以管理智能体提示词。",
77251
+ sandboxTabLabel: "沙盒选项卡"
77035
77252
  };
77036
77253
  var clawSandboxAgentSkills = {
77037
77254
  loadingSkills: "正在加载技能...",
77038
77255
  connectSandboxPrompt: "在 Sandbox 标签页中连接一个 sandbox 实例以管理技能。",
77256
+ enableSandboxPrompt: "在 Sandbox 标签页中启用专用沙盒并连接到实例,以管理技能。",
77257
+ sandboxTabLabel: "Sandbox 标签页",
77039
77258
  newSkill: "新建技能",
77040
77259
  noSkillsAvailable: "该平台暂无可用技能。创建一个以开始使用。",
77041
77260
  moreInfoAbout: "关于 {name} 的更多信息",
@@ -78233,7 +78452,8 @@ var modalsPaywallModal = {
78233
78452
  subscribeToGetAccess: "订阅以获取 {itemName} 的访问权限",
78234
78453
  redirecting: "正在跳转...",
78235
78454
  pay: "支付",
78236
- thisIncludes: "包含以下内容:"
78455
+ thisIncludes: "包含以下内容:",
78456
+ secureCheckout: "安全结账"
78237
78457
  };
78238
78458
  var modalsPromptGalleryModal = {
78239
78459
  promptGallery: "提示库",
@@ -78554,6 +78774,11 @@ var privacyTabLabels = {
78554
78774
  title: "隐私",
78555
78775
  description: "检测并过滤聊天消息中的个人身份信息。"
78556
78776
  },
78777
+ capability: {
78778
+ title: "个人信息过滤",
78779
+ description: "在智能体看到消息之前,自动查找并隐藏其中的个人信息——姓名、电子邮件、电话号码等。开启后,可在下方选择要检测的内容及处理方式。",
78780
+ offHint: "开启后可检测并隐藏消息中的个人信息。"
78781
+ },
78557
78782
  fields: {
78558
78783
  enableRouter: {
78559
78784
  label: "启用隐私路由",
@@ -78565,12 +78790,14 @@ var privacyTabLabels = {
78565
78790
  options: {
78566
78791
  redact: "编辑",
78567
78792
  mask: "遮蔽",
78568
- block: "拦截"
78793
+ block: "拦截",
78794
+ allow: "允许"
78569
78795
  },
78570
78796
  descriptions: {
78571
78797
  redact: "PII 将被替换为其类型,例如:「Email [EMAIL_ADDRESS]」。",
78572
78798
  mask: "PII 将被星号隐藏,例如:「Email ***********」。",
78573
- block: "消息将被拒绝,并向用户显示您的拦截消息。"
78799
+ block: "消息将被拒绝,并向用户显示您的拦截消息。",
78800
+ allow: "检测到 PII 但不做处理——消息将原样通过。适用于在不修改消息的情况下监控或审计个人信息。"
78574
78801
  }
78575
78802
  },
78576
78803
  blockMessage: {
@@ -79260,6 +79487,11 @@ var screenshareTabLabels = {
79260
79487
  title: "屏幕共享",
79261
79488
  description: "当用户在语音通话中共享屏幕时,您的智能体的表现方式。"
79262
79489
  },
79490
+ capability: {
79491
+ title: "屏幕共享",
79492
+ description: "允许用户在语音通话中共享屏幕,以便智能体看到他们的操作并逐步引导。开启后,可在下方设置屏幕共享提示词。",
79493
+ offHint: "开启后可允许在通话中共享屏幕并编辑这些提示词。"
79494
+ },
79263
79495
  disabledHint: "屏幕共享当前已为该智能体关闭。这些提示将被保存,但开启后才会生效。",
79264
79496
  fields: {
79265
79497
  systemPrompt: {
@@ -80026,7 +80258,8 @@ var tabsVoiceTab = {
80026
80258
  var tasksTabLabels = {
80027
80259
  header: {
80028
80260
  title: "任务",
80029
- description: "为您的智能体配置自动化任务。"
80261
+ description: "为您的智能体配置自动化任务。",
80262
+ infoBox: "让您的智能体按自己的日程工作。设置它自动运行的周期性任务——例如每日摘要或提醒——无需任何人主动提出。"
80030
80263
  },
80031
80264
  toolbar: {
80032
80265
  searchPlaceholder: "搜索所有任务...",
@@ -80168,11 +80401,54 @@ var voiceTabCallConfigSection = {
80168
80401
  refreshingAriaLabel: "刷新中",
80169
80402
  moreInfoAbout: "关于 {label} 的更多信息"
80170
80403
  };
80404
+ var analyticsTabLabels = {
80405
+ header: {
80406
+ title: "分析",
80407
+ description: "该智能体的使用报告和数据洞察。"
80408
+ },
80409
+ infoBox: "了解该智能体的使用情况——谁在与它对话、大家在谈论什么、花费多少等等。在下方选择一份报告即可深入查看。",
80410
+ openAria: "打开{label}",
80411
+ tabs: {
80412
+ overview: {
80413
+ label: "概览",
80414
+ description: "随时间变化的使用情况和参与度的总体快照。"
80415
+ },
80416
+ users: {
80417
+ label: "用户",
80418
+ description: "查看谁在与该智能体对话以及他们的活跃程度。"
80419
+ },
80420
+ topics: {
80421
+ label: "主题",
80422
+ description: "对话中人们最常提及的主题。"
80423
+ },
80424
+ transcripts: {
80425
+ label: "对话记录",
80426
+ description: "逐条阅读完整的对话记录。"
80427
+ },
80428
+ financial: {
80429
+ label: "费用",
80430
+ description: "跟踪令牌用量以及该智能体的花费。"
80431
+ },
80432
+ audit: {
80433
+ label: "审计",
80434
+ description: "查看该智能体的更改和活动日志。"
80435
+ },
80436
+ reports: {
80437
+ label: "数据报告",
80438
+ description: "生成并下载详细报告以供分享或存档。"
80439
+ }
80440
+ }
80441
+ };
80171
80442
  var voiceTabLabels = {
80172
80443
  header: {
80173
80444
  title: "语音",
80174
80445
  description: "选择您的智能体使用的声音以及语音通话的工作方式。"
80175
80446
  },
80447
+ capability: {
80448
+ title: "语音通话",
80449
+ description: "让用户可以与该智能体语音交谈并听到其回复,就像打电话一样。开启后,可在下方选择声音并微调通话行为。",
80450
+ offHint: "开启后可让用户与该智能体开始语音对话。"
80451
+ },
80176
80452
  subTabs: {
80177
80453
  voice: "语音",
80178
80454
  callConfig: "语音通话"
@@ -80420,6 +80696,13 @@ var ltiTabLabels = {
80420
80696
  title: "LTI",
80421
80697
  description: "管理此智能体的 LTI 链接、签名密钥、工具和平台端点。"
80422
80698
  },
80699
+ capability: {
80700
+ title: "LTI 启动",
80701
+ description: "允许将此智能体添加到学习管理系统(Canvas、Brightspace、Blackboard 或 Moodle),以便学生可以直接在课程中打开它。开启后,可在下方创建您的 LMS 所需的链接、签名密钥和工具。",
80702
+ offHint: "开启后可将此智能体嵌入 LMS 并设置其链接和密钥。",
80703
+ toggleSuccess: "LTI 设置已更新",
80704
+ toggleError: "无法更新 LTI 设置"
80705
+ },
80423
80706
  subTabs: {
80424
80707
  agentLinks: "链接",
80425
80708
  keys: "密钥",
@@ -80823,6 +81106,7 @@ var zh = {
80823
81106
  userProfileDropdownIndex: userProfileDropdownIndex,
80824
81107
  version: version$1,
80825
81108
  voiceTabCallConfigSection: voiceTabCallConfigSection,
81109
+ analyticsTabLabels: analyticsTabLabels,
80826
81110
  voiceTabLabels: voiceTabLabels,
80827
81111
  voiceTabVoicePicker: voiceTabVoicePicker,
80828
81112
  welcomeChatConversationStarters: welcomeChatConversationStarters,
@@ -83254,7 +83538,7 @@ function getOwnKeys(obj) {
83254
83538
  );
83255
83539
  }
83256
83540
 
83257
- const useIsomorphicLayoutEffect$1 = typeof window !== "undefined" ? useLayoutEffect : useEffect;
83541
+ const useIsomorphicLayoutEffect$2 = typeof window !== "undefined" ? useLayoutEffect : useEffect;
83258
83542
 
83259
83543
  function useField(opts) {
83260
83544
  const [fieldApi] = useState(() => {
@@ -83267,8 +83551,8 @@ function useField(opts) {
83267
83551
  extendedApi.Field = Field;
83268
83552
  return extendedApi;
83269
83553
  });
83270
- useIsomorphicLayoutEffect$1(fieldApi.mount, [fieldApi]);
83271
- useIsomorphicLayoutEffect$1(() => {
83554
+ useIsomorphicLayoutEffect$2(fieldApi.mount, [fieldApi]);
83555
+ useIsomorphicLayoutEffect$2(() => {
83272
83556
  fieldApi.update(opts);
83273
83557
  });
83274
83558
  useStore(
@@ -83327,9 +83611,9 @@ function useForm(opts) {
83327
83611
  };
83328
83612
  return extendedApi;
83329
83613
  });
83330
- useIsomorphicLayoutEffect$1(formApi.mount, []);
83614
+ useIsomorphicLayoutEffect$2(formApi.mount, []);
83331
83615
  useStore(formApi.store, (state) => state.isSubmitting);
83332
- useIsomorphicLayoutEffect$1(() => {
83616
+ useIsomorphicLayoutEffect$2(() => {
83333
83617
  formApi.update(opts);
83334
83618
  });
83335
83619
  return formApi;
@@ -138620,6 +138904,10 @@ function Profile({ tenant, username, tenants, onClose, customization = {}, isAdm
138620
138904
  : activeTab === 'experience' && experienceSubTab === 'resume'
138621
138905
  ? { onClick: handleAddResume, upload: true, ariaLabel: t('profileIndex.ariaAddResume') }
138622
138906
  : null;
138907
+ // Rendered inline on the sub-tabs row (education/experience/resume), pushed to
138908
+ // the far right. `headerAdd` already encodes which sub-tab is active, so this
138909
+ // only appears on the sub-tabs that support adding/uploading.
138910
+ const headerAddButton = headerAdd && (jsx(Button$1, { size: "icon", onClick: headerAdd.onClick, className: "text-gray-700 bg-gradient-to-r from-[#2563EB] to-[#93C5FD] hover:opacity-90 text-white flex-shrink-0", "aria-label": headerAdd.ariaLabel, children: headerAdd.upload ? jsx(Upload, { className: "h-4 w-4" }) : jsx(Plus, { className: "h-4 w-4" }) }));
138623
138911
  const tabDescription = (id) => {
138624
138912
  const key = (isReadOnly && TAB_DESC_PREVIEW_KEYS[id]) || TAB_DESC_KEYS[id];
138625
138913
  return key ? t(`profileIndex.${key}`) : '';
@@ -138634,10 +138922,10 @@ function Profile({ tenant, username, tenants, onClose, customization = {}, isAdm
138634
138922
  ? 'bg-blue-50 text-blue-700 font-medium'
138635
138923
  : 'hover:bg-gray-50 text-gray-700 dark:text-gray-300 hover:text-gray-900 dark:hover:text-gray-100'}`, children: [jsx(tab.renderIcon, { className: "h-5 w-5 mr-3 flex-shrink-0", "aria-hidden": "true" }), jsx("span", { className: "truncate", children: tab.label })] }, tab.id))) }) }) })] }), jsx("nav", { className: "lg:hidden", "aria-label": t('profileIndex.ariaProfileTabsMobile'), children: jsx("div", { className: "w-full justify-start px-6 py-2 bg-white border-b border-gray-200 rounded-none h-auto overflow-x-auto", children: jsx("div", { className: "flex space-x-2", role: "tablist", "aria-orientation": "horizontal", children: TABS.map((tab) => (jsxs("button", { role: "tab", "aria-selected": activeTab === tab.id, "aria-controls": `${tab.id}-tabpanel`, id: `${tab.id}-tab-mobile`, onClick: () => setActiveTab(tab.id), className: `flex items-center gap-2 px-3 py-2 rounded-lg whitespace-nowrap text-sm transition-all ${activeTab === tab.id
138636
138924
  ? 'bg-blue-50 text-blue-600 font-medium'
138637
- : 'text-gray-600 hover:bg-gray-50'}`, children: [jsx(tab.renderIcon, { className: "h-4 w-4", "aria-hidden": "true" }), jsx("span", { className: "hidden sm:inline", children: tab.label }), jsx("span", { className: "sm:hidden", children: tab.label })] }, tab.id))) }) }) }), jsxs("div", { className: "flex-1 flex flex-col overflow-hidden", style: { height: '100%' }, children: [jsx("div", { className: "hidden lg:block flex-shrink-0 p-6 border-b border-gray-200 bg-white dark:bg-gray-900", children: jsxs("div", { className: "flex items-center justify-between", children: [jsxs("div", { children: [jsx("h3", { className: "text-lg font-medium text-gray-900 dark:text-gray-100 mb-2", children: (_f = (_e = TABS.find((t) => t.id === activeTab)) === null || _e === void 0 ? void 0 : _e.label) !== null && _f !== void 0 ? _f : activeTab }), jsx("p", { className: "text-gray-600 dark:text-gray-400 text-sm", children: tabDescription(activeTab) })] }), headerAdd && (jsx(Button$1, { size: "icon", onClick: headerAdd.onClick, className: "text-gray-700 bg-gradient-to-r from-[#2563EB] to-[#93C5FD] hover:opacity-90 text-white mr-4", "aria-label": headerAdd.ariaLabel, children: headerAdd.upload ? jsx(Upload, { className: "h-4 w-4" }) : jsx(Plus, { className: "h-4 w-4" }) }))] }) }), jsxs("div", { className: "flex-1 p-6 space-y-6", style: {
138925
+ : 'text-gray-600 hover:bg-gray-50'}`, children: [jsx(tab.renderIcon, { className: "h-4 w-4", "aria-hidden": "true" }), jsx("span", { className: "hidden sm:inline", children: tab.label }), jsx("span", { className: "sm:hidden", children: tab.label })] }, tab.id))) }) }) }), jsxs("div", { className: "flex-1 flex flex-col overflow-hidden", style: { height: '100%' }, children: [jsx("div", { className: "hidden lg:block flex-shrink-0 p-6 border-b border-gray-200 bg-white dark:bg-gray-900", children: jsx("div", { className: "flex items-center justify-between", children: jsxs("div", { children: [jsx("h3", { className: "text-lg font-medium text-gray-900 dark:text-gray-100 mb-2", children: (_f = (_e = TABS.find((t) => t.id === activeTab)) === null || _e === void 0 ? void 0 : _e.label) !== null && _f !== void 0 ? _f : activeTab }), jsx("p", { className: "text-gray-600 dark:text-gray-400 text-sm", children: tabDescription(activeTab) })] }) }) }), jsxs("div", { className: "flex-1 p-6 space-y-6", style: {
138638
138926
  overflowY: 'auto',
138639
138927
  overflowX: 'hidden',
138640
- }, role: "tabpanel", id: `${activeTab}-tabpanel`, "aria-labelledby": `${activeTab}-tab`, tabIndex: 0, children: [jsx("div", { className: "lg:hidden mb-6", children: jsxs("div", { className: "flex flex-row items-center sm:justify-between gap-3", children: [jsxs("div", { children: [jsx("h3", { className: "text-lg font-medium text-gray-900 dark:text-gray-100 mb-2", children: (_h = (_g = TABS.find((t) => t.id === activeTab)) === null || _g === void 0 ? void 0 : _g.label) !== null && _h !== void 0 ? _h : activeTab }), jsx("p", { className: "text-gray-600 dark:text-gray-400 text-sm", children: tabDescription(activeTab) })] }), headerAdd && (jsx(Button$1, { size: "icon", onClick: headerAdd.onClick, className: "text-gray-700 bg-gradient-to-r from-[#2563EB] to-[#93C5FD] hover:opacity-90 text-white", "aria-label": headerAdd.ariaLabel, children: headerAdd.upload ? jsx(Upload, { className: "h-4 w-4" }) : jsx(Plus, { className: "h-4 w-4" }) }))] }) }), activeTab === 'basic' && (jsx("div", { className: "space-y-6", children: jsxs("form", { onSubmit: (formEvent) => {
138928
+ }, role: "tabpanel", id: `${activeTab}-tabpanel`, "aria-labelledby": `${activeTab}-tab`, tabIndex: 0, children: [jsx("div", { className: "lg:hidden mb-6", children: jsx("div", { className: "flex flex-row items-center sm:justify-between gap-3", children: jsxs("div", { children: [jsx("h3", { className: "text-lg font-medium text-gray-900 dark:text-gray-100 mb-2", children: (_h = (_g = TABS.find((t) => t.id === activeTab)) === null || _g === void 0 ? void 0 : _g.label) !== null && _h !== void 0 ? _h : activeTab }), jsx("p", { className: "text-gray-600 dark:text-gray-400 text-sm", children: tabDescription(activeTab) })] }) }) }), activeTab === 'basic' && (jsx("div", { className: "space-y-6", children: jsxs("form", { onSubmit: (formEvent) => {
138641
138929
  formEvent.preventDefault();
138642
138930
  formEvent.stopPropagation();
138643
138931
  if (isReadOnly)
@@ -138712,7 +139000,7 @@ function Profile({ tenant, username, tenants, onClose, customization = {}, isAdm
138712
139000
  var _a;
138713
139001
  return (jsxs(Fragment$1, { children: [jsxs("div", { className: "relative mb-0", children: [jsx("div", { className: "absolute inset-y-0 left-4 flex items-center pointer-events-none", "aria-hidden": "true", children: jsx("div", { className: "bg-black text-white rounded w-8 h-8 flex items-center justify-center", children: jsx("span", { className: "font-bold text-sm", children: "X" }) }) }), jsx(Input, { id: "x", className: "w-full bg-gray-50 border-gray-200 focus:ring-blue-500 focus:border-blue-500 text-base py-3 pl-16 h-10", placeholder: t('profileIndex.placeholderX'), value: field.state.value, onChange: (e) => handleSocialLinkChange(e.target.value, field.handleChange, X_URL_PREFIX), disabled: socialForm.state.isSubmitting || isReadOnly })] }), jsx("p", { className: "text-red-500 dark:text-gray-400 text-sm", role: ((_a = field.state.meta.errors) === null || _a === void 0 ? void 0 : _a.length) ? 'alert' : undefined, "aria-live": "polite", children: field.state.meta.errors })] }));
138714
139002
  },
138715
- })] })] }) })), activeTab === 'education' && (jsxs(Tabs, { value: educationSubTab, onValueChange: setEducationSubTab, className: "space-y-4", children: [jsxs(TabsList, { children: [jsx(TabsTrigger, { value: "education", children: t('profileIndex.tabEducation') }), jsx(TabsTrigger, { value: "credentials", children: t('gradebookGradebookTab.typeCredentials') }), jsx(TabsTrigger, { value: "skills", children: t('gradebookGradebookTab.typeSkills') })] }), jsx(TabsContent, { value: "education", children: jsx(EducationTab, { org: tenant, username: username }) }), jsx(TabsContent, { value: "credentials", children: jsx(CredentialsList, { org: tenant, username: username }) }), jsx(TabsContent, { value: "skills", children: jsx(SkillsList, { org: tenant, username: username }) })] })), activeTab === 'gradebook' && jsx(GradebookTab, { org: tenant, username: username }), activeTab === 'experience' && (jsxs(Tabs, { value: experienceSubTab, onValueChange: setExperienceSubTab, className: "space-y-4", children: [jsxs(TabsList, { children: [jsx(TabsTrigger, { value: "experience", children: t('profileIndex.tabExperience') }), jsx(TabsTrigger, { value: "resume", children: t('profileIndex.tabResume') })] }), jsx(TabsContent, { value: "experience", children: jsx(ExperienceTab, { org: tenant, username: username }) }), jsx(TabsContent, { value: "resume", children: jsx(ResumeTab, { org: tenant, username: username }) })] })), activeTab === 'purchases' && jsx(PurchasesTab, { org: tenant, username: username }), activeTab === 'memory' && jsx(MemoryTab, { org: tenant, username: username }), activeTab === 'privacy' && jsx(ChatPrivacyTab, { org: tenant, username: username }), !isReadOnly && activeTab === 'security' && (jsx(Security, { app: currentSPA || '', email: (userMetadata === null || userMetadata === void 0 ? void 0 : userMetadata.email) || '', platformKey: tenant, onAccountDeleted: onAccountDeleted })), activeTab === 'advanced' && (localLLMProps || systemControlProps) && (jsxs("div", { className: "space-y-6", children: [localLLMProps && (jsx(LocalModelsContent, { isAvailable: localLLMProps.isAvailable, state: localLLMProps.state, ollamaStatus: localLLMProps.ollamaStatus, systemMemory: localLLMProps.systemMemory, isUsingFoundry: localLLMProps.isUsingFoundry, foundryModels: localLLMProps.foundryModels, selectedFoundryModel: localLLMProps.selectedFoundryModel, foundryStatus: localLLMProps.foundryStatus, onStartDownload: localLLMProps.onStartDownload, onCancelDownload: localLLMProps.onCancelDownload, onInstallOllama: localLLMProps.onInstallOllama, onStopManager: localLLMProps.onStopManager, onInstallFoundry: localLLMProps.onInstallFoundry, onCheckStatus: localLLMProps.onCheckStatus, onResetState: localLLMProps.onResetState, onSelectFoundryModel: localLLMProps.onSelectFoundryModel })), systemControlProps && (jsx(SystemControlContent, { isAvailable: systemControlProps.isAvailable, state: systemControlProps.state, status: systemControlProps.status, requiredSizeGb: systemControlProps.requiredSizeGb, ollamaStatus: systemControlProps.ollamaStatus, systemMemory: systemControlProps.systemMemory, accessibilityPermission: systemControlProps.accessibilityPermission, onInstall: systemControlProps.onInstall, onStop: systemControlProps.onStop, onCheckStatus: systemControlProps.onCheckStatus, onResetState: systemControlProps.onResetState, onRequestAccessibilityPermission: systemControlProps.onRequestAccessibilityPermission, onDownloadModel: systemControlProps.onDownloadModel }))] }))] }), !isReadOnly && ['basic', 'social'].includes(activeTab) && (jsx("div", { className: "flex-shrink-0 border-t border-gray-200 p-6 bg-white dark:bg-gray-900", children: jsxs("div", { className: "flex justify-end gap-3", children: [jsx(Button$1, { onClick: onClose, variant: "outline", children: t('profileIndex.buttonCancel') }), jsx(Button$1, { onClick: () => {
139003
+ })] })] }) })), activeTab === 'education' && (jsxs(Tabs, { value: educationSubTab, onValueChange: setEducationSubTab, className: "space-y-4", children: [jsxs("div", { className: "flex items-center justify-between gap-3", children: [jsxs(TabsList, { children: [jsx(TabsTrigger, { value: "education", children: t('profileIndex.tabEducation') }), jsx(TabsTrigger, { value: "credentials", children: t('gradebookGradebookTab.typeCredentials') }), jsx(TabsTrigger, { value: "skills", children: t('gradebookGradebookTab.typeSkills') })] }), headerAddButton] }), jsx(TabsContent, { value: "education", children: jsx(EducationTab, { org: tenant, username: username }) }), jsx(TabsContent, { value: "credentials", children: jsx(CredentialsList, { org: tenant, username: username }) }), jsx(TabsContent, { value: "skills", children: jsx(SkillsList, { org: tenant, username: username }) })] })), activeTab === 'gradebook' && jsx(GradebookTab, { org: tenant, username: username }), activeTab === 'experience' && (jsxs(Tabs, { value: experienceSubTab, onValueChange: setExperienceSubTab, className: "space-y-4", children: [jsxs("div", { className: "flex items-center justify-between gap-3", children: [jsxs(TabsList, { children: [jsx(TabsTrigger, { value: "experience", children: t('profileIndex.tabExperience') }), jsx(TabsTrigger, { value: "resume", children: t('profileIndex.tabResume') })] }), headerAddButton] }), jsx(TabsContent, { value: "experience", children: jsx(ExperienceTab, { org: tenant, username: username }) }), jsx(TabsContent, { value: "resume", children: jsx(ResumeTab, { org: tenant, username: username }) })] })), activeTab === 'purchases' && jsx(PurchasesTab, { org: tenant, username: username }), activeTab === 'memory' && jsx(MemoryTab, { org: tenant, username: username }), activeTab === 'privacy' && jsx(ChatPrivacyTab, { org: tenant, username: username }), !isReadOnly && activeTab === 'security' && (jsx(Security, { app: currentSPA || '', email: (userMetadata === null || userMetadata === void 0 ? void 0 : userMetadata.email) || '', platformKey: tenant, onAccountDeleted: onAccountDeleted })), activeTab === 'advanced' && (localLLMProps || systemControlProps) && (jsxs("div", { className: "space-y-6", children: [localLLMProps && (jsx(LocalModelsContent, { isAvailable: localLLMProps.isAvailable, state: localLLMProps.state, ollamaStatus: localLLMProps.ollamaStatus, systemMemory: localLLMProps.systemMemory, isUsingFoundry: localLLMProps.isUsingFoundry, foundryModels: localLLMProps.foundryModels, selectedFoundryModel: localLLMProps.selectedFoundryModel, foundryStatus: localLLMProps.foundryStatus, onStartDownload: localLLMProps.onStartDownload, onCancelDownload: localLLMProps.onCancelDownload, onInstallOllama: localLLMProps.onInstallOllama, onStopManager: localLLMProps.onStopManager, onInstallFoundry: localLLMProps.onInstallFoundry, onCheckStatus: localLLMProps.onCheckStatus, onResetState: localLLMProps.onResetState, onSelectFoundryModel: localLLMProps.onSelectFoundryModel })), systemControlProps && (jsx(SystemControlContent, { isAvailable: systemControlProps.isAvailable, state: systemControlProps.state, status: systemControlProps.status, requiredSizeGb: systemControlProps.requiredSizeGb, ollamaStatus: systemControlProps.ollamaStatus, systemMemory: systemControlProps.systemMemory, accessibilityPermission: systemControlProps.accessibilityPermission, onInstall: systemControlProps.onInstall, onStop: systemControlProps.onStop, onCheckStatus: systemControlProps.onCheckStatus, onResetState: systemControlProps.onResetState, onRequestAccessibilityPermission: systemControlProps.onRequestAccessibilityPermission, onDownloadModel: systemControlProps.onDownloadModel }))] }))] }), !isReadOnly && ['basic', 'social'].includes(activeTab) && (jsx("div", { className: "flex-shrink-0 border-t border-gray-200 p-6 bg-white dark:bg-gray-900", children: jsxs("div", { className: "flex justify-end gap-3", children: [jsx(Button$1, { onClick: onClose, variant: "outline", children: t('profileIndex.buttonCancel') }), jsx(Button$1, { onClick: () => {
138716
139004
  if (activeTab === 'basic') {
138717
139005
  basicForm.handleSubmit();
138718
139006
  }
@@ -148711,26 +148999,19 @@ const ChatPrivacyContent = ({ platformKey, username }) => {
148711
148999
  };
148712
149000
 
148713
149001
  function StringSettingInput({ value, defaultValue, disabled, onSave, }) {
148714
- const [localValue, setLocalValue] = useState(value || defaultValue);
148715
- const debounceRef = useRef(null);
149002
+ const t = useT();
149003
+ const savedValue = value || defaultValue;
149004
+ const [localValue, setLocalValue] = useState(savedValue);
148716
149005
  useEffect(() => {
148717
- setLocalValue(value || defaultValue);
148718
- }, [value, defaultValue]);
148719
- const handleChange = (newValue) => {
148720
- setLocalValue(newValue);
148721
- if (debounceRef.current)
148722
- clearTimeout(debounceRef.current);
148723
- debounceRef.current = setTimeout(() => {
148724
- onSave(newValue);
148725
- }, 800);
149006
+ setLocalValue(savedValue);
149007
+ }, [savedValue]);
149008
+ const isDirty = localValue !== savedValue;
149009
+ const handleSave = () => {
149010
+ if (!isDirty || disabled)
149011
+ return;
149012
+ onSave(localValue);
148726
149013
  };
148727
- useEffect(() => {
148728
- return () => {
148729
- if (debounceRef.current)
148730
- clearTimeout(debounceRef.current);
148731
- };
148732
- }, []);
148733
- return (jsxs("div", { className: "flex items-center gap-2", children: [jsx(Input, { value: localValue, onChange: (e) => handleChange(e.target.value), disabled: disabled, className: "max-w-[240px] w-[110px] sm:w-[230px] font-medium text-[#646464] text-sm" }), disabled && (jsx("div", { className: "w-4 h-4 border-2 border-blue-500 border-t-transparent rounded-full animate-spin" }))] }));
149014
+ return (jsxs("div", { className: "flex items-center gap-2", children: [isDirty && (jsx(Button$1, { type: "button", size: "sm", onClick: handleSave, disabled: disabled, className: "h-8 bg-blue-500 hover:bg-blue-600 text-white", children: t('advancedAdvanced.save') })), jsx(Input, { value: localValue, onChange: (e) => setLocalValue(e.target.value), disabled: disabled, className: "max-w-[240px] w-[110px] sm:w-[230px] font-medium text-[#646464] text-sm" }), disabled && (jsx("div", { className: "w-4 h-4 border-2 border-blue-500 border-t-transparent rounded-full animate-spin" }))] }));
148734
149015
  }
148735
149016
  function AdvancedTab({ platformKey, username, currentSPA, authURL, currentPlatformBaseDomain, }) {
148736
149017
  const t = useT();
@@ -148776,6 +149057,7 @@ function AdvancedTab({ platformKey, username, currentSPA, authURL, currentPlatfo
148776
149057
  'overall_default_mentor',
148777
149058
  'help_center_url',
148778
149059
  'monetization_base_path',
149060
+ 'skills_welcome_tagline',
148779
149061
  ];
148780
149062
  const configurableMetadatas = allMetadatas.filter((metadata) => (typeof metadata.defaultValue === 'boolean' ||
148781
149063
  (typeof metadata.defaultValue === 'string' &&
@@ -169551,7 +169833,7 @@ var EditorContentWithKey = forwardRef(
169551
169833
  }
169552
169834
  );
169553
169835
  var EditorContent = React__default.memo(EditorContentWithKey);
169554
- var useIsomorphicLayoutEffect = typeof window !== "undefined" ? useLayoutEffect : useEffect;
169836
+ var useIsomorphicLayoutEffect$1 = typeof window !== "undefined" ? useLayoutEffect : useEffect;
169555
169837
  var EditorStateManager = class {
169556
169838
  constructor(initialEditor) {
169557
169839
  this.transactionNumber = 0;
@@ -169619,7 +169901,7 @@ function useEditorState(options) {
169619
169901
  options.selector,
169620
169902
  (_a = options.equalityFn) != null ? _a : deepEqual
169621
169903
  );
169622
- useIsomorphicLayoutEffect(() => {
169904
+ useIsomorphicLayoutEffect$1(() => {
169623
169905
  return editorStateManager.watch(options.editor);
169624
169906
  }, [options.editor, editorStateManager]);
169625
169907
  useDebugValue(selectedState);
@@ -222278,30 +222560,21 @@ function SandboxConfig({ platformKey, mentorUniqueId, username }) {
222278
222560
  ? t('clawSandboxSandboxConfig.noInstancesMatchSearch')
222279
222561
  : t('clawSandboxSandboxConfig.noInstancesAvailable') }) })) : (pagedInstances.map((inst) => {
222280
222562
  var _a;
222281
- return (jsxs(TableRow, { className: "border-b last:border-0", children: [jsx(TableCell, { className: "p-3 font-medium whitespace-nowrap text-[#646464]", children: inst.name }), jsx(TableCell, { className: "p-3 whitespace-nowrap text-[#646464] truncate max-w-[250px]", children: jsx(TooltipProvider, { children: jsxs(Tooltip$1, { children: [jsx(TooltipTrigger, { asChild: true, children: jsx("span", { className: "text-blue-600 hover:text-blue-800 cursor-default", children: inst.server_url }) }), jsx(TooltipContent, { className: "bg-gray-700 px-3 py-2 text-sm font-medium text-white shadow-sm", children: jsx("p", { children: inst.server_url }) })] }) }) }), jsx(TableCell, { className: "p-3 whitespace-nowrap text-[#646464]", children: inst.claw_type }), jsx(TableCell, { className: "p-3 whitespace-nowrap", children: jsx(StatusDot, { value: inst.status, kind: "status" }) }), jsx(TableCell, { className: "p-3 whitespace-nowrap", children: jsx(StatusDot, { value: inst.last_health_status, kind: "health" }) }), jsx(TableCell, { className: "p-3 whitespace-nowrap text-[#646464]", children: (_a = inst.claw_version) !== null && _a !== void 0 ? _a : '—' }), jsx(TableCell, { className: "p-3 whitespace-nowrap text-[#646464]", children: timeAgo(inst.last_health_check, t('clawSandboxSandboxConfig.never')) }), jsx(TableCell, { className: "p-3 text-right", children: jsxs(DropdownMenu, { children: [jsx(DropdownMenuTrigger, { asChild: true, children: jsxs(Button$1, { variant: "ghost", size: "sm", disabled: connectingInstanceId === inst.id, "aria-label": connectingInstanceId === inst.id
222282
- ? t('clawSandboxSandboxConfig.connectingInstance')
222283
- : t('clawSandboxSandboxConfig.actions'), children: [connectingInstanceId === inst.id ? (jsx(LoaderCircle, { className: "h-4 w-4 animate-spin" })) : (jsx(Ellipsis, { className: "h-4 w-4" })), jsx("span", { className: "sr-only", children: connectingInstanceId === inst.id
222284
- ? t('clawSandboxSandboxConfig.connecting')
222285
- : t('clawSandboxSandboxConfig.actions') })] }) }), jsxs(DropdownMenuContent, { align: "end", children: [(() => {
222286
- const unhealthy = isInstanceUnhealthy(inst.status);
222287
- // Don't use the `disabled` prop Radix sets
222288
- // pointer-events:none on disabled items, which
222289
- // also kills the Tooltip hover. Instead block the
222290
- // action via onSelect and dim with opacity.
222291
- const connectItem = (jsxs(DropdownMenuItem, { className: cn('cursor-pointer', (unhealthy || isCreating || connectingInstanceId !== null) &&
222292
- 'opacity-50 cursor-not-allowed'), onSelect: (e) => {
222293
- if (unhealthy ||
222294
- isCreating ||
222295
- connectingInstanceId !== null) {
222296
- e.preventDefault();
222297
- return;
222298
- }
222299
- handleConnect(inst.id);
222300
- }, children: [jsx(Link2, { className: "mr-2 h-4 w-4" }), t('clawSandboxSandboxConfig.connect')] }));
222301
- if (!unhealthy)
222302
- return connectItem;
222303
- return (jsx(TooltipProvider, { children: jsxs(Tooltip$1, { children: [jsx(TooltipTrigger, { asChild: true, children: connectItem }), jsx(TooltipContent, { side: "left", collisionPadding: 12, className: "max-w-[260px] whitespace-normal break-words rounded-lg bg-gray-700 px-3 py-2 text-xs font-medium leading-snug text-white shadow-sm", children: t('clawSandboxSandboxConfig.instanceUnhealthyTooltip') })] }) }));
222304
- })(), jsxs(DropdownMenuItem, { className: "cursor-pointer", onClick: () => runInstanceChecks(inst.id), disabled: checkingInstanceId !== null, children: [checkingInstanceId === inst.id ? (jsx(LoaderCircle, { className: "mr-2 h-4 w-4 animate-spin" })) : (jsx(Activity, { className: "mr-2 h-4 w-4" })), t('clawSandboxSandboxConfig.runChecks')] }), jsxs(DropdownMenuItem, { className: "cursor-pointer", onClick: () => setEditingInstance(inst), children: [jsx(Pen, { className: "mr-2 h-4 w-4" }), t('clawSandboxSandboxConfig.edit')] }), jsxs(DropdownMenuItem, { variant: "destructive", className: "cursor-pointer", onClick: () => setDeletingInstanceId(inst.id), children: [jsx(Trash2, { className: "mr-2 h-4 w-4" }), t('clawSandboxSandboxConfig.delete')] })] })] }) })] }, inst.id));
222563
+ return (jsxs(TableRow, { className: "border-b last:border-0", children: [jsx(TableCell, { className: "p-3 font-medium whitespace-nowrap text-[#646464]", children: inst.name }), jsx(TableCell, { className: "p-3 whitespace-nowrap text-[#646464] truncate max-w-[250px]", children: jsx(TooltipProvider, { children: jsxs(Tooltip$1, { children: [jsx(TooltipTrigger, { asChild: true, children: jsx("span", { className: "text-blue-600 hover:text-blue-800 cursor-default", children: inst.server_url }) }), jsx(TooltipContent, { className: "bg-gray-700 px-3 py-2 text-sm font-medium text-white shadow-sm", children: jsx("p", { children: inst.server_url }) })] }) }) }), jsx(TableCell, { className: "p-3 whitespace-nowrap text-[#646464]", children: inst.claw_type }), jsx(TableCell, { className: "p-3 whitespace-nowrap", children: jsx(StatusDot, { value: inst.status, kind: "status" }) }), jsx(TableCell, { className: "p-3 whitespace-nowrap", children: jsx(StatusDot, { value: inst.last_health_status, kind: "health" }) }), jsx(TableCell, { className: "p-3 whitespace-nowrap text-[#646464]", children: (_a = inst.claw_version) !== null && _a !== void 0 ? _a : '—' }), jsx(TableCell, { className: "p-3 whitespace-nowrap text-[#646464]", children: timeAgo(inst.last_health_check, t('clawSandboxSandboxConfig.never')) }), jsx(TableCell, { className: "p-3 text-right", children: (() => {
222564
+ const unhealthy = isInstanceUnhealthy(inst.status);
222565
+ const isThisConnecting = connectingInstanceId === inst.id;
222566
+ const connectDisabled = unhealthy || isCreating || connectingInstanceId !== null;
222567
+ // Surfaced as a first-class button (not tucked in the
222568
+ // three-dot menu) so connecting is one click. A
222569
+ // disabled button swallows pointer events, so wrap it
222570
+ // in a span when we need the unhealthy tooltip to show.
222571
+ const connectButton = (jsxs(Button$1, { variant: "outline", size: "sm", className: "cursor-pointer", disabled: connectDisabled, onClick: () => handleConnect(inst.id), "aria-label": isThisConnecting
222572
+ ? t('clawSandboxSandboxConfig.connectingInstance')
222573
+ : t('clawSandboxSandboxConfig.connect'), "data-testid": `connect-instance-${inst.id}`, children: [isThisConnecting ? (jsx(LoaderCircle, { className: "mr-2 h-4 w-4 animate-spin" })) : (jsx(Link2, { className: "mr-2 h-4 w-4" })), isThisConnecting
222574
+ ? t('clawSandboxSandboxConfig.connecting')
222575
+ : t('clawSandboxSandboxConfig.connect')] }));
222576
+ return (jsxs("div", { className: "flex items-center justify-end gap-2", children: [unhealthy ? (jsx(TooltipProvider, { children: jsxs(Tooltip$1, { children: [jsx(TooltipTrigger, { asChild: true, children: jsx("span", { tabIndex: 0, children: connectButton }) }), jsx(TooltipContent, { side: "left", collisionPadding: 12, className: "max-w-[260px] rounded-lg bg-gray-700 px-3 py-2 text-xs leading-snug font-medium break-words whitespace-normal text-white shadow-sm", children: t('clawSandboxSandboxConfig.instanceUnhealthyTooltip') })] }) })) : (connectButton), jsxs(DropdownMenu, { children: [jsx(DropdownMenuTrigger, { asChild: true, children: jsxs(Button$1, { variant: "ghost", size: "sm", "aria-label": t('clawSandboxSandboxConfig.actions'), children: [jsx(Ellipsis, { className: "h-4 w-4" }), jsx("span", { className: "sr-only", children: t('clawSandboxSandboxConfig.actions') })] }) }), jsxs(DropdownMenuContent, { align: "end", children: [jsxs(DropdownMenuItem, { className: "cursor-pointer", onClick: () => runInstanceChecks(inst.id), disabled: checkingInstanceId !== null, children: [checkingInstanceId === inst.id ? (jsx(LoaderCircle, { className: "mr-2 h-4 w-4 animate-spin" })) : (jsx(Activity, { className: "mr-2 h-4 w-4" })), t('clawSandboxSandboxConfig.runChecks')] }), jsxs(DropdownMenuItem, { className: "cursor-pointer", onClick: () => setEditingInstance(inst), children: [jsx(Pen, { className: "mr-2 h-4 w-4" }), t('clawSandboxSandboxConfig.edit')] }), jsxs(DropdownMenuItem, { variant: "destructive", className: "cursor-pointer", onClick: () => setDeletingInstanceId(inst.id), children: [jsx(Trash2, { className: "mr-2 h-4 w-4" }), t('clawSandboxSandboxConfig.delete')] })] })] })] }));
222577
+ })() })] }, inst.id));
222305
222578
  })) })] }) }) }) }), jsx(IblPagination, { currentPage: currentPage, totalPages: totalPages, onPageChange: setCurrentPage, disabled: false }), jsx(OverlayModal, { open: showNewInstanceForm, onClose: () => setShowNewInstanceForm(false), title: t('clawSandboxSandboxConfig.newInstanceTitle'), className: "max-w-lg", children: jsxs("div", { className: "grid gap-4", children: [jsxs("div", { className: "space-y-2", children: [jsx(Label$2, { htmlFor: "new-instance-name", className: "text-sm font-medium text-[#646464]", children: t('clawSandboxSandboxConfig.fieldName') }), jsx(Input, { id: "new-instance-name", name: "new-instance-name", value: newInstance.name, onChange: (e) => setNewInstance({ ...newInstance, name: e.target.value }), placeholder: t('clawSandboxSandboxConfig.namePlaceholder'), className: "py-6" })] }), jsxs("div", { className: "space-y-2", children: [jsx(Label$2, { htmlFor: "new-instance-type", className: "text-sm font-medium text-[#646464]", children: t('clawSandboxSandboxConfig.fieldType') }), jsxs(Select$1, { value: newInstance.claw_type, onValueChange: (value) => setNewInstance({ ...newInstance, claw_type: value }), children: [jsx(SelectTrigger, { id: "new-instance-type", className: "py-6", children: jsx(SelectValue, {}) }), jsxs(SelectContent, { children: [jsx(SelectItem, { value: "openclaw", children: "OpenClaw" }), jsx(SelectItem, { value: "ironclaw", children: "IronClaw" })] })] })] }), jsxs("div", { className: "space-y-2", children: [jsx(Label$2, { htmlFor: "new-instance-url", className: "text-sm font-medium text-[#646464]", children: t('clawSandboxSandboxConfig.fieldServerUrl') }), jsx(Input, { id: "new-instance-url", name: "new-instance-url", value: newInstance.server_url, onChange: (e) => setNewInstance({ ...newInstance, server_url: e.target.value }), placeholder: t('clawSandboxSandboxConfig.serverUrlPlaceholder'), className: "py-6" })] }), jsxs("div", { className: "space-y-2", children: [jsx(Label$2, { htmlFor: "new-instance-token", className: "text-sm font-medium text-[#646464]", children: t('clawSandboxSandboxConfig.fieldGatewayToken') }), jsx(Input, { id: "new-instance-token", name: "new-instance-token", value: newInstance.gateway_token, onChange: (e) => setNewInstance({ ...newInstance, gateway_token: e.target.value }), placeholder: t('clawSandboxSandboxConfig.gatewayTokenPlaceholder'), type: "password", className: "py-6", required: true })] }), jsxs("div", { className: "flex justify-end gap-2 pt-2", children: [jsx(Button$1, { variant: "outline", onClick: () => setShowNewInstanceForm(false), children: t('clawSandboxSandboxConfig.cancel') }), jsx(Button$1, { onClick: handleCreateInstance, disabled: isCreatingInstance ||
222306
222579
  !newInstance.name ||
222307
222580
  !newInstance.server_url ||
@@ -222471,12 +222744,14 @@ function AgentConfigPrompts({ platformKey, mentorUniqueId }) {
222471
222744
  if (isLoading) {
222472
222745
  return (jsx("div", { className: "flex items-center justify-center py-10", children: jsx(LoaderCircle, { className: "h-5 w-5 animate-spin text-blue-500" }) }));
222473
222746
  }
222474
- // Sandbox not connected or disabled agent config prompts only apply when
222475
- // the mentor has an active sandbox to push them to.
222747
+ // Agent config prompts only apply once a Claw instance is connected. The
222748
+ // host (Prompts tab) already only renders this section for a connected
222749
+ // sandbox, but we guard here too so the component is safe to drop in
222750
+ // anywhere.
222476
222751
  if (!isSandboxActive) {
222477
222752
  return null;
222478
222753
  }
222479
- return (jsxs(Fragment$1, { children: [jsx("div", { className: "space-y-6", children: AGENT_WORKSPACE_FIELDS.map(({ key, labelKey, descriptionKey }) => {
222754
+ return (jsxs(Fragment$1, { children: [jsx("div", { className: "space-y-6", "data-testid": "agent-config-prompts-fields", children: AGENT_WORKSPACE_FIELDS.map(({ key, labelKey, descriptionKey }) => {
222480
222755
  var _a;
222481
222756
  const label = t(labelKey);
222482
222757
  const description = t(descriptionKey);
@@ -222495,11 +222770,16 @@ const EMPTY_SKILL_FORM = {
222495
222770
  function AgentSkills({ platformKey, mentorUniqueId }) {
222496
222771
  var _a;
222497
222772
  const t = useT();
222498
- // Gate skills on having a connected sandbox config.
222499
- const { data: clawConfig, isError: isClawConfigError, isLoading: isLoadingClawConfig, } = useGetClawMentorConfigQuery({ org: platformKey, mentorUniqueId });
222500
- const isSandboxActive = !isClawConfigError && Boolean(clawConfig);
222501
- const { data: availableSkills, isLoading: isLoadingSkills } = useGetAgentSkillsQuery({ org: platformKey }, { skip: !isSandboxActive });
222502
- const { data: assignments, isLoading: isLoadingAssignments } = useGetMentorSkillAssignmentsQuery({ org: platformKey, mentorUniqueId }, { skip: !isSandboxActive });
222773
+ // Skills are managed independently of the sandbox connection — org-level
222774
+ // skills and the mentor's assignments both resolve without a wired Claw
222775
+ // instance, so we always fetch and let admins add/assign skills freely.
222776
+ const { data: availableSkills, isLoading: isLoadingSkills } = useGetAgentSkillsQuery({
222777
+ org: platformKey,
222778
+ });
222779
+ const { data: assignments, isLoading: isLoadingAssignments } = useGetMentorSkillAssignmentsQuery({
222780
+ org: platformKey,
222781
+ mentorUniqueId,
222782
+ });
222503
222783
  // Assignment mutations (toggle on mentor)
222504
222784
  const [createAssignment, { isLoading: isCreatingAssignment }] = useCreateMentorSkillAssignmentMutation();
222505
222785
  const [updateAssignment, { isLoading: isUpdatingAssignment }] = useUpdateMentorSkillAssignmentMutation();
@@ -222512,7 +222792,7 @@ function AgentSkills({ platformKey, mentorUniqueId }) {
222512
222792
  const [editingSkill, setEditingSkill] = useState(null);
222513
222793
  const [deletingSkill, setDeletingSkill] = useState(null);
222514
222794
  const [form, setForm] = useState(EMPTY_SKILL_FORM);
222515
- const isLoading = isLoadingClawConfig || (isSandboxActive && (isLoadingSkills || isLoadingAssignments));
222795
+ const isLoading = isLoadingSkills || isLoadingAssignments;
222516
222796
  const isTogglingMentorSkill = isCreatingAssignment || isUpdatingAssignment || isDeletingAssignment;
222517
222797
  const skills = (availableSkills !== null && availableSkills !== void 0 ? availableSkills : []).filter((s) => s.enabled);
222518
222798
  // Skill assignments are now keyed by skill UUID (the new stable identifier).
@@ -222635,12 +222915,7 @@ function AgentSkills({ platformKey, mentorUniqueId }) {
222635
222915
  if (isLoading) {
222636
222916
  return (jsxs("div", { className: "flex items-center gap-2 p-4", children: [jsx(LoaderCircle, { className: "h-4 w-4 animate-spin text-blue-500" }), jsx("span", { className: "text-sm text-gray-500", children: t('clawSandboxAgentSkills.loadingSkills') })] }));
222637
222917
  }
222638
- // Sandbox not connected or disabled skills are runtime sandbox features and
222639
- // can't be assigned to a mentor that has no active sandbox to run them.
222640
- if (!isSandboxActive) {
222641
- return (jsx("div", { className: "flex items-center justify-center rounded-lg border p-6", children: jsx("p", { className: "text-sm text-gray-500", children: t('clawSandboxAgentSkills.connectSandboxPrompt') }) }));
222642
- }
222643
- return (jsxs("div", { className: "space-y-4", children: [jsx("div", { className: "flex items-center justify-end", children: jsxs(Button$1, { onClick: openNewSkillDialog, size: "sm", className: "cursor-pointer bg-gradient-to-r from-[#2563EB] to-[#93C5FD] text-white hover:opacity-90", children: [jsx(Plus, { className: "h-4 w-4" }), t('clawSandboxAgentSkills.newSkill')] }) }), skills.length === 0 ? (jsx("div", { className: "flex items-center justify-center rounded-lg border p-6", children: jsx("p", { className: "text-sm text-gray-500", children: t('clawSandboxAgentSkills.noSkillsAvailable') }) })) : (jsx("div", { className: "space-y-6", children: skills.map((skill) => {
222918
+ return (jsxs("div", { className: "space-y-4", "data-testid": "agent-skills-content", children: [jsx("div", { className: "flex items-center justify-end", children: jsxs(Button$1, { onClick: openNewSkillDialog, size: "sm", className: "cursor-pointer bg-gradient-to-r from-[#2563EB] to-[#93C5FD] text-white hover:opacity-90", children: [jsx(Plus, { className: "h-4 w-4" }), t('clawSandboxAgentSkills.newSkill')] }) }), skills.length === 0 ? (jsx("div", { className: "flex items-center justify-center rounded-lg border p-6", children: jsx("p", { className: "text-sm text-gray-500", children: t('clawSandboxAgentSkills.noSkillsAvailable') }) })) : (jsx("div", { className: "space-y-6", children: skills.map((skill) => {
222644
222919
  var _a;
222645
222920
  const assignment = assignmentsBySkillUniqueId.get(skill.unique_id);
222646
222921
  const isEnabled = (_a = assignment === null || assignment === void 0 ? void 0 : assignment.enabled) !== null && _a !== void 0 ? _a : false;
@@ -222648,7 +222923,9 @@ function AgentSkills({ platformKey, mentorUniqueId }) {
222648
222923
  name: skill.name,
222649
222924
  }), children: jsx(Info$3, { className: "h-4 w-4 text-gray-400" }) }), jsx(TooltipContent, { className: "ibl-tooltip-content", children: jsx("p", { children: skill.description }) })] }) })), jsxs("span", { className: "hidden sm:inline text-xs text-gray-400", children: ["v", skill.version] })] }), jsxs("div", { className: "flex items-center gap-2", children: [jsx(Switch, { checked: isEnabled, onCheckedChange: (checked) => handleToggle(skill, checked), disabled: isTogglingMentorSkill, className: "cursor-pointer data-[state=checked]:bg-blue-500", "aria-label": t(isEnabled
222650
222925
  ? 'clawSandboxAgentSkills.skillEnabledLabel'
222651
- : 'clawSandboxAgentSkills.skillDisabledLabel', { name: skill.name }) }), jsxs(DropdownMenu, { children: [jsx(DropdownMenuTrigger, { asChild: true, children: jsx(Button$1, { variant: "ghost", size: "sm", "aria-label": t('clawSandboxAgentSkills.skillActions', { name: skill.name }), children: jsx(Ellipsis, { className: "h-4 w-4" }) }) }), jsxs(DropdownMenuContent, { align: "end", children: [jsxs(DropdownMenuItem, { className: "cursor-pointer", onClick: () => openEditSkillDialog(skill), children: [jsx(Pen, { className: "mr-2 h-4 w-4" }), t('clawSandboxAgentSkills.edit')] }), jsxs(DropdownMenuItem, { variant: "destructive", className: "cursor-pointer", onClick: () => setDeletingSkill(skill), children: [jsx(Trash2, { className: "mr-2 h-4 w-4" }), t('clawSandboxAgentSkills.delete')] })] })] })] })] }, skill.id));
222926
+ : 'clawSandboxAgentSkills.skillDisabledLabel', { name: skill.name }) }), jsxs(DropdownMenu, { children: [jsx(DropdownMenuTrigger, { asChild: true, children: jsx(Button$1, { variant: "ghost", size: "sm", "aria-label": t('clawSandboxAgentSkills.skillActions', {
222927
+ name: skill.name,
222928
+ }), children: jsx(Ellipsis, { className: "h-4 w-4" }) }) }), jsxs(DropdownMenuContent, { align: "end", children: [jsxs(DropdownMenuItem, { className: "cursor-pointer", onClick: () => openEditSkillDialog(skill), children: [jsx(Pen, { className: "mr-2 h-4 w-4" }), t('clawSandboxAgentSkills.edit')] }), jsxs(DropdownMenuItem, { variant: "destructive", className: "cursor-pointer", onClick: () => setDeletingSkill(skill), children: [jsx(Trash2, { className: "mr-2 h-4 w-4" }), t('clawSandboxAgentSkills.delete')] })] })] })] })] }, skill.id));
222652
222929
  }) })), jsxs(OverlayModal, { open: showNewDialog, onClose: closeAllDialogs, title: t('clawSandboxAgentSkills.newSkillDialogTitle'), className: "max-w-2xl", children: [jsx(SkillForm, { form: form, onChange: setForm }), jsxs("div", { className: "flex justify-end gap-2 pt-2", children: [jsx(Button$1, { variant: "outline", onClick: closeAllDialogs, children: t('clawSandboxAgentSkills.cancel') }), jsx(Button$1, { onClick: handleCreateSkill, disabled: isCreatingSkill || !form.name || !form.slug, className: "bg-gradient-to-r from-[#2563EB] to-[#93C5FD] text-white hover:opacity-90", children: isCreatingSkill
222653
222930
  ? t('clawSandboxAgentSkills.creating')
222654
222931
  : t('clawSandboxAgentSkills.create') })] })] }), jsxs(OverlayModal, { open: !!editingSkill, onClose: closeAllDialogs, title: t('clawSandboxAgentSkills.editSkillDialogTitle'), className: "max-w-2xl", children: [jsx(SkillForm, { form: form, onChange: setForm }), jsxs("div", { className: "flex justify-end gap-2 pt-2", children: [jsx(Button$1, { variant: "outline", onClick: closeAllDialogs, children: t('clawSandboxAgentSkills.cancel') }), jsx(Button$1, { onClick: handleUpdateSkill, disabled: isUpdatingSkill || !form.name || !form.slug, className: "bg-gradient-to-r from-[#2563EB] to-[#93C5FD] text-white hover:opacity-90", children: isUpdatingSkill
@@ -222737,11 +223014,44 @@ function formatInterval(interval) {
222737
223014
  return '';
222738
223015
  return `/${interval}`;
222739
223016
  }
223017
+ // Avoids the SSR warning while still measuring/aligning before the browser paints.
223018
+ const useIsomorphicLayoutEffect = typeof window !== 'undefined' ? useLayoutEffect : useEffect;
222740
223019
  function PaywallModal({ pricing, platformKey, itemId, itemType, open, onClose, closable = true, buttonClassName, }) {
222741
223020
  const t = useT();
222742
223021
  const [createCheckout, { isLoading: isCheckoutLoading }] = useCreateCheckoutMutation();
222743
223022
  const [selectedPriceId, setSelectedPriceId] = useState(null);
222744
223023
  const activePrices = pricing.prices;
223024
+ // Keep the title/description block the same height on every card (the tallest
223025
+ // one's height) so the price + Pay button below always line up, regardless of
223026
+ // how long each plan's title or description is.
223027
+ const gridRef = useRef(null);
223028
+ const headerRefs = useRef([]);
223029
+ headerRefs.current.length = activePrices.length;
223030
+ const equalizeHeaderHeights = useCallback(() => {
223031
+ const headers = headerRefs.current.filter((el) => el != null && el.isConnected);
223032
+ // Reset first so we measure each header's natural height, not a stale value.
223033
+ headers.forEach((el) => {
223034
+ el.style.minHeight = '';
223035
+ });
223036
+ if (headers.length <= 1)
223037
+ return;
223038
+ const maxHeight = headers.reduce((max, el) => Math.max(max, el.offsetHeight), 0);
223039
+ headers.forEach((el) => {
223040
+ el.style.minHeight = `${maxHeight}px`;
223041
+ });
223042
+ }, []);
223043
+ useIsomorphicLayoutEffect(() => {
223044
+ if (!open)
223045
+ return;
223046
+ equalizeHeaderHeights();
223047
+ const grid = gridRef.current;
223048
+ if (!grid || typeof ResizeObserver === 'undefined')
223049
+ return;
223050
+ // Re-run when the grid resizes (viewport changes wrap the descriptions).
223051
+ const observer = new ResizeObserver(() => equalizeHeaderHeights());
223052
+ observer.observe(grid);
223053
+ return () => observer.disconnect();
223054
+ }, [open, activePrices, equalizeHeaderHeights]);
222745
223055
  const handleCheckout = async (price) => {
222746
223056
  setSelectedPriceId(price.id);
222747
223057
  try {
@@ -222761,16 +223071,35 @@ function PaywallModal({ pricing, platformKey, itemId, itemType, open, onClose, c
222761
223071
  setSelectedPriceId(null);
222762
223072
  }
222763
223073
  };
223074
+ const preventClose = (e) => {
223075
+ if (!closable)
223076
+ e.preventDefault();
223077
+ };
223078
+ // Single pricing tier: render the focused, card-style layout that matches
223079
+ // UpgradePackageModal instead of a lone card floating in the wide grid modal.
223080
+ if (activePrices.length === 1) {
223081
+ const price = activePrices[0];
223082
+ const isThisLoading = isCheckoutLoading && selectedPriceId === price.id;
223083
+ return (jsx(Dialog, { open: open, onOpenChange: (isOpen) => {
223084
+ if (!isOpen && closable)
223085
+ onClose();
223086
+ }, children: jsxs(DialogContent, { className: cn('max-w-md gap-0 p-0 overflow-hidden rounded-[10px] border border-[#e5e5e5] shadow-[0_10px_15px_-3px_rgba(0,0,0,0.1),0_4px_6px_-4px_rgba(0,0,0,0.1)]', !closable && '[&>button.absolute]:hidden'), onPointerDownOutside: preventClose, onEscapeKeyDown: preventClose, children: [jsxs("div", { className: "relative flex flex-col items-center px-6 pt-8 pb-6 bg-[linear-gradient(135deg,#f5f8ff_0%,#ffffff_100%)] border-b border-[#e5e7eb]", children: [jsx("div", { className: "flex h-12 w-12 items-center justify-center rounded-full mb-4", style: {
223087
+ background: 'linear-gradient(to right, rgb(56, 161, 229), rgb(114, 132, 255))',
223088
+ boxShadow: '0 4px 12px -2px rgba(56, 161, 229, 0.4)',
223089
+ }, children: jsx(Sparkles, { className: "h-6 w-6 text-white" }) }), jsxs("span", { className: "inline-flex items-baseline gap-1 rounded-full px-3 py-1 text-[13px] font-semibold leading-4 mb-3", style: {
223090
+ backgroundColor: '#f5f8ff',
223091
+ color: '#155dfc',
223092
+ border: '1px solid #d0e0ff',
223093
+ }, children: [formatPrice(price.amount, price.currency), price.interval !== 'one_time' && (jsx("span", { className: "text-[11px] font-normal opacity-80", children: formatInterval(price.interval) }))] }), jsxs(DialogHeader, { className: "text-center sm:text-center space-y-2", children: [jsx(DialogTitle, { className: "text-[18px] font-medium leading-7 text-[#101828] tracking-tight", children: price.name || t('modalsPaywallModal.chooseYourPlan') }), jsx(DialogDescription, { className: "text-[14px] font-normal leading-[22.75px] text-[#4a5565] max-w-[320px] mx-auto", children: price.description ||
223094
+ t('modalsPaywallModal.subscribeToGetAccess', { itemName: pricing.item_name }) })] })] }), jsxs("div", { className: "px-6 py-5", children: [price.features.length > 0 && (jsx("ul", { className: "space-y-3 mb-6", children: price.features.map((feature, idx) => (jsxs("li", { className: "flex items-start gap-3 text-[14px] leading-5 text-[#364153]", children: [jsx("span", { className: "mt-0.5 flex h-5 w-5 items-center justify-center rounded-full bg-[#f5f8ff] shrink-0", children: jsx(Check, { className: "h-3 w-3 text-[#155dfc]", strokeWidth: 3 }) }), jsx("span", { className: "font-normal", children: feature })] }, idx))) })), jsx(Button$1, { type: "button", onClick: () => handleCheckout(price), disabled: isCheckoutLoading, className: cn('w-full h-9 px-6 py-2 rounded-lg border-0 text-white text-[14px] font-medium leading-5 bg-[linear-gradient(to_right,rgb(56,161,229),rgb(114,132,255))] hover:opacity-90 transition-opacity disabled:opacity-70', buttonClassName), children: isThisLoading ? (jsxs(Fragment$1, { children: [jsx(LoaderCircle, { className: "h-4 w-4 animate-spin" }), jsx("span", { children: t('modalsPaywallModal.redirecting') })] })) : (t('modalsPaywallModal.pay')) }), jsxs("div", { className: "mt-3 flex items-center justify-center gap-1.5 text-[12px] font-normal leading-4 text-[#6a7282]", children: [jsx(CreditCard, { className: "h-3.5 w-3.5", "aria-hidden": "true" }), jsx("span", { children: t('modalsPaywallModal.secureCheckout') })] })] })] }) }));
223095
+ }
222764
223096
  return (jsx(Dialog, { open: open, onOpenChange: (isOpen) => {
222765
223097
  if (!isOpen && closable)
222766
223098
  onClose();
222767
- }, children: jsxs(DialogContent, { className: cn('max-w-5xl gap-0 overflow-y-auto max-h-[90vh] p-8', !closable && '[&>button.absolute]:hidden'), onPointerDownOutside: (e) => {
222768
- if (!closable)
222769
- e.preventDefault();
222770
- }, onEscapeKeyDown: (e) => {
222771
- if (!closable)
222772
- e.preventDefault();
222773
- }, children: [jsxs(DialogHeader, { className: "text-center sm:text-center mb-8", children: [jsx(DialogTitle, { className: "text-3xl font-bold tracking-tight", children: t('modalsPaywallModal.chooseYourPlan') }), jsx(DialogDescription, { className: "text-base text-muted-foreground mt-2", children: t('modalsPaywallModal.subscribeToGetAccess', { itemName: pricing.item_name }) })] }), jsx("div", { className: cn('grid gap-5', activePrices.length === 1 && 'grid-cols-1 max-w-sm mx-auto', activePrices.length === 2 && 'grid-cols-1 sm:grid-cols-2 max-w-2xl mx-auto', activePrices.length === 3 && 'grid-cols-1 sm:grid-cols-2 lg:grid-cols-3', activePrices.length >= 4 && 'grid-cols-1 sm:grid-cols-2 lg:grid-cols-4'), children: activePrices.map((price) => (jsxs("div", { className: "rounded-xl bg-muted/50 p-6 flex flex-col gap-5", children: [jsxs("div", { children: [jsx("h3", { className: "text-xl font-bold", children: price.name }), price.description && (jsx("p", { className: "text-sm text-muted-foreground mt-2 leading-relaxed", children: price.description }))] }), jsxs("div", { className: "flex items-baseline gap-1", children: [jsx("span", { className: "text-4xl font-bold tracking-tight", children: formatPrice(price.amount, price.currency) }), price.interval !== 'one_time' && (jsx("span", { className: "text-sm text-muted-foreground", children: formatInterval(price.interval) }))] }), jsx(Button$1, { onClick: () => handleCheckout(price), disabled: isCheckoutLoading, className: cn('w-full h-11 text-sm font-medium', buttonClassName), children: isCheckoutLoading && selectedPriceId === price.id
223099
+ }, children: jsxs(DialogContent, { className: cn('max-w-5xl gap-0 overflow-y-auto max-h-[90vh] p-8', !closable && '[&>button.absolute]:hidden'), onPointerDownOutside: preventClose, onEscapeKeyDown: preventClose, children: [jsxs(DialogHeader, { className: "text-center sm:text-center mb-8", children: [jsx(DialogTitle, { className: "text-3xl font-bold tracking-tight", children: t('modalsPaywallModal.chooseYourPlan') }), jsx(DialogDescription, { className: "text-base text-muted-foreground mt-2", children: t('modalsPaywallModal.subscribeToGetAccess', { itemName: pricing.item_name }) })] }), jsx("div", { ref: gridRef, className: cn('grid gap-5 items-stretch', activePrices.length === 2 &&
223100
+ 'grid-cols-1 sm:grid-cols-2 sm:auto-cols-fr max-w-2xl mx-auto', activePrices.length === 3 && 'grid-cols-1 sm:grid-cols-2 lg:grid-cols-3', activePrices.length >= 4 && 'grid-cols-1 sm:grid-cols-2 lg:grid-cols-4'), children: activePrices.map((price, index) => (jsxs("div", { className: "rounded-xl bg-muted/50 p-6 flex flex-col gap-5 min-w-[16rem]", children: [jsxs("div", { ref: (el) => {
223101
+ headerRefs.current[index] = el;
223102
+ }, children: [jsx("h3", { className: "text-xl font-bold", children: price.name }), price.description && (jsx("p", { className: "text-sm text-muted-foreground mt-2 leading-relaxed", children: price.description }))] }), jsxs("div", { className: "flex items-baseline gap-1", children: [jsx("span", { className: "text-4xl font-bold tracking-tight", children: formatPrice(price.amount, price.currency) }), price.interval !== 'one_time' && (jsx("span", { className: "text-sm text-muted-foreground", children: formatInterval(price.interval) }))] }), jsx(Button$1, { onClick: () => handleCheckout(price), disabled: isCheckoutLoading, className: cn('w-full h-11 text-sm font-medium', buttonClassName), children: isCheckoutLoading && selectedPriceId === price.id
222774
223103
  ? t('modalsPaywallModal.redirecting')
222775
223104
  : t('modalsPaywallModal.pay') }), price.features.length > 0 && (jsxs("div", { children: [jsx("p", { className: "text-sm font-medium mb-3", children: t('modalsPaywallModal.thisIncludes') }), jsx("ul", { className: "space-y-3", children: price.features.map((feature, idx) => (jsxs("li", { className: "flex items-start gap-2.5 text-sm", children: [jsx(CircleCheckBig, { className: "h-4 w-4 text-primary shrink-0 mt-0.5" }), jsx("span", { className: "leading-snug", children: feature })] }, idx))) })] }))] }, price.id))) })] }) }));
222776
223105
  }