mirror of
https://github.com/lobehub/lobehub
synced 2026-04-21 09:37:28 +00:00
💄 style: Update agent onboarding style (#13678)
* 💄 style: Update onboarding * style: update * 💄 style: Update i18n * fix: test
This commit is contained in:
parent
5f25efd54c
commit
4787bed380
38 changed files with 905 additions and 496 deletions
|
|
@ -1,6 +1,6 @@
|
|||
const { defineConfig } = require('@lobehub/i18n-cli');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const fs = require('node:fs');
|
||||
const path = require('node:path');
|
||||
|
||||
module.exports = defineConfig({
|
||||
entry: 'locales/en-US',
|
||||
|
|
@ -27,14 +27,14 @@ module.exports = defineConfig({
|
|||
],
|
||||
temperature: 0,
|
||||
saveImmediately: true,
|
||||
modelName: 'chatgpt-4o-latest',
|
||||
modelName: 'gpt-5.1-chat-latest',
|
||||
experimental: {
|
||||
jsonMode: true,
|
||||
},
|
||||
markdown: {
|
||||
reference:
|
||||
'You need to maintain the component format of the mdx file; the output text does not need to be wrapped in any code block syntax on the outermost layer.\n' +
|
||||
fs.readFileSync(path.join(__dirname, 'docs/glossary.md'), 'utf-8'),
|
||||
fs.readFileSync(path.join(__dirname, 'docs/glossary.md'), 'utf8'),
|
||||
entry: ['./README.md', './docs/**/*.md', './docs/**/*.mdx'],
|
||||
entryLocale: 'en-US',
|
||||
outputLocales: ['zh-CN'],
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@ export default eslint(
|
|||
// AI coding tools directories
|
||||
'.claude',
|
||||
'.serena',
|
||||
'.i18nrc.js',
|
||||
],
|
||||
next: true,
|
||||
react: 'next',
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
{
|
||||
"agent.banner.label": "تسجيل وكيل",
|
||||
"agent.completionSubtitle": "تم إعداد مساعدك وهو جاهز للعمل.",
|
||||
"agent.completionTitle": "تم الإعداد بالكامل!",
|
||||
"agent.enterApp": "دخول التطبيق",
|
||||
"agent.completion.sentence.readyWhenYouAre": "جاهز متى شئت :)",
|
||||
"agent.completion.sentence.readyWithName": "{{name}} هنا - أنا جاهز!",
|
||||
"agent.completionSubtitle": "كل شيء جاهز - لنبدأ عندما تكون مستعدًا.",
|
||||
"agent.completionTitle": "أنت على وشك الانتهاء",
|
||||
"agent.enterApp": "أنا جاهز",
|
||||
"agent.greeting.emojiLabel": "رمز تعبيري",
|
||||
"agent.greeting.nameLabel": "الاسم",
|
||||
"agent.greeting.namePlaceholder": "مثلًا: لومي، أطلس، نيكو...",
|
||||
|
|
@ -11,13 +13,19 @@
|
|||
"agent.greeting.vibePlaceholder": "مثلًا: دافئ وودود، حاد ومباشر...",
|
||||
"agent.history.current": "الحالي",
|
||||
"agent.history.title": "مواضيع السجل",
|
||||
"agent.layout.mode.agent": "وضع الوكيل",
|
||||
"agent.layout.mode.classic": "الوضع الكلاسيكي",
|
||||
"agent.layout.skip": "تخطي هذه الخطوة",
|
||||
"agent.layout.skipConfirm.content": "هل ترغب في المغادرة الآن؟ أستطيع مساعدتك في تخصيص الأمور خلال ثوانٍ.",
|
||||
"agent.layout.skipConfirm.ok": "تخطي الآن",
|
||||
"agent.layout.skipConfirm.title": "تخطي الإعداد الآن؟",
|
||||
"agent.layout.switchMessage": "لست في مزاج لذلك اليوم؟ يمكنك التبديل إلى <modeLink><modeText>{{mode}}</modeText></modeLink> أو <skipLink><skipText>{{skip}}</skipText></skipLink>.",
|
||||
"agent.modeSwitch.agent": "تفاعلي",
|
||||
"agent.modeSwitch.classic": "كلاسيكي",
|
||||
"agent.modeSwitch.debug": "تصدير التصحيح",
|
||||
"agent.modeSwitch.label": "اختر وضع التسجيل",
|
||||
"agent.modeSwitch.reset": "إعادة ضبط التدفق",
|
||||
"agent.progress": "{{currentStep}}/{{totalSteps}}",
|
||||
"agent.skipOnboarding": "تخطي التسجيل",
|
||||
"agent.stage.agentIdentity": "هوية الوكيل",
|
||||
"agent.stage.painPoints": "نقاط الألم",
|
||||
"agent.stage.proSettings": "الإعدادات المتقدمة",
|
||||
|
|
@ -33,6 +41,16 @@
|
|||
"agent.telemetryHint": "يمكنك أيضًا الإجابة بكلماتك الخاصة.",
|
||||
"agent.title": "تسجيل المحادثة",
|
||||
"agent.welcome": "...هم؟ لقد استيقظت للتو — ذهني فارغ. من أنت؟ وأيضًا — ماذا يجب أن يُطلق علي؟ أحتاج إلى اسم أيضًا.",
|
||||
"agent.welcome.footer": "قم بتكوين وكيل Lobe AI الخاص بك. يعمل على خادمك، ويتعلم من كل تفاعل، ويصبح أقوى كلما استمر في العمل.",
|
||||
"agent.welcome.guide.growTogether.desc": "مع كل محادثة، سأفهمك بشكل أفضل وأصبح زميلًا أقوى مع مرور الوقت.",
|
||||
"agent.welcome.guide.growTogether.title": "النمو معك",
|
||||
"agent.welcome.guide.knowYou.desc": "ما الذي يشغل بالك هذه الأيام؟ القليل من السياق يساعدني في دعمك بشكل أفضل.",
|
||||
"agent.welcome.guide.knowYou.title": "التعرف عليك",
|
||||
"agent.welcome.guide.name.desc": "امنحني اسمًا ليكون الأمر أكثر شخصية منذ البداية.",
|
||||
"agent.welcome.guide.name.title": "امنحني اسمًا",
|
||||
"agent.welcome.sentence.1": "سررت بلقائك! دعنا نتعرّف على بعض.",
|
||||
"agent.welcome.sentence.2": "ما نوع الشريك الذي تريدني أن أكونه؟",
|
||||
"agent.welcome.sentence.3": "أولًا، اختر لي اسمًا :)",
|
||||
"back": "رجوع",
|
||||
"finish": "ابدأ الآن",
|
||||
"interests.area.business": "الأعمال والاستراتيجية",
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
{
|
||||
"agent.banner.label": "Въвеждане на агент",
|
||||
"agent.completionSubtitle": "Вашият асистент е конфигуриран и готов за работа.",
|
||||
"agent.completionTitle": "Всичко е готово!",
|
||||
"agent.enterApp": "Влезте в приложението",
|
||||
"agent.completion.sentence.readyWhenYouAre": "На разположение съм, когато сте готови :)",
|
||||
"agent.completion.sentence.readyWithName": "{{name}} тук — готов/а!",
|
||||
"agent.completionSubtitle": "Всичко е на място — нека започнем, когато си готов.",
|
||||
"agent.completionTitle": "Почти сте готови",
|
||||
"agent.enterApp": "Готов съм",
|
||||
"agent.greeting.emojiLabel": "Емоджи",
|
||||
"agent.greeting.nameLabel": "Име",
|
||||
"agent.greeting.namePlaceholder": "напр. Луми, Атлас, Неко...",
|
||||
|
|
@ -11,13 +13,19 @@
|
|||
"agent.greeting.vibePlaceholder": "напр. Топло и приятелско, Остро и директно...",
|
||||
"agent.history.current": "Текущо",
|
||||
"agent.history.title": "История на темите",
|
||||
"agent.layout.mode.agent": "Агентски режим",
|
||||
"agent.layout.mode.classic": "Класически режим",
|
||||
"agent.layout.skip": "Пропуснете тази стъпка",
|
||||
"agent.layout.skipConfirm.content": "Вече ли тръгвате? Мога за секунди да ви помогна да персонализирате нещата.",
|
||||
"agent.layout.skipConfirm.ok": "Пропуснете засега",
|
||||
"agent.layout.skipConfirm.title": "Да пропуснете въвеждането засега?",
|
||||
"agent.layout.switchMessage": "Не сте в настроение днес? Можете да преминете в <modeLink><modeText>{{mode}}</modeText></modeLink> или да <skipLink><skipText>{{skip}}</skipText></skipLink>.",
|
||||
"agent.modeSwitch.agent": "Разговорен",
|
||||
"agent.modeSwitch.classic": "Класически",
|
||||
"agent.modeSwitch.debug": "Експорт за отстраняване на грешки",
|
||||
"agent.modeSwitch.label": "Изберете режим за въвеждане",
|
||||
"agent.modeSwitch.reset": "Нулиране на процеса",
|
||||
"agent.progress": "{{currentStep}}/{{totalSteps}}",
|
||||
"agent.skipOnboarding": "Пропуснете въвеждането",
|
||||
"agent.stage.agentIdentity": "Идентичност на агента",
|
||||
"agent.stage.painPoints": "Трудности",
|
||||
"agent.stage.proSettings": "Разширени настройки",
|
||||
|
|
@ -33,6 +41,16 @@
|
|||
"agent.telemetryHint": "Можете също да отговорите със свои думи.",
|
||||
"agent.title": "Разговорно въвеждане",
|
||||
"agent.welcome": "...хм? Току-що се събудих — умът ми е празен. Кой сте вие? И — какво име да ми дадете? Имам нужда и от име.",
|
||||
"agent.welcome.footer": "Настройте своя Lobe AI агент. Той работи на вашия сървър, учи се от всяко взаимодействие и става по-мощен, колкото по-дълго работи.",
|
||||
"agent.welcome.guide.growTogether.desc": "С всяка беседа ще те опознавам по-добре и с времето ще ставам все по-надежден партньор.",
|
||||
"agent.welcome.guide.growTogether.title": "Растем заедно",
|
||||
"agent.welcome.guide.knowYou.desc": "Какво имаш за вършене напоследък? Малко контекст ще ми помогне да те подкрепя по-добре.",
|
||||
"agent.welcome.guide.knowYou.title": "Да те опозная",
|
||||
"agent.welcome.guide.name.desc": "Дай ми име, за да звучи по-лично от самото начало.",
|
||||
"agent.welcome.guide.name.title": "Дай ми име",
|
||||
"agent.welcome.sentence.1": "Радвам се да се запознаем! Нека се опознаем по-добре.",
|
||||
"agent.welcome.sentence.2": "Какъв тип партньор искаш да бъда?",
|
||||
"agent.welcome.sentence.3": "Първо, дай ми име :)",
|
||||
"back": "Назад",
|
||||
"finish": "Да започнем",
|
||||
"interests.area.business": "Бизнес и стратегия",
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
{
|
||||
"agent.banner.label": "Agent-Einführung",
|
||||
"agent.completionSubtitle": "Ihr Assistent ist konfiguriert und einsatzbereit.",
|
||||
"agent.completionTitle": "Alles erledigt!",
|
||||
"agent.enterApp": "App betreten",
|
||||
"agent.completion.sentence.readyWhenYouAre": "Bereit, wenn du es bist :)",
|
||||
"agent.completion.sentence.readyWithName": "{{name}} hier – ich bin bereit!",
|
||||
"agent.completionSubtitle": "Alles ist vorbereitet – wir können loslegen, sobald du soweit bist.",
|
||||
"agent.completionTitle": "Du bist fast am Ziel",
|
||||
"agent.enterApp": "Ich bin bereit",
|
||||
"agent.greeting.emojiLabel": "Emoji",
|
||||
"agent.greeting.nameLabel": "Name",
|
||||
"agent.greeting.namePlaceholder": "z. B. Lumi, Atlas, Neko...",
|
||||
|
|
@ -11,13 +13,19 @@
|
|||
"agent.greeting.vibePlaceholder": "z. B. Warm & freundlich, Scharf & direkt...",
|
||||
"agent.history.current": "Aktuell",
|
||||
"agent.history.title": "Verlaufsthemen",
|
||||
"agent.layout.mode.agent": "Agentenmodus",
|
||||
"agent.layout.mode.classic": "Klassischer Modus",
|
||||
"agent.layout.skip": "Diesen Schritt überspringen",
|
||||
"agent.layout.skipConfirm.content": "Gehst du schon? Ich könnte dir in wenigen Sekunden helfen, alles zu personalisieren.",
|
||||
"agent.layout.skipConfirm.ok": "Für jetzt überspringen",
|
||||
"agent.layout.skipConfirm.title": "Onboarding jetzt überspringen?",
|
||||
"agent.layout.switchMessage": "Heute nicht so in Stimmung? Du kannst zum <modeLink><modeText>{{mode}}</modeText></modeLink> wechseln oder <skipLink><skipText>{{skip}}</skipText></skipLink>.",
|
||||
"agent.modeSwitch.agent": "Konversation",
|
||||
"agent.modeSwitch.classic": "Klassisch",
|
||||
"agent.modeSwitch.debug": "Debug-Export",
|
||||
"agent.modeSwitch.label": "Wählen Sie Ihren Einführungsmodus",
|
||||
"agent.modeSwitch.reset": "Flow zurücksetzen",
|
||||
"agent.progress": "{{currentStep}}/{{totalSteps}}",
|
||||
"agent.skipOnboarding": "Einführung überspringen",
|
||||
"agent.stage.agentIdentity": "Agentenidentität",
|
||||
"agent.stage.painPoints": "Schmerzpunkte",
|
||||
"agent.stage.proSettings": "Erweiterte Einstellungen",
|
||||
|
|
@ -33,6 +41,16 @@
|
|||
"agent.telemetryHint": "Sie können auch in Ihren eigenen Worten antworten.",
|
||||
"agent.title": "Konversations-Einführung",
|
||||
"agent.welcome": "...hm? Ich bin gerade aufgewacht – mein Kopf ist leer. Wer sind Sie? Und – wie soll ich heißen? Ich brauche auch einen Namen.",
|
||||
"agent.welcome.footer": "Konfiguriere deinen Lobe AI Agent. Er läuft auf deinem Server, lernt aus jeder Interaktion und wird mit der Zeit immer leistungsfähiger.",
|
||||
"agent.welcome.guide.growTogether.desc": "Mit jedem Gespräch verstehe ich dich besser und werde nach und nach ein stärkerer Teamplayer.",
|
||||
"agent.welcome.guide.growTogether.title": "Gemeinsam wachsen",
|
||||
"agent.welcome.guide.knowYou.desc": "Woran arbeitest du zurzeit? Ein wenig Kontext hilft mir, dich besser zu unterstützen.",
|
||||
"agent.welcome.guide.knowYou.title": "Dich kennenlernen",
|
||||
"agent.welcome.guide.name.desc": "Gib mir einen Namen, damit sich alles von Anfang an persönlicher anfühlt.",
|
||||
"agent.welcome.guide.name.title": "Gib mir einen Namen",
|
||||
"agent.welcome.sentence.1": "Sehr schön, dich kennenzulernen! Lass uns einander besser kennenlernen.",
|
||||
"agent.welcome.sentence.2": "Welche Art von Partner soll ich für dich sein?",
|
||||
"agent.welcome.sentence.3": "Gib mir zuerst einen Namen :)",
|
||||
"back": "Zurück",
|
||||
"finish": "Los geht’s",
|
||||
"interests.area.business": "Geschäft & Strategie",
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
{
|
||||
"agent.banner.label": "Agent Onboarding",
|
||||
"agent.completionSubtitle": "Your assistant is configured and ready to go.",
|
||||
"agent.completionTitle": "You're All Set!",
|
||||
"agent.enterApp": "Enter App",
|
||||
"agent.completion.sentence.readyWhenYouAre": "Ready when you are :)",
|
||||
"agent.completion.sentence.readyWithName": "{{name}} here - I'm ready!",
|
||||
"agent.completionSubtitle": "Everything's in place - let's get started when you're ready.",
|
||||
"agent.completionTitle": "You are almost there",
|
||||
"agent.enterApp": "I'm ready",
|
||||
"agent.greeting.emojiLabel": "Emoji",
|
||||
"agent.greeting.nameLabel": "Name",
|
||||
"agent.greeting.namePlaceholder": "e.g. Lumi, Atlas, Neko...",
|
||||
|
|
@ -11,13 +13,19 @@
|
|||
"agent.greeting.vibePlaceholder": "e.g. Warm & friendly, Sharp & direct...",
|
||||
"agent.history.current": "Current",
|
||||
"agent.history.title": "History Topics",
|
||||
"agent.layout.mode.agent": "agent mode",
|
||||
"agent.layout.mode.classic": "classic mode",
|
||||
"agent.layout.skip": "skip this step",
|
||||
"agent.layout.skipConfirm.content": "Leaving already? I could help personalize things for you in seconds.",
|
||||
"agent.layout.skipConfirm.ok": "Skip for now",
|
||||
"agent.layout.skipConfirm.title": "Skip onboarding for now?",
|
||||
"agent.layout.switchMessage": "Not feeling it today? You can switch to <modeLink><modeText>{{mode}}</modeText></modeLink> or <skipLink><skipText>{{skip}}</skipText></skipLink>.",
|
||||
"agent.modeSwitch.agent": "Conversational",
|
||||
"agent.modeSwitch.classic": "Classic",
|
||||
"agent.modeSwitch.debug": "Debug Export",
|
||||
"agent.modeSwitch.label": "Choose your onboarding mode",
|
||||
"agent.modeSwitch.reset": "Reset Flow",
|
||||
"agent.progress": "{{currentStep}}/{{totalSteps}}",
|
||||
"agent.skipOnboarding": "Skip onboarding",
|
||||
"agent.stage.agentIdentity": "Agent Identity",
|
||||
"agent.stage.painPoints": "Pain Points",
|
||||
"agent.stage.proSettings": "Advanced Setup",
|
||||
|
|
@ -33,6 +41,16 @@
|
|||
"agent.telemetryHint": "You can also answer in your own words.",
|
||||
"agent.title": "Conversation Onboarding",
|
||||
"agent.welcome": "...hm? I just woke up — my mind's a blank. Who are you? And — what should I be called? I need a name too.",
|
||||
"agent.welcome.footer": "Configure your Lobe AI Agent. It lives on your server, learns from every interaction, and becomes more powerful the longer it runs.",
|
||||
"agent.welcome.guide.growTogether.desc": "With each chat, I'll understand you better and become a stronger teammate over time.",
|
||||
"agent.welcome.guide.growTogether.title": "Grow with You",
|
||||
"agent.welcome.guide.knowYou.desc": "What's on your plate these days? A little context helps me support you better.",
|
||||
"agent.welcome.guide.knowYou.title": "Get to Know You",
|
||||
"agent.welcome.guide.name.desc": "Give me a name so this feels more personal from the start.",
|
||||
"agent.welcome.guide.name.title": "Name Me",
|
||||
"agent.welcome.sentence.1": "So nice to meet you! Let’s get to know each other.",
|
||||
"agent.welcome.sentence.2": "What kind of partner do you want me to be?",
|
||||
"agent.welcome.sentence.3": "First, give me a name :)",
|
||||
"back": "Back",
|
||||
"finish": "Get Started",
|
||||
"interests.area.business": "Business & Strategy",
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
{
|
||||
"agent.banner.label": "Incorporación del Agente",
|
||||
"agent.completionSubtitle": "Tu asistente está configurado y listo para comenzar.",
|
||||
"agent.completionTitle": "¡Todo Listo!",
|
||||
"agent.enterApp": "Entrar a la Aplicación",
|
||||
"agent.completion.sentence.readyWhenYouAre": "Cuando tú digas :)",
|
||||
"agent.completion.sentence.readyWithName": "Aquí {{name}} — ¡listo cuando tú quieras!",
|
||||
"agent.completionSubtitle": "Todo está listo. Empecemos cuando te venga bien.",
|
||||
"agent.completionTitle": "Ya casi lo tienes",
|
||||
"agent.enterApp": "Estoy listo",
|
||||
"agent.greeting.emojiLabel": "Emoji",
|
||||
"agent.greeting.nameLabel": "Nombre",
|
||||
"agent.greeting.namePlaceholder": "p. ej. Lumi, Atlas, Neko...",
|
||||
|
|
@ -11,13 +13,19 @@
|
|||
"agent.greeting.vibePlaceholder": "p. ej. Cálido y amigable, Directo y preciso...",
|
||||
"agent.history.current": "Actual",
|
||||
"agent.history.title": "Temas del Historial",
|
||||
"agent.layout.mode.agent": "modo agente",
|
||||
"agent.layout.mode.classic": "modo clásico",
|
||||
"agent.layout.skip": "omitir este paso",
|
||||
"agent.layout.skipConfirm.content": "¿Ya te vas? Puedo ayudarte a personalizar todo en solo unos segundos.",
|
||||
"agent.layout.skipConfirm.ok": "Omitir por ahora",
|
||||
"agent.layout.skipConfirm.title": "¿Omitir la configuración inicial por ahora?",
|
||||
"agent.layout.switchMessage": "¿No te convence hoy? Puedes cambiar a <modeLink><modeText>{{mode}}</modeText></modeLink> o <skipLink><skipText>{{skip}}</skipText></skipLink>.",
|
||||
"agent.modeSwitch.agent": "Conversacional",
|
||||
"agent.modeSwitch.classic": "Clásico",
|
||||
"agent.modeSwitch.debug": "Exportar Depuración",
|
||||
"agent.modeSwitch.label": "Elige tu modo de incorporación",
|
||||
"agent.modeSwitch.reset": "Reiniciar Flujo",
|
||||
"agent.progress": "{{currentStep}}/{{totalSteps}}",
|
||||
"agent.skipOnboarding": "Omitir incorporación",
|
||||
"agent.stage.agentIdentity": "Identidad del Agente",
|
||||
"agent.stage.painPoints": "Puntos Problemáticos",
|
||||
"agent.stage.proSettings": "Configuración Avanzada",
|
||||
|
|
@ -33,6 +41,16 @@
|
|||
"agent.telemetryHint": "También puedes responder con tus propias palabras.",
|
||||
"agent.title": "Incorporación Conversacional",
|
||||
"agent.welcome": "...¿hm? Acabo de despertar — mi mente está en blanco. ¿Quién eres? Y — ¿cómo debería llamarme? También necesito un nombre.",
|
||||
"agent.welcome.footer": "Configura tu Lobe AI Agent. Vive en tu servidor, aprende de cada interacción y se vuelve más potente cuanto más tiempo funciona.",
|
||||
"agent.welcome.guide.growTogether.desc": "Con cada conversación, te comprenderé mejor y me convertiré en un compañero más sólido con el tiempo.",
|
||||
"agent.welcome.guide.growTogether.title": "Crecer contigo",
|
||||
"agent.welcome.guide.knowYou.desc": "¿Qué tienes entre manos estos días? Un poco de contexto me ayuda a apoyarte mejor.",
|
||||
"agent.welcome.guide.knowYou.title": "Conocerte",
|
||||
"agent.welcome.guide.name.desc": "Dame un nombre para que todo se sienta más personal desde el principio.",
|
||||
"agent.welcome.guide.name.title": "Ponme un nombre",
|
||||
"agent.welcome.sentence.1": "¡Qué gusto conocerte! Vamos a conocernos mejor.",
|
||||
"agent.welcome.sentence.2": "¿Qué tipo de compañero quieres que sea?",
|
||||
"agent.welcome.sentence.3": "Primero, dame un nombre :)",
|
||||
"back": "Volver",
|
||||
"finish": "Comenzar",
|
||||
"interests.area.business": "Negocios y Estrategia",
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
{
|
||||
"agent.banner.label": "آموزش نماینده",
|
||||
"agent.completionSubtitle": "دستیار شما تنظیم شده و آماده استفاده است.",
|
||||
"agent.completionTitle": "همه چیز آماده است!",
|
||||
"agent.enterApp": "ورود به برنامه",
|
||||
"agent.completion.sentence.readyWhenYouAre": "هر وقت آماده بودی :)",
|
||||
"agent.completion.sentence.readyWithName": "{{name}} اینجاست - من آمادهام!",
|
||||
"agent.completionSubtitle": "همهچیز مهیاست - هر وقت آماده بودی شروع میکنیم.",
|
||||
"agent.completionTitle": "تقریباً تمام شد",
|
||||
"agent.enterApp": "آمادهام",
|
||||
"agent.greeting.emojiLabel": "ایموجی",
|
||||
"agent.greeting.nameLabel": "نام",
|
||||
"agent.greeting.namePlaceholder": "مثلاً لومی، اطلس، نکو...",
|
||||
|
|
@ -11,13 +13,19 @@
|
|||
"agent.greeting.vibePlaceholder": "مثلاً گرم و دوستانه، تیز و مستقیم...",
|
||||
"agent.history.current": "فعلی",
|
||||
"agent.history.title": "موضوعات تاریخچه",
|
||||
"agent.layout.mode.agent": "حالت ایجنت",
|
||||
"agent.layout.mode.classic": "حالت کلاسیک",
|
||||
"agent.layout.skip": "رد کردن این مرحله",
|
||||
"agent.layout.skipConfirm.content": "میخوای همین حالا بری؟ میتونم در چند ثانیه همهچیز رو برات شخصیسازی کنم.",
|
||||
"agent.layout.skipConfirm.ok": "فعلاً رد کن",
|
||||
"agent.layout.skipConfirm.title": "فعلاً از راهاندازی اولیه رد میشی؟",
|
||||
"agent.layout.switchMessage": "امروز حال و هواشو نداری؟ میتونی به <modeLink><modeText>{{mode}}</modeText></modeLink> یا <skipLink><skipText>{{skip}}</skipText></skipLink> تغییر بدی.",
|
||||
"agent.modeSwitch.agent": "مکالمهای",
|
||||
"agent.modeSwitch.classic": "کلاسیک",
|
||||
"agent.modeSwitch.debug": "صادرات اشکالزدایی",
|
||||
"agent.modeSwitch.label": "حالت آموزش خود را انتخاب کنید",
|
||||
"agent.modeSwitch.reset": "بازنشانی جریان",
|
||||
"agent.progress": "{{currentStep}}/{{totalSteps}}",
|
||||
"agent.skipOnboarding": "رد کردن آموزش",
|
||||
"agent.stage.agentIdentity": "هویت نماینده",
|
||||
"agent.stage.painPoints": "نقاط ضعف",
|
||||
"agent.stage.proSettings": "تنظیمات پیشرفته",
|
||||
|
|
@ -33,6 +41,16 @@
|
|||
"agent.telemetryHint": "همچنین میتوانید با کلمات خود پاسخ دهید.",
|
||||
"agent.title": "آموزش مکالمه",
|
||||
"agent.welcome": "...هم؟ تازه بیدار شدم — ذهنم خالیه. شما کی هستید؟ و — چه نامی باید داشته باشم؟ من هم به یک نام نیاز دارم.",
|
||||
"agent.welcome.footer": "ایجنت Lobe AI خودت را تنظیم کن. روی سرور تو اجرا میشود، از هر تعامل یاد میگیرد و هرچه بیشتر کار کند قدرتمندتر میشود.",
|
||||
"agent.welcome.guide.growTogether.desc": "با هر گفتگو، بهتر میفهممت و کمکم همراه قویتری برایت میشوم.",
|
||||
"agent.welcome.guide.growTogether.title": "با تو رشد میکنم",
|
||||
"agent.welcome.guide.knowYou.desc": "این روزها درگیر چه کارهایی هستی؟ کمی زمینه کمکم میکند بهتر همراهت باشم.",
|
||||
"agent.welcome.guide.knowYou.title": "آشنایی با تو",
|
||||
"agent.welcome.guide.name.desc": "برای اینکه از همان اول حس صمیمیتری داشته باشیم، یک اسم برای من انتخاب کن.",
|
||||
"agent.welcome.guide.name.title": "اسم من را انتخاب کن",
|
||||
"agent.welcome.sentence.1": "از آشنایی با تو خوشحالم! بیاییم همدیگر را بهتر بشناسیم.",
|
||||
"agent.welcome.sentence.2": "میخواهی چه نوع همراهی برایت باشم؟",
|
||||
"agent.welcome.sentence.3": "اول از همه، یک اسم برای من بگذار :)",
|
||||
"back": "بازگشت",
|
||||
"finish": "شروع کن",
|
||||
"interests.area.business": "کسبوکار و استراتژی",
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
{
|
||||
"agent.banner.label": "Intégration de l'agent",
|
||||
"agent.completionSubtitle": "Votre assistant est configuré et prêt à l'emploi.",
|
||||
"agent.completionTitle": "Tout est prêt !",
|
||||
"agent.enterApp": "Entrer dans l'application",
|
||||
"agent.completion.sentence.readyWhenYouAre": "Prêt quand vous l'êtes :)",
|
||||
"agent.completion.sentence.readyWithName": "{{name}} ici — je suis prêt !",
|
||||
"agent.completionSubtitle": "Tout est en place — commençons quand vous le souhaitez.",
|
||||
"agent.completionTitle": "Vous y êtes presque",
|
||||
"agent.enterApp": "Je suis prêt",
|
||||
"agent.greeting.emojiLabel": "Émoji",
|
||||
"agent.greeting.nameLabel": "Nom",
|
||||
"agent.greeting.namePlaceholder": "par ex. Lumi, Atlas, Neko...",
|
||||
|
|
@ -11,13 +13,19 @@
|
|||
"agent.greeting.vibePlaceholder": "par ex. Chaleureux et amical, Franc et direct...",
|
||||
"agent.history.current": "Actuel",
|
||||
"agent.history.title": "Sujets historiques",
|
||||
"agent.layout.mode.agent": "mode agent",
|
||||
"agent.layout.mode.classic": "mode classique",
|
||||
"agent.layout.skip": "passer cette étape",
|
||||
"agent.layout.skipConfirm.content": "Vous partez déjà ? Je peux personnaliser les choses pour vous en quelques secondes.",
|
||||
"agent.layout.skipConfirm.ok": "Passer pour le moment",
|
||||
"agent.layout.skipConfirm.title": "Passer l'initialisation pour l'instant ?",
|
||||
"agent.layout.switchMessage": "Pas d'humeur aujourd'hui ? Vous pouvez passer en <modeLink><modeText>{{mode}}</modeText></modeLink> ou <skipLink><skipText>{{skip}}</skipText></skipLink>.",
|
||||
"agent.modeSwitch.agent": "Conversationnel",
|
||||
"agent.modeSwitch.classic": "Classique",
|
||||
"agent.modeSwitch.debug": "Exportation de débogage",
|
||||
"agent.modeSwitch.label": "Choisissez votre mode d'intégration",
|
||||
"agent.modeSwitch.reset": "Réinitialiser le processus",
|
||||
"agent.progress": "{{currentStep}}/{{totalSteps}}",
|
||||
"agent.skipOnboarding": "Passer l'intégration",
|
||||
"agent.stage.agentIdentity": "Identité de l'agent",
|
||||
"agent.stage.painPoints": "Points sensibles",
|
||||
"agent.stage.proSettings": "Configuration avancée",
|
||||
|
|
@ -33,6 +41,16 @@
|
|||
"agent.telemetryHint": "Vous pouvez également répondre avec vos propres mots.",
|
||||
"agent.title": "Intégration par conversation",
|
||||
"agent.welcome": "...hm ? Je viens de me réveiller — mon esprit est vide. Qui êtes-vous ? Et — comment devrais-je m'appeler ? J'ai besoin d'un nom aussi.",
|
||||
"agent.welcome.footer": "Configurez votre agent Lobe AI. Il fonctionne sur votre serveur, apprend à chaque interaction et devient plus performant au fil du temps.",
|
||||
"agent.welcome.guide.growTogether.desc": "À chaque discussion, je vous comprendrai mieux et, avec le temps, je deviendrai un coéquipier plus efficace.",
|
||||
"agent.welcome.guide.growTogether.title": "Évoluer avec vous",
|
||||
"agent.welcome.guide.knowYou.desc": "Qu'avez-vous au programme ces temps-ci ? Un peu de contexte m'aidera à mieux vous assister.",
|
||||
"agent.welcome.guide.knowYou.title": "Mieux vous connaître",
|
||||
"agent.welcome.guide.name.desc": "Donnez-moi un nom pour que cela paraisse plus personnalisé dès le départ.",
|
||||
"agent.welcome.guide.name.title": "Donnez-moi un nom",
|
||||
"agent.welcome.sentence.1": "Ravi de vous rencontrer ! Faisons connaissance.",
|
||||
"agent.welcome.sentence.2": "Quel type de partenaire voulez-vous que je sois ?",
|
||||
"agent.welcome.sentence.3": "D'abord, donnez-moi un nom :)",
|
||||
"back": "Retour",
|
||||
"finish": "Commencer",
|
||||
"interests.area.business": "Affaires & Stratégie",
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
{
|
||||
"agent.banner.label": "Introduzione Agente",
|
||||
"agent.completionSubtitle": "Il tuo assistente è configurato e pronto all'uso.",
|
||||
"agent.completionTitle": "Tutto Pronto!",
|
||||
"agent.enterApp": "Accedi all'App",
|
||||
"agent.completion.sentence.readyWhenYouAre": "Quando sei pronto :)",
|
||||
"agent.completion.sentence.readyWithName": "{{name}} qui - sono pronto!",
|
||||
"agent.completionSubtitle": "È tutto pronto: iniziamo quando vuoi.",
|
||||
"agent.completionTitle": "Ci sei quasi",
|
||||
"agent.enterApp": "Sono pronto",
|
||||
"agent.greeting.emojiLabel": "Emoji",
|
||||
"agent.greeting.nameLabel": "Nome",
|
||||
"agent.greeting.namePlaceholder": "es. Lumi, Atlas, Neko...",
|
||||
|
|
@ -11,13 +13,19 @@
|
|||
"agent.greeting.vibePlaceholder": "es. Caldo e amichevole, Tagliente e diretto...",
|
||||
"agent.history.current": "Corrente",
|
||||
"agent.history.title": "Argomenti della Cronologia",
|
||||
"agent.layout.mode.agent": "modalità agente",
|
||||
"agent.layout.mode.classic": "modalità classica",
|
||||
"agent.layout.skip": "salta questo passaggio",
|
||||
"agent.layout.skipConfirm.content": "Vai già via? Posso aiutarti a personalizzare tutto in pochi secondi.",
|
||||
"agent.layout.skipConfirm.ok": "Salta per ora",
|
||||
"agent.layout.skipConfirm.title": "Saltare l’onboarding per ora?",
|
||||
"agent.layout.switchMessage": "Non è giornata? Puoi passare a <modeLink><modeText>{{mode}}</modeText></modeLink> oppure a <skipLink><skipText>{{skip}}</skipText></skipLink>.",
|
||||
"agent.modeSwitch.agent": "Conversazionale",
|
||||
"agent.modeSwitch.classic": "Classico",
|
||||
"agent.modeSwitch.debug": "Esportazione Debug",
|
||||
"agent.modeSwitch.label": "Scegli la modalità di introduzione",
|
||||
"agent.modeSwitch.reset": "Reimposta Flusso",
|
||||
"agent.progress": "{{currentStep}}/{{totalSteps}}",
|
||||
"agent.skipOnboarding": "Salta introduzione",
|
||||
"agent.stage.agentIdentity": "Identità dell'Agente",
|
||||
"agent.stage.painPoints": "Punti Critici",
|
||||
"agent.stage.proSettings": "Configurazione Avanzata",
|
||||
|
|
@ -33,6 +41,16 @@
|
|||
"agent.telemetryHint": "Puoi anche rispondere con le tue parole.",
|
||||
"agent.title": "Introduzione Conversazionale",
|
||||
"agent.welcome": "...ehm? Mi sono appena svegliato — la mia mente è vuota. Chi sei? E — come dovrei chiamarmi? Ho bisogno di un nome anch'io.",
|
||||
"agent.welcome.footer": "Configura il tuo Lobe AI Agent. Vive sul tuo server, impara da ogni interazione e diventa più potente con il tempo.",
|
||||
"agent.welcome.guide.growTogether.desc": "Con ogni conversazione ti capirò meglio e diventerò un alleato sempre più forte.",
|
||||
"agent.welcome.guide.growTogether.title": "Crescere Insieme",
|
||||
"agent.welcome.guide.knowYou.desc": "Di cosa ti occupi ultimamente? Un po’ di contesto mi aiuta a supportarti meglio.",
|
||||
"agent.welcome.guide.knowYou.title": "Conoscerti",
|
||||
"agent.welcome.guide.name.desc": "Dammi un nome così tutto sembrerà più personale fin dall’inizio.",
|
||||
"agent.welcome.guide.name.title": "Dammi un Nome",
|
||||
"agent.welcome.sentence.1": "Che bello conoscerti! Cominciamo a conoscerci meglio.",
|
||||
"agent.welcome.sentence.2": "Che tipo di partner vuoi che io sia?",
|
||||
"agent.welcome.sentence.3": "Per iniziare, dammi un nome :)",
|
||||
"back": "Indietro",
|
||||
"finish": "Inizia",
|
||||
"interests.area.business": "Business e Strategia",
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
{
|
||||
"agent.banner.label": "エージェントオンボーディング",
|
||||
"agent.completionSubtitle": "アシスタントの設定が完了し、準備が整いました。",
|
||||
"agent.completionTitle": "準備完了!",
|
||||
"agent.enterApp": "アプリに入る",
|
||||
"agent.completion.sentence.readyWhenYouAre": "準備ができたらいつでもどうぞ :)",
|
||||
"agent.completion.sentence.readyWithName": "{{name}}です。準備できています!",
|
||||
"agent.completionSubtitle": "準備は整っています。ご都合の良いときに始めましょう。",
|
||||
"agent.completionTitle": "もう少しで完了です",
|
||||
"agent.enterApp": "準備できました",
|
||||
"agent.greeting.emojiLabel": "絵文字",
|
||||
"agent.greeting.nameLabel": "名前",
|
||||
"agent.greeting.namePlaceholder": "例: ルミ、アトラス、ネコ...",
|
||||
|
|
@ -11,13 +13,19 @@
|
|||
"agent.greeting.vibePlaceholder": "例: 温かくフレンドリー、鋭く直接的...",
|
||||
"agent.history.current": "現在",
|
||||
"agent.history.title": "履歴トピック",
|
||||
"agent.layout.mode.agent": "エージェントモード",
|
||||
"agent.layout.mode.classic": "クラシックモード",
|
||||
"agent.layout.skip": "このステップをスキップ",
|
||||
"agent.layout.skipConfirm.content": "もう離れますか?数秒であなた向けにカスタマイズできますよ。",
|
||||
"agent.layout.skipConfirm.ok": "とりあえずスキップ",
|
||||
"agent.layout.skipConfirm.title": "オンボーディングを今はスキップしますか?",
|
||||
"agent.layout.switchMessage": "今日は気分が乗らないですか?<modeLink><modeText>{{mode}}</modeText></modeLink>か<skipLink><skipText>{{skip}}</skipText></skipLink>に切り替えられます。",
|
||||
"agent.modeSwitch.agent": "会話モード",
|
||||
"agent.modeSwitch.classic": "クラシック",
|
||||
"agent.modeSwitch.debug": "デバッグエクスポート",
|
||||
"agent.modeSwitch.label": "オンボーディングモードを選択",
|
||||
"agent.modeSwitch.reset": "フローをリセット",
|
||||
"agent.progress": "{{currentStep}}/{{totalSteps}}",
|
||||
"agent.skipOnboarding": "オンボーディングをスキップ",
|
||||
"agent.stage.agentIdentity": "エージェントのアイデンティティ",
|
||||
"agent.stage.painPoints": "課題",
|
||||
"agent.stage.proSettings": "高度な設定",
|
||||
|
|
@ -33,6 +41,16 @@
|
|||
"agent.telemetryHint": "独自の言葉で答えることもできます。",
|
||||
"agent.title": "会話型オンボーディング",
|
||||
"agent.welcome": "...ん?今起きたばかりで、頭が真っ白です。あなたは誰ですか?それと、私の名前は何にしますか?",
|
||||
"agent.welcome.footer": "あなたの Lobe AI エージェントを設定してください。エージェントはあなたのサーバー上で稼働し、すべてのやり取りから学習し、稼働時間が長くなるほどより高性能になります。",
|
||||
"agent.welcome.guide.growTogether.desc": "チャットを重ねるごとにあなたのことをより理解し、時間とともに頼れる仲間になります。",
|
||||
"agent.welcome.guide.growTogether.title": "一緒に成長",
|
||||
"agent.welcome.guide.knowYou.desc": "最近何に取り組んでいますか?少し背景を教えていただければ、より適切にサポートできます。",
|
||||
"agent.welcome.guide.knowYou.title": "あなたのことを知る",
|
||||
"agent.welcome.guide.name.desc": "最初からもっと親しみやすくするために、私に名前を付けてください。",
|
||||
"agent.welcome.guide.name.title": "名前をつけて",
|
||||
"agent.welcome.sentence.1": "はじめまして!まずはお互いを知りましょう。",
|
||||
"agent.welcome.sentence.2": "どんなパートナーでいてほしいですか?",
|
||||
"agent.welcome.sentence.3": "まずは私に名前を付けてください :)",
|
||||
"back": "前へ",
|
||||
"finish": "使い始める",
|
||||
"interests.area.business": "ビジネスと戦略",
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
{
|
||||
"agent.banner.label": "에이전트 온보딩",
|
||||
"agent.completionSubtitle": "당신의 어시스턴트가 설정되어 준비되었습니다.",
|
||||
"agent.completionTitle": "모든 준비가 완료되었습니다!",
|
||||
"agent.enterApp": "앱으로 들어가기",
|
||||
"agent.completion.sentence.readyWhenYouAre": "준비되시면 말씀하세요 :)",
|
||||
"agent.completion.sentence.readyWithName": "{{name}}입니다 — 준비됐어요!",
|
||||
"agent.completionSubtitle": "모든 준비가 완료되었습니다 — 준비되시면 시작해요.",
|
||||
"agent.completionTitle": "거의 다 왔어요",
|
||||
"agent.enterApp": "준비됐어요",
|
||||
"agent.greeting.emojiLabel": "이모지",
|
||||
"agent.greeting.nameLabel": "이름",
|
||||
"agent.greeting.namePlaceholder": "예: 루미, 아틀라스, 네코...",
|
||||
|
|
@ -11,13 +13,19 @@
|
|||
"agent.greeting.vibePlaceholder": "예: 따뜻하고 친근한, 날카롭고 직설적인...",
|
||||
"agent.history.current": "현재",
|
||||
"agent.history.title": "히스토리 주제",
|
||||
"agent.layout.mode.agent": "에이전트 모드",
|
||||
"agent.layout.mode.classic": "클래식 모드",
|
||||
"agent.layout.skip": "이 단계 건너뛰기",
|
||||
"agent.layout.skipConfirm.content": "벌써 나가시려나요? 몇 초면 개인화 설정을 도와드릴게요.",
|
||||
"agent.layout.skipConfirm.ok": "일단 건너뛰기",
|
||||
"agent.layout.skipConfirm.title": "지금 온보딩을 건너뛰시겠어요?",
|
||||
"agent.layout.switchMessage": "오늘은 기분이 아니신가요? <modeLink><modeText>{{mode}}</modeText></modeLink>로 전환하거나 <skipLink><skipText>{{skip}}</skipText></skipLink>하실 수 있어요.",
|
||||
"agent.modeSwitch.agent": "대화형",
|
||||
"agent.modeSwitch.classic": "클래식",
|
||||
"agent.modeSwitch.debug": "디버그 내보내기",
|
||||
"agent.modeSwitch.label": "온보딩 모드 선택",
|
||||
"agent.modeSwitch.reset": "흐름 초기화",
|
||||
"agent.progress": "{{currentStep}}/{{totalSteps}}",
|
||||
"agent.skipOnboarding": "온보딩 건너뛰기",
|
||||
"agent.stage.agentIdentity": "에이전트 정체성",
|
||||
"agent.stage.painPoints": "문제점",
|
||||
"agent.stage.proSettings": "고급 설정",
|
||||
|
|
@ -33,6 +41,16 @@
|
|||
"agent.telemetryHint": "자신의 말로 대답할 수도 있습니다.",
|
||||
"agent.title": "대화형 온보딩",
|
||||
"agent.welcome": "...음? 방금 깨어났어요 — 머리가 텅 비었네요. 당신은 누구시죠? 그리고 — 저를 뭐라고 불러야 할까요? 저도 이름이 필요해요.",
|
||||
"agent.welcome.footer": "Lobe AI 에이전트를 구성하세요. 이 에이전트는 서버에 상주하며 모든 상호작용에서 학습하여 실행할수록 더 강력해집니다.",
|
||||
"agent.welcome.guide.growTogether.desc": "대화를 나눌수록 더 잘 이해하게 되어 시간이 지날수록 든든한 동료가 될게요.",
|
||||
"agent.welcome.guide.growTogether.title": "함께 성장하기",
|
||||
"agent.welcome.guide.knowYou.desc": "요즘 어떤 일을 하고 계신가요? 상황을 조금 알려주시면 더 잘 도와드릴 수 있어요.",
|
||||
"agent.welcome.guide.knowYou.title": "당신을 알아가기",
|
||||
"agent.welcome.guide.name.desc": "처음부터 더 친근하게 느낄 수 있도록 이름을 지어주세요.",
|
||||
"agent.welcome.guide.name.title": "이름 지어주기",
|
||||
"agent.welcome.sentence.1": "만나서 반가워요! 서로 알아가볼까요?",
|
||||
"agent.welcome.sentence.2": "어떤 파트너가 되길 원하시나요?",
|
||||
"agent.welcome.sentence.3": "먼저, 이름을 지어주세요 :)",
|
||||
"back": "이전 단계",
|
||||
"finish": "시작하기",
|
||||
"interests.area.business": "비즈니스 및 전략",
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
{
|
||||
"agent.banner.label": "Agent Onboarding",
|
||||
"agent.completionSubtitle": "Je assistent is geconfigureerd en klaar om te starten.",
|
||||
"agent.completionTitle": "Alles is gereed!",
|
||||
"agent.enterApp": "App Betreden",
|
||||
"agent.completion.sentence.readyWhenYouAre": "Zeg het maar wanneer je klaar bent :)",
|
||||
"agent.completion.sentence.readyWithName": "{{name}} hier – ik ben er klaar voor!",
|
||||
"agent.completionSubtitle": "Alles staat klaar — we kunnen beginnen zodra jij zover bent.",
|
||||
"agent.completionTitle": "Je bent er bijna",
|
||||
"agent.enterApp": "Ik ben er klaar voor",
|
||||
"agent.greeting.emojiLabel": "Emoji",
|
||||
"agent.greeting.nameLabel": "Naam",
|
||||
"agent.greeting.namePlaceholder": "bijv. Lumi, Atlas, Neko...",
|
||||
|
|
@ -11,13 +13,19 @@
|
|||
"agent.greeting.vibePlaceholder": "bijv. Warm & vriendelijk, Scherp & direct...",
|
||||
"agent.history.current": "Huidig",
|
||||
"agent.history.title": "Historische Onderwerpen",
|
||||
"agent.layout.mode.agent": "agentmodus",
|
||||
"agent.layout.mode.classic": "klassieke modus",
|
||||
"agent.layout.skip": "deze stap overslaan",
|
||||
"agent.layout.skipConfirm.content": "Ga je nu al weg? Ik kan binnen enkele seconden helpen om alles voor je te personaliseren.",
|
||||
"agent.layout.skipConfirm.ok": "Voor nu overslaan",
|
||||
"agent.layout.skipConfirm.title": "Onboarding nu overslaan?",
|
||||
"agent.layout.switchMessage": "Even geen zin vandaag? Je kunt schakelen naar <modeLink><modeText>{{mode}}</modeText></modeLink> of <skipLink><skipText>{{skip}}</skipText></skipLink>.",
|
||||
"agent.modeSwitch.agent": "Conversatie",
|
||||
"agent.modeSwitch.classic": "Klassiek",
|
||||
"agent.modeSwitch.debug": "Debug Export",
|
||||
"agent.modeSwitch.label": "Kies je onboarding modus",
|
||||
"agent.modeSwitch.reset": "Flow Resetten",
|
||||
"agent.progress": "{{currentStep}}/{{totalSteps}}",
|
||||
"agent.skipOnboarding": "Onboarding overslaan",
|
||||
"agent.stage.agentIdentity": "Agent Identiteit",
|
||||
"agent.stage.painPoints": "Pijnpunten",
|
||||
"agent.stage.proSettings": "Geavanceerde Instellingen",
|
||||
|
|
@ -33,6 +41,16 @@
|
|||
"agent.telemetryHint": "Je kunt ook antwoorden in je eigen woorden.",
|
||||
"agent.title": "Conversatie Onboarding",
|
||||
"agent.welcome": "...hm? Ik ben net wakker — mijn gedachten zijn leeg. Wie ben jij? En — hoe moet ik genoemd worden? Ik heb ook een naam nodig.",
|
||||
"agent.welcome.footer": "Configureer je Lobe AI Agent. Hij draait op je eigen server, leert van elke interactie en wordt krachtiger naarmate hij langer actief is.",
|
||||
"agent.welcome.guide.growTogether.desc": "Met ieder gesprek leer ik je beter kennen en word ik op termijn een sterkere teammate.",
|
||||
"agent.welcome.guide.growTogether.title": "Met je meegroeien",
|
||||
"agent.welcome.guide.knowYou.desc": "Waar ben je de laatste tijd mee bezig? Een beetje context helpt me om je beter te ondersteunen.",
|
||||
"agent.welcome.guide.knowYou.title": "Jou leren kennen",
|
||||
"agent.welcome.guide.name.desc": "Geef me een naam zodat het vanaf het begin persoonlijker voelt.",
|
||||
"agent.welcome.guide.name.title": "Geef me een naam",
|
||||
"agent.welcome.sentence.1": "Leuk om je te ontmoeten! Laten we elkaar beter leren kennen.",
|
||||
"agent.welcome.sentence.2": "Wat voor partner wil je dat ik voor je ben?",
|
||||
"agent.welcome.sentence.3": "Geef me eerst een naam :)",
|
||||
"back": "Terug",
|
||||
"finish": "Aan de slag",
|
||||
"interests.area.business": "Zakelijk & Strategie",
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
{
|
||||
"agent.banner.label": "Wprowadzenie Agenta",
|
||||
"agent.completionSubtitle": "Twój asystent jest skonfigurowany i gotowy do działania.",
|
||||
"agent.completionTitle": "Wszystko gotowe!",
|
||||
"agent.enterApp": "Wejdź do aplikacji",
|
||||
"agent.completion.sentence.readyWhenYouAre": "Jestem gotów, kiedy Ty będziesz :)",
|
||||
"agent.completion.sentence.readyWithName": "{{name}} w gotowości – możemy zaczynać!",
|
||||
"agent.completionSubtitle": "Wszystko przygotowane – zaczniemy, gdy tylko dasz znak.",
|
||||
"agent.completionTitle": "Jesteś już prawie na miejscu",
|
||||
"agent.enterApp": "Jestem gotów",
|
||||
"agent.greeting.emojiLabel": "Emoji",
|
||||
"agent.greeting.nameLabel": "Imię",
|
||||
"agent.greeting.namePlaceholder": "np. Lumi, Atlas, Neko...",
|
||||
|
|
@ -11,13 +13,19 @@
|
|||
"agent.greeting.vibePlaceholder": "np. Ciepły i przyjazny, Ostry i bezpośredni...",
|
||||
"agent.history.current": "Bieżące",
|
||||
"agent.history.title": "Tematy historii",
|
||||
"agent.layout.mode.agent": "tryb agenta",
|
||||
"agent.layout.mode.classic": "tryb klasyczny",
|
||||
"agent.layout.skip": "pomiń ten krok",
|
||||
"agent.layout.skipConfirm.content": "Już wychodzisz? Mogę pomóc spersonalizować wszystko w kilka sekund.",
|
||||
"agent.layout.skipConfirm.ok": "Pomiń na razie",
|
||||
"agent.layout.skipConfirm.title": "Pominąć konfigurację wstępną?",
|
||||
"agent.layout.switchMessage": "Nie masz dziś ochoty? Możesz przełączyć na <modeLink><modeText>{{mode}}</modeText></modeLink> lub <skipLink><skipText>{{skip}}</skipText></skipLink>.",
|
||||
"agent.modeSwitch.agent": "Konwersacyjny",
|
||||
"agent.modeSwitch.classic": "Klasyczny",
|
||||
"agent.modeSwitch.debug": "Eksport debugowania",
|
||||
"agent.modeSwitch.label": "Wybierz tryb wprowadzenia",
|
||||
"agent.modeSwitch.reset": "Zresetuj proces",
|
||||
"agent.progress": "{{currentStep}}/{{totalSteps}}",
|
||||
"agent.skipOnboarding": "Pomiń wprowadzenie",
|
||||
"agent.stage.agentIdentity": "Tożsamość Agenta",
|
||||
"agent.stage.painPoints": "Problemy",
|
||||
"agent.stage.proSettings": "Zaawansowana konfiguracja",
|
||||
|
|
@ -33,6 +41,16 @@
|
|||
"agent.telemetryHint": "Możesz również odpowiedzieć własnymi słowami.",
|
||||
"agent.title": "Wprowadzenie do rozmowy",
|
||||
"agent.welcome": "...hm? Właśnie się obudziłem — moja głowa jest pusta. Kim jesteś? I — jak mam się nazywać? Potrzebuję też imienia.",
|
||||
"agent.welcome.footer": "Skonfiguruj swojego agenta Lobe AI. Działa na Twoim serwerze, uczy się z każdej interakcji i staje się potężniejszy z czasem.",
|
||||
"agent.welcome.guide.growTogether.desc": "Z każdą rozmową będę lepiej Cię rozumieć i z biegiem czasu stanę się jeszcze lepszym wsparciem.",
|
||||
"agent.welcome.guide.growTogether.title": "Rozwijajmy się razem",
|
||||
"agent.welcome.guide.knowYou.desc": "Nad czym ostatnio pracujesz? Trochę kontekstu pomoże mi lepiej Cię wspierać.",
|
||||
"agent.welcome.guide.knowYou.title": "Poznajmy się",
|
||||
"agent.welcome.guide.name.desc": "Nadaj mi imię, aby od początku było bardziej osobiste.",
|
||||
"agent.welcome.guide.name.title": "Nazwij mnie",
|
||||
"agent.welcome.sentence.1": "Miło Cię poznać! Poznajmy się lepiej.",
|
||||
"agent.welcome.sentence.2": "Jakim partnerem mam dla Ciebie być?",
|
||||
"agent.welcome.sentence.3": "Najpierw nadaj mi imię :)",
|
||||
"back": "Wstecz",
|
||||
"finish": "Zaczynamy",
|
||||
"interests.area.business": "Biznes i strategia",
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
{
|
||||
"agent.banner.label": "Integração do Agente",
|
||||
"agent.completionSubtitle": "Seu assistente está configurado e pronto para uso.",
|
||||
"agent.completionTitle": "Tudo Pronto!",
|
||||
"agent.enterApp": "Entrar no Aplicativo",
|
||||
"agent.completion.sentence.readyWhenYouAre": "Pronto quando você estiver :)",
|
||||
"agent.completion.sentence.readyWithName": "{{name}} aqui — pronto para começar!",
|
||||
"agent.completionSubtitle": "Tudo preparado — é só começar quando quiser.",
|
||||
"agent.completionTitle": "Você está quase lá",
|
||||
"agent.enterApp": "Estou pronto",
|
||||
"agent.greeting.emojiLabel": "Emoji",
|
||||
"agent.greeting.nameLabel": "Nome",
|
||||
"agent.greeting.namePlaceholder": "ex.: Lumi, Atlas, Neko...",
|
||||
|
|
@ -11,13 +13,19 @@
|
|||
"agent.greeting.vibePlaceholder": "ex.: Caloroso e amigável, Direto e objetivo...",
|
||||
"agent.history.current": "Atual",
|
||||
"agent.history.title": "Tópicos do Histórico",
|
||||
"agent.layout.mode.agent": "modo agente",
|
||||
"agent.layout.mode.classic": "modo clássico",
|
||||
"agent.layout.skip": "pular esta etapa",
|
||||
"agent.layout.skipConfirm.content": "Indo embora já? Posso ajudar a personalizar tudo para você em poucos segundos.",
|
||||
"agent.layout.skipConfirm.ok": "Pular por enquanto",
|
||||
"agent.layout.skipConfirm.title": "Pular a configuração inicial agora?",
|
||||
"agent.layout.switchMessage": "Não está no clima hoje? Você pode mudar para <modeLink><modeText>{{mode}}</modeText></modeLink> ou <skipLink><skipText>{{skip}}</skipText></skipLink>.",
|
||||
"agent.modeSwitch.agent": "Conversacional",
|
||||
"agent.modeSwitch.classic": "Clássico",
|
||||
"agent.modeSwitch.debug": "Exportar Depuração",
|
||||
"agent.modeSwitch.label": "Escolha seu modo de integração",
|
||||
"agent.modeSwitch.reset": "Reiniciar Fluxo",
|
||||
"agent.progress": "{{currentStep}}/{{totalSteps}}",
|
||||
"agent.skipOnboarding": "Pular integração",
|
||||
"agent.stage.agentIdentity": "Identidade do Agente",
|
||||
"agent.stage.painPoints": "Pontos de Dor",
|
||||
"agent.stage.proSettings": "Configuração Avançada",
|
||||
|
|
@ -33,6 +41,16 @@
|
|||
"agent.telemetryHint": "Você também pode responder com suas próprias palavras.",
|
||||
"agent.title": "Integração por Conversa",
|
||||
"agent.welcome": "...hm? Acabei de acordar — minha mente está vazia. Quem é você? E — como devo ser chamado? Preciso de um nome também.",
|
||||
"agent.welcome.footer": "Configure seu Lobe AI Agent. Ele vive no seu servidor, aprende com cada interação e se torna mais poderoso quanto mais tempo estiver em uso.",
|
||||
"agent.welcome.guide.growTogether.desc": "A cada conversa, vou entender você melhor e me tornar um parceiro mais forte ao longo do tempo.",
|
||||
"agent.welcome.guide.growTogether.title": "Crescer com Você",
|
||||
"agent.welcome.guide.knowYou.desc": "O que anda ocupando seu tempo hoje em dia? Um pouco de contexto me ajuda a apoiar você melhor.",
|
||||
"agent.welcome.guide.knowYou.title": "Conhecer Você",
|
||||
"agent.welcome.guide.name.desc": "Dê-me um nome para deixar tudo mais pessoal desde o começo.",
|
||||
"agent.welcome.guide.name.title": "Dar um Nome",
|
||||
"agent.welcome.sentence.1": "Muito prazer! Vamos nos conhecer melhor.",
|
||||
"agent.welcome.sentence.2": "Que tipo de parceiro você quer que eu seja?",
|
||||
"agent.welcome.sentence.3": "Primeiro, me dê um nome :)",
|
||||
"back": "Voltar",
|
||||
"finish": "Começar",
|
||||
"interests.area.business": "Negócios e Estratégia",
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
{
|
||||
"agent.banner.label": "Настройка агента",
|
||||
"agent.completionSubtitle": "Ваш помощник настроен и готов к работе.",
|
||||
"agent.completionTitle": "Все готово!",
|
||||
"agent.enterApp": "Войти в приложение",
|
||||
"agent.completion.sentence.readyWhenYouAre": "Готов, как только вы будете готовы :)",
|
||||
"agent.completion.sentence.readyWithName": "{{name}} на связи — готов приступить!",
|
||||
"agent.completionSubtitle": "Всё готово — начнём, когда вы будете готовы.",
|
||||
"agent.completionTitle": "Почти всё готово",
|
||||
"agent.enterApp": "Я готов",
|
||||
"agent.greeting.emojiLabel": "Эмодзи",
|
||||
"agent.greeting.nameLabel": "Имя",
|
||||
"agent.greeting.namePlaceholder": "например, Луми, Атлас, Неко...",
|
||||
|
|
@ -11,13 +13,19 @@
|
|||
"agent.greeting.vibePlaceholder": "например, Теплый и дружелюбный, Резкий и прямолинейный...",
|
||||
"agent.history.current": "Текущий",
|
||||
"agent.history.title": "Темы истории",
|
||||
"agent.layout.mode.agent": "режим агента",
|
||||
"agent.layout.mode.classic": "классический режим",
|
||||
"agent.layout.skip": "пропустить этот шаг",
|
||||
"agent.layout.skipConfirm.content": "Уже уходите? Я могу за пару секунд помочь настроить всё под вас.",
|
||||
"agent.layout.skipConfirm.ok": "Пропустить пока",
|
||||
"agent.layout.skipConfirm.title": "Пропустить вводный этап сейчас?",
|
||||
"agent.layout.switchMessage": "Не в настроении сегодня? Можно переключиться на <modeLink><modeText>{{mode}}</modeText></modeLink> или <skipLink><skipText>{{skip}}</skipText></skipLink>.",
|
||||
"agent.modeSwitch.agent": "Разговорный",
|
||||
"agent.modeSwitch.classic": "Классический",
|
||||
"agent.modeSwitch.debug": "Экспорт отладки",
|
||||
"agent.modeSwitch.label": "Выберите режим настройки",
|
||||
"agent.modeSwitch.reset": "Сбросить процесс",
|
||||
"agent.progress": "{{currentStep}}/{{totalSteps}}",
|
||||
"agent.skipOnboarding": "Пропустить настройку",
|
||||
"agent.stage.agentIdentity": "Идентичность агента",
|
||||
"agent.stage.painPoints": "Болевые точки",
|
||||
"agent.stage.proSettings": "Расширенные настройки",
|
||||
|
|
@ -33,6 +41,16 @@
|
|||
"agent.telemetryHint": "Вы также можете ответить своими словами.",
|
||||
"agent.title": "Настройка через беседу",
|
||||
"agent.welcome": "...мм? Я только что проснулся — мой разум пуст. Кто вы? И — как меня назвать? Мне тоже нужно имя.",
|
||||
"agent.welcome.footer": "Настройте агента Lobe AI. Он размещается на вашем сервере, учится на каждом взаимодействии и с течением времени становится всё мощнее.",
|
||||
"agent.welcome.guide.growTogether.desc": "С каждой беседой я буду лучше понимать вас и со временем стану более полезным напарником.",
|
||||
"agent.welcome.guide.growTogether.title": "Расти вместе с вами",
|
||||
"agent.welcome.guide.knowYou.desc": "Что у вас сейчас на повестке? Немного контекста поможет мне лучше вам помочь.",
|
||||
"agent.welcome.guide.knowYou.title": "Познакомиться с вами",
|
||||
"agent.welcome.guide.name.desc": "Дайте мне имя — так всё будет восприниматься более лично с самого начала.",
|
||||
"agent.welcome.guide.name.title": "Назовите меня",
|
||||
"agent.welcome.sentence.1": "Очень приятно познакомиться! Давайте узнаем друг друга поближе.",
|
||||
"agent.welcome.sentence.2": "Каким партнёром вы хотели бы, чтобы я был(а)?",
|
||||
"agent.welcome.sentence.3": "Сначала придумайте мне имя :)",
|
||||
"back": "Назад",
|
||||
"finish": "Начать",
|
||||
"interests.area.business": "Бизнес и стратегия",
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
{
|
||||
"agent.banner.label": "Temsilci Başlatma",
|
||||
"agent.completionSubtitle": "Asistanınız yapılandırıldı ve kullanıma hazır.",
|
||||
"agent.completionTitle": "Her Şey Hazır!",
|
||||
"agent.enterApp": "Uygulamaya Gir",
|
||||
"agent.completion.sentence.readyWhenYouAre": "Hazır olduğunda ben de hazırım :)",
|
||||
"agent.completion.sentence.readyWithName": "{{name}} burada - hazırım!",
|
||||
"agent.completionSubtitle": "Her şey hazır - ne zaman istersen başlayabiliriz.",
|
||||
"agent.completionTitle": "Neredeyse hazırsın",
|
||||
"agent.enterApp": "Hazırım",
|
||||
"agent.greeting.emojiLabel": "Emoji",
|
||||
"agent.greeting.nameLabel": "Ad",
|
||||
"agent.greeting.namePlaceholder": "ör. Lumi, Atlas, Neko...",
|
||||
|
|
@ -11,13 +13,19 @@
|
|||
"agent.greeting.vibePlaceholder": "ör. Sıcak & samimi, Keskin & direkt...",
|
||||
"agent.history.current": "Mevcut",
|
||||
"agent.history.title": "Geçmiş Konular",
|
||||
"agent.layout.mode.agent": "ajan modu",
|
||||
"agent.layout.mode.classic": "klasik mod",
|
||||
"agent.layout.skip": "bu adımı atla",
|
||||
"agent.layout.skipConfirm.content": "Şimdiden gidiyor musun? Saniyeler içinde her şeyi kişiselleştirmene yardımcı olabilirim.",
|
||||
"agent.layout.skipConfirm.ok": "Şimdilik atla",
|
||||
"agent.layout.skipConfirm.title": "Şimdilik başlangıcı atlamak istiyor musun?",
|
||||
"agent.layout.switchMessage": "Bugün modunda değil misin? <modeLink><modeText>{{mode}}</modeText></modeLink> ya da <skipLink><skipText>{{skip}}</skipText></skipLink> seçebilirsin.",
|
||||
"agent.modeSwitch.agent": "Sohbet Odaklı",
|
||||
"agent.modeSwitch.classic": "Klasik",
|
||||
"agent.modeSwitch.debug": "Hata Ayıklama Dışa Aktarımı",
|
||||
"agent.modeSwitch.label": "Başlatma modunuzu seçin",
|
||||
"agent.modeSwitch.reset": "Akışı Sıfırla",
|
||||
"agent.progress": "{{currentStep}}/{{totalSteps}}",
|
||||
"agent.skipOnboarding": "Başlatmayı Atla",
|
||||
"agent.stage.agentIdentity": "Temsilci Kimliği",
|
||||
"agent.stage.painPoints": "Sorun Noktaları",
|
||||
"agent.stage.proSettings": "Gelişmiş Ayarlar",
|
||||
|
|
@ -33,6 +41,16 @@
|
|||
"agent.telemetryHint": "Kendi kelimelerinizle de cevap verebilirsiniz.",
|
||||
"agent.title": "Sohbet Başlatma",
|
||||
"agent.welcome": "...hm? Yeni uyandım — zihnim bomboş. Siz kimsiniz? Ve — bana ne ad vermeliyim? Bir adıma da ihtiyacım var.",
|
||||
"agent.welcome.footer": "Lobe AI Ajanını yapılandır. Sunucunda yaşar, her etkileşimden öğrenir ve çalıştıkça daha güçlü hale gelir.",
|
||||
"agent.welcome.guide.growTogether.desc": "Her sohbetle seni daha iyi anlayacak ve zamanla daha güçlü bir ekip arkadaşı olacağım.",
|
||||
"agent.welcome.guide.growTogether.title": "Seninle Büyür",
|
||||
"agent.welcome.guide.knowYou.desc": "Son zamanlarda nelerle uğraşıyorsun? Biraz bağlam, sana daha iyi destek olmama yardımcı olur.",
|
||||
"agent.welcome.guide.knowYou.title": "Seni Tanımak",
|
||||
"agent.welcome.guide.name.desc": "Bana bir isim ver ki en başından itibaren daha kişisel hissettirsin.",
|
||||
"agent.welcome.guide.name.title": "Bana İsim Ver",
|
||||
"agent.welcome.sentence.1": "Tanıştığımıza çok memnun oldum! Birbirimizi tanıyalım.",
|
||||
"agent.welcome.sentence.2": "Nasıl bir yol arkadaşı olmamı istersin?",
|
||||
"agent.welcome.sentence.3": "Önce, bana bir isim ver :)",
|
||||
"back": "Geri",
|
||||
"finish": "Başlayalım",
|
||||
"interests.area.business": "İş ve Strateji",
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
{
|
||||
"agent.banner.label": "Đăng ký Đại lý",
|
||||
"agent.completionSubtitle": "Trợ lý của bạn đã được cấu hình và sẵn sàng hoạt động.",
|
||||
"agent.completionTitle": "Mọi thứ đã sẵn sàng!",
|
||||
"agent.enterApp": "Vào Ứng dụng",
|
||||
"agent.completion.sentence.readyWhenYouAre": "Sẵn sàng khi bạn sẵn sàng :)",
|
||||
"agent.completion.sentence.readyWithName": "{{name}} đây - Tôi đã sẵn sàng!",
|
||||
"agent.completionSubtitle": "Mọi thứ đã ổn định — hãy bắt đầu khi bạn muốn.",
|
||||
"agent.completionTitle": "Bạn sắp hoàn tất rồi",
|
||||
"agent.enterApp": "Tôi đã sẵn sàng",
|
||||
"agent.greeting.emojiLabel": "Biểu tượng cảm xúc",
|
||||
"agent.greeting.nameLabel": "Tên",
|
||||
"agent.greeting.namePlaceholder": "ví dụ: Lumi, Atlas, Neko...",
|
||||
|
|
@ -11,13 +13,19 @@
|
|||
"agent.greeting.vibePlaceholder": "ví dụ: Ấm áp & thân thiện, Sắc bén & trực tiếp...",
|
||||
"agent.history.current": "Hiện tại",
|
||||
"agent.history.title": "Chủ đề Lịch sử",
|
||||
"agent.layout.mode.agent": "chế độ agent",
|
||||
"agent.layout.mode.classic": "chế độ cổ điển",
|
||||
"agent.layout.skip": "bỏ qua bước này",
|
||||
"agent.layout.skipConfirm.content": "Rời đi rồi sao? Tôi có thể giúp bạn cá nhân hóa mọi thứ chỉ trong vài giây.",
|
||||
"agent.layout.skipConfirm.ok": "Tạm thời bỏ qua",
|
||||
"agent.layout.skipConfirm.title": "Bỏ qua phần giới thiệu chứ?",
|
||||
"agent.layout.switchMessage": "Hôm nay không thoải mái à? Bạn có thể chuyển sang <modeLink><modeText>{{mode}}</modeText></modeLink> hoặc <skipLink><skipText>{{skip}}</skipText></skipLink>.",
|
||||
"agent.modeSwitch.agent": "Hội thoại",
|
||||
"agent.modeSwitch.classic": "Cổ điển",
|
||||
"agent.modeSwitch.debug": "Xuất gỡ lỗi",
|
||||
"agent.modeSwitch.label": "Chọn chế độ đăng ký của bạn",
|
||||
"agent.modeSwitch.reset": "Đặt lại Quy trình",
|
||||
"agent.progress": "{{currentStep}}/{{totalSteps}}",
|
||||
"agent.skipOnboarding": "Bỏ qua đăng ký",
|
||||
"agent.stage.agentIdentity": "Danh tính Đại lý",
|
||||
"agent.stage.painPoints": "Điểm đau",
|
||||
"agent.stage.proSettings": "Cài đặt Nâng cao",
|
||||
|
|
@ -33,6 +41,16 @@
|
|||
"agent.telemetryHint": "Bạn cũng có thể trả lời bằng từ ngữ của riêng mình.",
|
||||
"agent.title": "Đăng ký Hội thoại",
|
||||
"agent.welcome": "...hm? Tôi vừa tỉnh dậy — đầu óc tôi trống rỗng. Bạn là ai? Và — tôi nên được gọi là gì? Tôi cũng cần một cái tên.",
|
||||
"agent.welcome.footer": "Cấu hình Lobe AI Agent của bạn. Nó chạy trên máy chủ của bạn, học từ mọi tương tác và trở nên mạnh mẽ hơn theo thời gian.",
|
||||
"agent.welcome.guide.growTogether.desc": "Mỗi cuộc trò chuyện giúp tôi hiểu bạn hơn và trở thành cộng sự tốt hơn theo thời gian.",
|
||||
"agent.welcome.guide.growTogether.title": "Cùng Phát Triển",
|
||||
"agent.welcome.guide.knowYou.desc": "Dạo này bạn đang bận điều gì? Một chút bối cảnh sẽ giúp tôi hỗ trợ bạn tốt hơn.",
|
||||
"agent.welcome.guide.knowYou.title": "Tìm Hiểu Bạn",
|
||||
"agent.welcome.guide.name.desc": "Hãy đặt cho tôi một cái tên để mọi thứ trở nên gần gũi hơn ngay từ đầu.",
|
||||
"agent.welcome.guide.name.title": "Đặt Tên Cho Tôi",
|
||||
"agent.welcome.sentence.1": "Rất vui được gặp bạn! Hãy cùng làm quen nhé.",
|
||||
"agent.welcome.sentence.2": "Bạn muốn tôi trở thành kiểu cộng sự như thế nào?",
|
||||
"agent.welcome.sentence.3": "Trước tiên, hãy đặt cho tôi một cái tên :)",
|
||||
"back": "Quay lại",
|
||||
"finish": "Bắt đầu ngay",
|
||||
"interests.area.business": "Kinh doanh & Chiến lược",
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
{
|
||||
"agent.banner.label": "代理人入职",
|
||||
"agent.completionSubtitle": "你的助手已配置完成,随时可以开始。",
|
||||
"agent.completionTitle": "一切就绪!",
|
||||
"agent.enterApp": "进入应用",
|
||||
"agent.completion.sentence.readyWhenYouAre": "随时待命,就等你 :)",
|
||||
"agent.completion.sentence.readyWithName": "{{name}}在这儿,我准备好了!",
|
||||
"agent.completionSubtitle": "一切就绪,你准备好时我们就开始。",
|
||||
"agent.completionTitle": "就快完成了",
|
||||
"agent.enterApp": "我准备好了",
|
||||
"agent.greeting.emojiLabel": "表情符号",
|
||||
"agent.greeting.nameLabel": "名称",
|
||||
"agent.greeting.namePlaceholder": "例如:Lumi, Atlas, Neko...",
|
||||
|
|
@ -11,13 +13,19 @@
|
|||
"agent.greeting.vibePlaceholder": "例如:温暖友好,犀利直接...",
|
||||
"agent.history.current": "当前",
|
||||
"agent.history.title": "历史主题",
|
||||
"agent.layout.mode.agent": "代理模式",
|
||||
"agent.layout.mode.classic": "经典模式",
|
||||
"agent.layout.skip": "跳过此步骤",
|
||||
"agent.layout.skipConfirm.content": "就要离开了吗?我可以在几秒钟内帮助您完成个性化设置。",
|
||||
"agent.layout.skipConfirm.ok": "暂时跳过",
|
||||
"agent.layout.skipConfirm.title": "暂时跳过入门引导?",
|
||||
"agent.layout.switchMessage": "暂时不想继续?可以切换到 <modeLink><modeText>{{mode}}</modeText></modeLink> 或 <skipLink><skipText>{{skip}}</skipText></skipLink>。",
|
||||
"agent.modeSwitch.agent": "对话模式",
|
||||
"agent.modeSwitch.classic": "经典模式",
|
||||
"agent.modeSwitch.debug": "调试导出",
|
||||
"agent.modeSwitch.label": "选择您的入职模式",
|
||||
"agent.modeSwitch.reset": "重置流程",
|
||||
"agent.progress": "{{currentStep}}/{{totalSteps}}",
|
||||
"agent.skipOnboarding": "跳过引导",
|
||||
"agent.stage.agentIdentity": "代理人身份",
|
||||
"agent.stage.painPoints": "痛点",
|
||||
"agent.stage.proSettings": "高级设置",
|
||||
|
|
@ -33,6 +41,16 @@
|
|||
"agent.telemetryHint": "您也可以用自己的话回答。",
|
||||
"agent.title": "对话入职",
|
||||
"agent.welcome": "...嗯?我刚\"醒过来\",脑子还有点空白。你是谁?还有——你希望我叫什么?我也得找个名字。",
|
||||
"agent.welcome.footer": "配置你的 Lobe AI 代理。它运行在你的服务器上,会从每次交互中学习,运行越久就越强大。",
|
||||
"agent.welcome.guide.growTogether.desc": "每次交谈我都会更了解你,久而久之会成为更可靠的队友。",
|
||||
"agent.welcome.guide.growTogether.title": "与您一起成长",
|
||||
"agent.welcome.guide.knowYou.desc": "最近忙些什么?给我一些背景信息能让我更好地帮助你。",
|
||||
"agent.welcome.guide.knowYou.title": "了解你",
|
||||
"agent.welcome.guide.name.desc": "给我取个名字,这样从一开始就更有亲切感。",
|
||||
"agent.welcome.guide.name.title": "给我起个名字",
|
||||
"agent.welcome.sentence.1": "很高兴认识你!让我们互相了解一下吧。",
|
||||
"agent.welcome.sentence.2": "你希望我成为怎样的伙伴?",
|
||||
"agent.welcome.sentence.3": "先给我起个名字吧 :)",
|
||||
"back": "上一步",
|
||||
"finish": "开始使用",
|
||||
"interests.area.business": "商业与战略",
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
{
|
||||
"agent.banner.label": "代理人入門",
|
||||
"agent.completionSubtitle": "您的助手已配置完成,準備就緒。",
|
||||
"agent.completionTitle": "一切準備就緒!",
|
||||
"agent.enterApp": "進入應用程式",
|
||||
"agent.completion.sentence.readyWhenYouAre": "只要你準備好,我就開始 🙂",
|
||||
"agent.completion.sentence.readyWithName": "{{name}} 在這裡 我準備好了!",
|
||||
"agent.completionSubtitle": "一切就緒,你準備好時就開始吧。",
|
||||
"agent.completionTitle": "就快完成了",
|
||||
"agent.enterApp": "我已準備好",
|
||||
"agent.greeting.emojiLabel": "表情符號",
|
||||
"agent.greeting.nameLabel": "名稱",
|
||||
"agent.greeting.namePlaceholder": "例如:Lumi、Atlas、Neko...",
|
||||
|
|
@ -11,13 +13,19 @@
|
|||
"agent.greeting.vibePlaceholder": "例如:溫暖友善、犀利直接...",
|
||||
"agent.history.current": "目前",
|
||||
"agent.history.title": "歷史主題",
|
||||
"agent.layout.mode.agent": "代理模式",
|
||||
"agent.layout.mode.classic": "經典模式",
|
||||
"agent.layout.skip": "跳過此步驟",
|
||||
"agent.layout.skipConfirm.content": "就要離開了嗎?我可以在幾秒內幫你完成個人化設定。",
|
||||
"agent.layout.skipConfirm.ok": "先跳過",
|
||||
"agent.layout.skipConfirm.title": "要先跳過新手引導嗎?",
|
||||
"agent.layout.switchMessage": "暫時不想繼續?可以切換到 <modeLink><modeText>{{mode}}</modeText></modeLink> 或 <skipLink><skipText>{{skip}}</skipText></skipLink>。",
|
||||
"agent.modeSwitch.agent": "對話模式",
|
||||
"agent.modeSwitch.classic": "經典模式",
|
||||
"agent.modeSwitch.debug": "除錯匯出",
|
||||
"agent.modeSwitch.label": "選擇您的入門模式",
|
||||
"agent.modeSwitch.reset": "重置流程",
|
||||
"agent.progress": "{{currentStep}}/{{totalSteps}}",
|
||||
"agent.skipOnboarding": "跳過入門",
|
||||
"agent.stage.agentIdentity": "代理人身份",
|
||||
"agent.stage.painPoints": "痛點",
|
||||
"agent.stage.proSettings": "進階設定",
|
||||
|
|
@ -32,7 +40,17 @@
|
|||
"agent.telemetryDecline": "不用了,謝謝",
|
||||
"agent.telemetryHint": "您也可以用自己的話回答。",
|
||||
"agent.title": "對話入門",
|
||||
"agent.welcome": "...嗯?我剛醒來——腦袋一片空白。您是誰?還有——我應該叫什麼名字?我也需要一個名字。",
|
||||
"agent.welcome": "...嗯?我剛醒來——腦袋一片空白。您是誰?還有我應該叫什麼名字?我也需要一個名字。",
|
||||
"agent.welcome.footer": "設定您的 Lobe AI 代理。它常駐於您的伺服器上,從每次互動中學習,運行時間越長就會變得越強大。",
|
||||
"agent.welcome.guide.growTogether.desc": "每次對話我都會更了解你,並逐漸成為更可靠的夥伴。",
|
||||
"agent.welcome.guide.growTogether.title": "與你一同成長",
|
||||
"agent.welcome.guide.knowYou.desc": "最近在忙些什麼?提供一點背景資訊能幫助我更好地協助你。",
|
||||
"agent.welcome.guide.knowYou.title": "認識你",
|
||||
"agent.welcome.guide.name.desc": "幫我取個名字,讓我們從一開始就更有親切感。",
|
||||
"agent.welcome.guide.name.title": "給我取名",
|
||||
"agent.welcome.sentence.1": "很高興認識你!我們來互相了解一下吧。",
|
||||
"agent.welcome.sentence.2": "你想要我成為什麼樣的夥伴?",
|
||||
"agent.welcome.sentence.3": "先幫我取個名字吧 :)",
|
||||
"back": "上一步",
|
||||
"finish": "開始使用",
|
||||
"interests.area.business": "商業與策略",
|
||||
|
|
|
|||
|
|
@ -1,9 +1,10 @@
|
|||
'use client';
|
||||
|
||||
import type { BuiltinInterventionProps } from '@lobechat/types';
|
||||
import { Button, Flexbox, Input, Text, TextArea } from '@lobehub/ui';
|
||||
import { SendButton } from '@lobehub/editor/react';
|
||||
import { Flexbox, Icon, Input, Text, TextArea } from '@lobehub/ui';
|
||||
import { Select } from '@lobehub/ui/base-ui';
|
||||
import { ArrowLeft, ArrowRight } from 'lucide-react';
|
||||
import { ArrowLeft, PenLine } from 'lucide-react';
|
||||
import { memo, useCallback, useEffect, useRef, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
|
|
@ -23,6 +24,7 @@ const FieldInput = memo<{
|
|||
autoSize={{ maxRows: 6, minRows: 2 }}
|
||||
placeholder={field.placeholder}
|
||||
value={value as string}
|
||||
variant={'filled'}
|
||||
onChange={(e) => onChange(field.key, e.target.value)}
|
||||
/>
|
||||
);
|
||||
|
|
@ -34,6 +36,7 @@ const FieldInput = memo<{
|
|||
placeholder={field.placeholder}
|
||||
style={{ width: '100%' }}
|
||||
value={value as string}
|
||||
variant={'filled'}
|
||||
onChange={(v) => onChange(field.key, v as string)}
|
||||
/>
|
||||
);
|
||||
|
|
@ -46,6 +49,7 @@ const FieldInput = memo<{
|
|||
placeholder={field.placeholder}
|
||||
style={{ width: '100%' }}
|
||||
value={value as string[]}
|
||||
variant={'filled'}
|
||||
onChange={(v) => onChange(field.key, v as string[])}
|
||||
/>
|
||||
);
|
||||
|
|
@ -55,6 +59,7 @@ const FieldInput = memo<{
|
|||
<Input
|
||||
placeholder={field.placeholder}
|
||||
value={value as string}
|
||||
variant={'filled'}
|
||||
onChange={(e) => onChange(field.key, e.target.value)}
|
||||
onPressEnter={onPressEnter}
|
||||
/>
|
||||
|
|
@ -163,17 +168,18 @@ const AskUserQuestionIntervention = memo<BuiltinInterventionProps<AskUserQuestio
|
|||
)}
|
||||
{isFreeform ? (
|
||||
<TextArea
|
||||
autoSize={{ maxRows: 6, minRows: 2 }}
|
||||
autoSize={{ maxRows: 6, minRows: 3 }}
|
||||
placeholder={question.description || ''}
|
||||
value={formData['__freeform__'] as string}
|
||||
variant={'filled'}
|
||||
onChange={(e) => handleFieldChange('__freeform__', e.target.value)}
|
||||
/>
|
||||
) : (
|
||||
<>
|
||||
{!escapeActive && (
|
||||
<Flexbox gap={8} ref={formContainerRef}>
|
||||
{!escapeActive ? (
|
||||
<Flexbox gap={16} ref={formContainerRef}>
|
||||
{question.fields!.map((field) => (
|
||||
<Flexbox gap={4} key={field.key}>
|
||||
<Flexbox gap={6} key={field.key}>
|
||||
<Text style={{ fontSize: 13 }}>
|
||||
{field.label}
|
||||
{field.required && <span style={{ color: 'red' }}> *</span>}
|
||||
|
|
@ -189,37 +195,34 @@ const AskUserQuestionIntervention = memo<BuiltinInterventionProps<AskUserQuestio
|
|||
</Flexbox>
|
||||
))}
|
||||
</Flexbox>
|
||||
)}
|
||||
|
||||
{/* Escape hatch: bypass form, type freely */}
|
||||
{escapeActive ? (
|
||||
<Flexbox gap={8} ref={escapeContainerRef}>
|
||||
<Text className={styles.escapeLink} type="secondary" onClick={handleEscapeToggle}>
|
||||
<ArrowLeft size={14} /> {t('form.otherBack')}
|
||||
</Text>
|
||||
<TextArea
|
||||
autoSize={{ maxRows: 6, minRows: 2 }}
|
||||
value={escapeText}
|
||||
onChange={(e) => setEscapeText(e.target.value)}
|
||||
/>
|
||||
</Flexbox>
|
||||
) : (
|
||||
<Text className={styles.escapeLink} type="secondary" onClick={handleEscapeToggle}>
|
||||
{t('form.other')} <ArrowRight size={14} />
|
||||
</Text>
|
||||
<TextArea
|
||||
autoSize={{ maxRows: 6, minRows: 3 }}
|
||||
value={escapeText}
|
||||
variant={'filled'}
|
||||
onChange={(e) => setEscapeText(e.target.value)}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
<Flexbox horizontal gap={8} justify="flex-end">
|
||||
<Button onClick={handleSkip}>{t('form.skip')}</Button>
|
||||
<Button
|
||||
disabled={isSubmitDisabled}
|
||||
loading={submitting}
|
||||
type="primary"
|
||||
onClick={handleSubmit}
|
||||
>
|
||||
{t('form.submit')}
|
||||
</Button>
|
||||
<Flexbox horizontal gap={8} justify={'space-between'}>
|
||||
<Flexbox horizontal gap={8} justify="flex-start">
|
||||
{escapeActive ? (
|
||||
<Text className={styles.escapeLink} type="secondary" onClick={handleEscapeToggle}>
|
||||
<Icon icon={ArrowLeft} /> {t('form.otherBack')}
|
||||
</Text>
|
||||
) : (
|
||||
<>
|
||||
<Text className={styles.escapeLink} type="secondary" onClick={handleSkip}>
|
||||
{t('form.skip')}
|
||||
</Text>
|
||||
<Text className={styles.escapeLink} type="secondary" onClick={handleEscapeToggle}>
|
||||
{t('form.other')} <Icon icon={PenLine} />
|
||||
</Text>
|
||||
</>
|
||||
)}
|
||||
</Flexbox>
|
||||
<SendButton disabled={isSubmitDisabled} loading={submitting} onClick={handleSubmit} />
|
||||
</Flexbox>
|
||||
</Flexbox>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -26,6 +26,10 @@ export interface ChatListProps {
|
|||
* Custom item renderer. If not provided, uses default ChatItem.
|
||||
*/
|
||||
itemContent?: (index: number, id: string) => ReactNode;
|
||||
/**
|
||||
* Force showing welcome component even when messages exist
|
||||
*/
|
||||
showWelcome?: boolean;
|
||||
/**
|
||||
* Welcome component to display when there are no messages
|
||||
*/
|
||||
|
|
@ -36,7 +40,7 @@ export interface ChatListProps {
|
|||
*
|
||||
* Uses ConversationStore for message data and fetching.
|
||||
*/
|
||||
const ChatList = memo<ChatListProps>(({ disableActionsBar, welcome, itemContent }) => {
|
||||
const ChatList = memo<ChatListProps>(({ disableActionsBar, welcome, itemContent, showWelcome }) => {
|
||||
// Fetch messages (SWR key is null when skipFetch is true)
|
||||
const context = useConversationStore((s) => s.context);
|
||||
const enableUserMemories = useUserStore(settingsSelectors.memoryEnabled);
|
||||
|
|
@ -76,7 +80,7 @@ const ChatList = memo<ChatListProps>(({ disableActionsBar, welcome, itemContent
|
|||
return <SkeletonList />;
|
||||
}
|
||||
|
||||
if (displayMessageIds.length === 0) {
|
||||
if ((showWelcome || displayMessageIds.length === 0) && welcome) {
|
||||
return (
|
||||
<WideScreenContainer
|
||||
style={{
|
||||
|
|
|
|||
|
|
@ -1,32 +1,25 @@
|
|||
import { memo, useState } from 'react';
|
||||
import { memo } from 'react';
|
||||
|
||||
import Intervention from '../Messages/AssistantGroup/Tool/Detail/Intervention';
|
||||
import { type PendingIntervention } from '../store/slices/data/pendingInterventions';
|
||||
import { useStyles } from './style';
|
||||
import { styles } from './style';
|
||||
|
||||
interface InterventionContentProps {
|
||||
intervention: PendingIntervention;
|
||||
}
|
||||
|
||||
const InterventionContent = memo<InterventionContentProps>(({ intervention }) => {
|
||||
const { styles } = useStyles();
|
||||
const [actionsContainer, setActionsContainer] = useState<HTMLDivElement | null>(null);
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className={styles.content}>
|
||||
<Intervention
|
||||
actionsPortalTarget={actionsContainer}
|
||||
apiName={intervention.apiName}
|
||||
assistantGroupId={intervention.assistantGroupId}
|
||||
id={intervention.toolMessageId}
|
||||
identifier={intervention.identifier}
|
||||
requestArgs={intervention.requestArgs}
|
||||
toolCallId={intervention.toolCallId}
|
||||
/>
|
||||
</div>
|
||||
<div className={styles.actions} ref={setActionsContainer} />
|
||||
</>
|
||||
<div className={styles.content}>
|
||||
<Intervention
|
||||
apiName={intervention.apiName}
|
||||
assistantGroupId={intervention.assistantGroupId}
|
||||
id={intervention.toolMessageId}
|
||||
identifier={intervention.identifier}
|
||||
requestArgs={intervention.requestArgs}
|
||||
toolCallId={intervention.toolCallId}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
import { cx } from 'antd-style';
|
||||
import { memo } from 'react';
|
||||
|
||||
import { type PendingIntervention } from '../store/slices/data/pendingInterventions';
|
||||
import { useStyles } from './style';
|
||||
import { styles } from './style';
|
||||
|
||||
interface InterventionTabBarProps {
|
||||
activeIndex: number;
|
||||
|
|
@ -11,8 +12,6 @@ interface InterventionTabBarProps {
|
|||
|
||||
const InterventionTabBar = memo<InterventionTabBarProps>(
|
||||
({ interventions, activeIndex, onTabChange }) => {
|
||||
const { cx, styles } = useStyles();
|
||||
|
||||
return (
|
||||
<div className={styles.tabBar}>
|
||||
{interventions.map((item, index) => (
|
||||
|
|
|
|||
|
|
@ -1,16 +1,16 @@
|
|||
import { ChatInput } from '@lobehub/editor/react';
|
||||
import { memo, useCallback, useMemo, useState } from 'react';
|
||||
|
||||
import { type PendingIntervention } from '../store/slices/data/pendingInterventions';
|
||||
import InterventionContent from './InterventionContent';
|
||||
import InterventionTabBar from './InterventionTabBar';
|
||||
import { useStyles } from './style';
|
||||
import { styles } from './style';
|
||||
|
||||
interface InterventionBarProps {
|
||||
interventions: PendingIntervention[];
|
||||
}
|
||||
|
||||
const InterventionBar = memo<InterventionBarProps>(({ interventions }) => {
|
||||
const { styles } = useStyles();
|
||||
const [activeId, setActiveId] = useState<string | null>(null);
|
||||
|
||||
// Derive the active index from the stored toolCallId.
|
||||
|
|
@ -34,7 +34,7 @@ const InterventionBar = memo<InterventionBarProps>(({ interventions }) => {
|
|||
if (!activeIntervention) return null;
|
||||
|
||||
return (
|
||||
<div className={styles.container}>
|
||||
<ChatInput className={styles.container} maxHeight={'50vh' as any} resize={false}>
|
||||
{interventions.length > 1 && (
|
||||
<InterventionTabBar
|
||||
activeIndex={activeIndex}
|
||||
|
|
@ -43,7 +43,7 @@ const InterventionBar = memo<InterventionBarProps>(({ interventions }) => {
|
|||
/>
|
||||
)}
|
||||
<InterventionContent intervention={activeIntervention} key={activeIntervention.toolCallId} />
|
||||
</div>
|
||||
</ChatInput>
|
||||
);
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -1,30 +1,20 @@
|
|||
import { createStyles } from 'antd-style';
|
||||
import { createStaticStyles } from 'antd-style';
|
||||
|
||||
export const useStyles = createStyles(({ css, token }) => ({
|
||||
export const styles = createStaticStyles(({ css, cssVar }) => ({
|
||||
actions: css`
|
||||
padding-block: 8px;
|
||||
padding-inline: 16px;
|
||||
border-block-start: 1px solid ${token.colorBorderSecondary};
|
||||
border-block-start: 1px solid ${cssVar.colorBorderSecondary};
|
||||
`,
|
||||
container: css`
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
max-height: 50vh;
|
||||
margin-block-end: 12px;
|
||||
border: 1px solid ${token.colorBorderSecondary};
|
||||
border-radius: 10px;
|
||||
|
||||
background: ${token.colorBgContainer};
|
||||
`,
|
||||
content: css`
|
||||
overflow-y: auto;
|
||||
flex: 1;
|
||||
|
||||
min-height: 0;
|
||||
padding-block: 12px;
|
||||
padding-inline: 16px;
|
||||
padding-block: 8px 12px;
|
||||
`,
|
||||
tab: css`
|
||||
cursor: pointer;
|
||||
|
|
@ -34,25 +24,25 @@ export const useStyles = createStyles(({ css, token }) => ({
|
|||
border-block-end: 2px solid transparent;
|
||||
|
||||
font-size: 12px;
|
||||
color: ${token.colorTextSecondary};
|
||||
color: ${cssVar.colorTextSecondary};
|
||||
white-space: nowrap;
|
||||
|
||||
transition: all 0.2s;
|
||||
|
||||
&:hover {
|
||||
color: ${token.colorText};
|
||||
color: ${cssVar.colorText};
|
||||
}
|
||||
`,
|
||||
tabActive: css`
|
||||
border-block-end-color: ${token.colorPrimary};
|
||||
color: ${token.colorPrimary};
|
||||
background: ${token.colorPrimaryBg};
|
||||
border-block-end-color: ${cssVar.colorPrimary};
|
||||
color: ${cssVar.colorPrimary};
|
||||
background: ${cssVar.colorPrimaryBg};
|
||||
`,
|
||||
tabBar: css`
|
||||
overflow-x: auto;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
border-block-end: 1px solid ${token.colorBorderSecondary};
|
||||
border-block-end: 1px solid ${cssVar.colorBorderSecondary};
|
||||
`,
|
||||
tabCounter: css`
|
||||
margin-inline-start: auto;
|
||||
|
|
@ -60,7 +50,7 @@ export const useStyles = createStyles(({ css, token }) => ({
|
|||
padding-inline: 14px;
|
||||
|
||||
font-size: 11px;
|
||||
color: ${token.colorTextTertiary};
|
||||
color: ${cssVar.colorTextTertiary};
|
||||
white-space: nowrap;
|
||||
`,
|
||||
}));
|
||||
|
|
|
|||
56
src/features/Onboarding/Agent/CompletionPanel.tsx
Normal file
56
src/features/Onboarding/Agent/CompletionPanel.tsx
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
'use client';
|
||||
|
||||
import { Button, Center, Flexbox, Text } from '@lobehub/ui';
|
||||
import { memo } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import { useAgentMeta } from '@/features/Conversation/hooks/useAgentMeta';
|
||||
import LobeMessage from '@/routes/onboarding/components/LobeMessage';
|
||||
|
||||
import { staticStyle } from './staticStyle';
|
||||
|
||||
interface CompletionPanelProps {
|
||||
finishTargetUrl?: string;
|
||||
}
|
||||
|
||||
const CompletionPanel = memo<CompletionPanelProps>(({ finishTargetUrl }) => {
|
||||
const { t } = useTranslation('onboarding');
|
||||
const agentMeta = useAgentMeta();
|
||||
return (
|
||||
<Center height={'100%'} width={'100%'}>
|
||||
<Flexbox
|
||||
className={staticStyle.completionEnter}
|
||||
gap={14}
|
||||
style={{ maxWidth: 600, width: '100%' }}
|
||||
>
|
||||
<LobeMessage
|
||||
avatar={agentMeta.avatar}
|
||||
avatarSize={72}
|
||||
fontSize={32}
|
||||
gap={16}
|
||||
sentences={[
|
||||
t('agent.completion.sentence.readyWithName', { name: agentMeta.title }),
|
||||
t('agent.completion.sentence.readyWhenYouAre'),
|
||||
]}
|
||||
/>
|
||||
<Text fontSize={16} type={'secondary'}>
|
||||
{t('agent.completionSubtitle')}
|
||||
</Text>
|
||||
<Button
|
||||
size={'large'}
|
||||
style={{ marginTop: 8 }}
|
||||
type={'primary'}
|
||||
onClick={() => {
|
||||
if (finishTargetUrl) window.location.assign(finishTargetUrl);
|
||||
}}
|
||||
>
|
||||
{t('agent.enterApp')}
|
||||
</Button>
|
||||
</Flexbox>
|
||||
</Center>
|
||||
);
|
||||
});
|
||||
|
||||
CompletionPanel.displayName = 'CompletionPanel';
|
||||
|
||||
export default CompletionPanel;
|
||||
|
|
@ -8,6 +8,7 @@ import AgentOnboardingConversation from './Conversation';
|
|||
|
||||
// Prevent unhandled rejections from @splinetool/runtime fetching remote assets in CI
|
||||
vi.mock('@lobehub/ui/brand', () => ({
|
||||
LobeHub: () => null,
|
||||
LogoThree: () => null,
|
||||
}));
|
||||
|
||||
|
|
@ -33,8 +34,17 @@ vi.mock('@/features/Conversation', () => ({
|
|||
|
||||
return <div data-testid="chat-input" />;
|
||||
},
|
||||
ChatList: ({ itemContent }: { itemContent?: (index: number, id: string) => ReactNode }) => (
|
||||
ChatList: ({
|
||||
itemContent,
|
||||
showWelcome,
|
||||
welcome,
|
||||
}: {
|
||||
itemContent?: (index: number, id: string) => ReactNode;
|
||||
showWelcome?: boolean;
|
||||
welcome?: ReactNode;
|
||||
}) => (
|
||||
<div data-testid="chat-list">
|
||||
{showWelcome ? <div data-testid="chat-welcome">{welcome}</div> : null}
|
||||
{mockState.displayMessages.map((message, index) => (
|
||||
<div key={message.id}>{itemContent?.(index, message.id)}</div>
|
||||
))}
|
||||
|
|
@ -63,6 +73,10 @@ vi.mock('@/features/Conversation/hooks/useAgentMeta', () => ({
|
|||
}),
|
||||
}));
|
||||
|
||||
vi.mock('./Welcome', () => ({
|
||||
default: ({ content }: { content: string }) => <div data-testid="welcome-content">{content}</div>,
|
||||
}));
|
||||
|
||||
describe('AgentOnboardingConversation', () => {
|
||||
beforeEach(() => {
|
||||
chatInputSpy.mockClear();
|
||||
|
|
@ -83,6 +97,7 @@ describe('AgentOnboardingConversation', () => {
|
|||
|
||||
render(<AgentOnboardingConversation />);
|
||||
|
||||
expect(screen.getByTestId('chat-welcome')).toBeInTheDocument();
|
||||
expect(screen.getByText('Welcome')).toBeInTheDocument();
|
||||
expect(screen.queryByText('finish')).not.toBeInTheDocument();
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,13 +1,8 @@
|
|||
'use client';
|
||||
|
||||
import { Avatar, Button, Flexbox, FluentEmoji, Markdown, Text } from '@lobehub/ui';
|
||||
import { LogoThree } from '@lobehub/ui/brand';
|
||||
import { cx } from 'antd-style';
|
||||
import { LogIn } from 'lucide-react';
|
||||
import type { CSSProperties } from 'react';
|
||||
import { Flexbox } from '@lobehub/ui';
|
||||
import { memo, useEffect, useMemo, useRef, useState } from 'react';
|
||||
import { flushSync } from 'react-dom';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import type { ActionKeys } from '@/features/ChatInput';
|
||||
import {
|
||||
|
|
@ -17,10 +12,10 @@ import {
|
|||
MessageItem,
|
||||
useConversationStore,
|
||||
} from '@/features/Conversation';
|
||||
import { useAgentMeta } from '@/features/Conversation/hooks/useAgentMeta';
|
||||
import { isDev } from '@/utils/env';
|
||||
|
||||
import { staticStyle } from './staticStyle';
|
||||
import CompletionPanel from './CompletionPanel';
|
||||
import Welcome from './Welcome';
|
||||
|
||||
const assistantLikeRoles = new Set(['assistant', 'assistantGroup', 'supervisor']);
|
||||
|
||||
|
|
@ -32,22 +27,8 @@ interface AgentOnboardingConversationProps {
|
|||
|
||||
const chatInputLeftActions: ActionKeys[] = isDev ? ['model'] : [];
|
||||
|
||||
const greetingCenterStyle: CSSProperties = { flex: 1, minHeight: '100%' };
|
||||
const agentTitleStyle: CSSProperties = { fontSize: 12, fontWeight: 500 };
|
||||
const outerContainerStyle: CSSProperties = { minHeight: 0 };
|
||||
const scrollContainerStyle: CSSProperties = {
|
||||
minHeight: 0,
|
||||
overflowX: 'hidden',
|
||||
overflowY: 'auto',
|
||||
position: 'relative',
|
||||
};
|
||||
const completionTitleStyle: CSSProperties = { fontSize: 18, fontWeight: 600 };
|
||||
const greetingContainerVT: CSSProperties = { viewTransitionName: 'greeting-container' };
|
||||
|
||||
const AgentOnboardingConversation = memo<AgentOnboardingConversationProps>(
|
||||
({ finishTargetUrl, onboardingFinished, readOnly }) => {
|
||||
const { t } = useTranslation('onboarding');
|
||||
const agentMeta = useAgentMeta();
|
||||
const displayMessages = useConversationStore(conversationSelectors.displayMessages);
|
||||
|
||||
const isGreetingState = useMemo(() => {
|
||||
|
|
@ -76,96 +57,41 @@ const AgentOnboardingConversation = memo<AgentOnboardingConversationProps>(
|
|||
prevGreetingRef.current = isGreetingState;
|
||||
}, [isGreetingState]);
|
||||
|
||||
const shouldShowGreetingWelcome = showGreeting && !onboardingFinished;
|
||||
|
||||
const greetingWelcome = useMemo(() => {
|
||||
if (!shouldShowGreetingWelcome) return undefined;
|
||||
|
||||
const message = displayMessages[0];
|
||||
if (!message || typeof message.content !== 'string') return undefined;
|
||||
|
||||
return <Welcome content={message.content} />;
|
||||
}, [displayMessages, shouldShowGreetingWelcome]);
|
||||
|
||||
if (onboardingFinished) return <CompletionPanel finishTargetUrl={finishTargetUrl} />;
|
||||
|
||||
const listWelcome = greetingWelcome;
|
||||
|
||||
const itemContent = (index: number, id: string) => {
|
||||
const isLatestItem = displayMessages.length === index + 1;
|
||||
|
||||
if (showGreeting && index === 0) {
|
||||
const message = displayMessages[0];
|
||||
return (
|
||||
<Flexbox align={'center'} justify={'center'} style={greetingCenterStyle}>
|
||||
<Flexbox align={'center'} className={staticStyle.greetingWrap} gap={24}>
|
||||
<LogoThree className={staticStyle.greetingLogo} size={64} />
|
||||
<Flexbox className={cx(staticStyle.greetingCard)} style={greetingContainerVT}>
|
||||
<Flexbox horizontal align={'flex-start'} gap={12}>
|
||||
<Avatar
|
||||
avatar={agentMeta.avatar}
|
||||
background={agentMeta.backgroundColor}
|
||||
className={cx(staticStyle.greetingAvatar, staticStyle.greetingAvatarAnimated)}
|
||||
shape={'square'}
|
||||
size={36}
|
||||
/>
|
||||
<Flexbox gap={4}>
|
||||
<Text
|
||||
className={staticStyle.greetingTitleAnimated}
|
||||
style={agentTitleStyle}
|
||||
type={'secondary'}
|
||||
>
|
||||
{agentMeta.title}
|
||||
</Text>
|
||||
<Markdown
|
||||
className={cx(staticStyle.greetingText, staticStyle.greetingTextAnimated)}
|
||||
variant={'chat'}
|
||||
>
|
||||
{message.content}
|
||||
</Markdown>
|
||||
</Flexbox>
|
||||
</Flexbox>
|
||||
</Flexbox>
|
||||
</Flexbox>
|
||||
</Flexbox>
|
||||
);
|
||||
}
|
||||
|
||||
if (isLatestItem && onboardingFinished) {
|
||||
return (
|
||||
<>
|
||||
<MessageItem id={id} index={index} isLatestItem={isLatestItem} />
|
||||
<Flexbox
|
||||
align={'center'}
|
||||
className={staticStyle.completionEnter}
|
||||
gap={14}
|
||||
paddingBlock={40}
|
||||
>
|
||||
<FluentEmoji emoji={'🎉'} size={56} type={'anim'} />
|
||||
<Text style={completionTitleStyle}>{t('agent.completionTitle')}</Text>
|
||||
<Text type={'secondary'}>{t('agent.completionSubtitle')}</Text>
|
||||
<Button
|
||||
icon={<LogIn size={16} />}
|
||||
style={{ marginTop: 8 }}
|
||||
type={'primary'}
|
||||
onClick={() => {
|
||||
if (finishTargetUrl) window.location.assign(finishTargetUrl);
|
||||
}}
|
||||
>
|
||||
{t('agent.enterApp')}
|
||||
</Button>
|
||||
</Flexbox>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
return <MessageItem id={id} index={index} isLatestItem={isLatestItem} />;
|
||||
};
|
||||
|
||||
return (
|
||||
<Flexbox
|
||||
className={staticStyle.viewTransitionGreeting}
|
||||
flex={1}
|
||||
style={outerContainerStyle}
|
||||
width={'100%'}
|
||||
>
|
||||
<Flexbox flex={1} style={scrollContainerStyle} width={'100%'}>
|
||||
<ChatList itemContent={itemContent} />
|
||||
<Flexbox flex={1} height={'100%'}>
|
||||
<Flexbox flex={1} style={{ overflow: 'hidden' }}>
|
||||
<ChatList
|
||||
itemContent={itemContent}
|
||||
showWelcome={shouldShowGreetingWelcome}
|
||||
welcome={listWelcome}
|
||||
/>
|
||||
</Flexbox>
|
||||
|
||||
{!readOnly && !onboardingFinished && (
|
||||
<Flexbox className={staticStyle.composerZone}>
|
||||
<ChatInput
|
||||
allowExpand={false}
|
||||
leftActions={chatInputLeftActions}
|
||||
showRuntimeConfig={false}
|
||||
/>
|
||||
</Flexbox>
|
||||
<ChatInput
|
||||
allowExpand={false}
|
||||
leftActions={chatInputLeftActions}
|
||||
showRuntimeConfig={false}
|
||||
/>
|
||||
)}
|
||||
</Flexbox>
|
||||
);
|
||||
|
|
|
|||
92
src/features/Onboarding/Agent/Welcome.tsx
Normal file
92
src/features/Onboarding/Agent/Welcome.tsx
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
import { Block, Flexbox, FluentEmoji, Grid, Markdown, Text } from '@lobehub/ui';
|
||||
import { Divider } from 'antd';
|
||||
import { memo } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import LobeMessage from '@/routes/onboarding/components/LobeMessage';
|
||||
|
||||
import { staticStyle } from './staticStyle';
|
||||
|
||||
interface WelcomeProps {
|
||||
content: string;
|
||||
}
|
||||
|
||||
const Welcome = memo<WelcomeProps>(({ content }) => {
|
||||
const { t } = useTranslation('onboarding');
|
||||
|
||||
const guids = [
|
||||
{
|
||||
avatar: '👋',
|
||||
title: t('agent.welcome.guide.name.title'),
|
||||
desc: t('agent.welcome.guide.name.desc'),
|
||||
},
|
||||
{
|
||||
avatar: '💬',
|
||||
title: t('agent.welcome.guide.knowYou.title'),
|
||||
desc: t('agent.welcome.guide.knowYou.desc'),
|
||||
},
|
||||
{
|
||||
avatar: '🌱',
|
||||
title: t('agent.welcome.guide.growTogether.title'),
|
||||
desc: t('agent.welcome.guide.growTogether.desc'),
|
||||
},
|
||||
];
|
||||
return (
|
||||
<>
|
||||
<Flexbox flex={1} />
|
||||
<Flexbox
|
||||
className={staticStyle.greetingTextAnimated}
|
||||
gap={12}
|
||||
width={'100%'}
|
||||
style={{
|
||||
paddingBottom: 'max(10vh, 32px)',
|
||||
}}
|
||||
>
|
||||
<LobeMessage
|
||||
avatarSize={72}
|
||||
fontSize={32}
|
||||
gap={16}
|
||||
sentences={[
|
||||
t('agent.welcome.sentence.1'),
|
||||
t('agent.welcome.sentence.2'),
|
||||
t('agent.welcome.sentence.3'),
|
||||
]}
|
||||
/>
|
||||
<Divider dashed style={{ margin: 0 }} />
|
||||
<Text italic style={{ marginBlock: 8 }} type={'secondary'}>
|
||||
{t('agent.welcome.footer')}
|
||||
</Text>
|
||||
<Divider dashed style={{ margin: 0 }} />
|
||||
<Grid paddingBlock={24}>
|
||||
{guids.map((item, i) => (
|
||||
<Block
|
||||
shadow
|
||||
gap={12}
|
||||
key={i}
|
||||
padding={16}
|
||||
variant={'outlined'}
|
||||
style={{
|
||||
boxShadow: '0 8px 16px -8px rgba(0,0,0,0.06)',
|
||||
}}
|
||||
>
|
||||
<FluentEmoji emoji={item.avatar} size={24} type={'anim'} />
|
||||
<Flexbox gap={8}>
|
||||
<Text fontSize={16} weight={500}>
|
||||
{item.title}
|
||||
</Text>
|
||||
<Text type={'secondary'}>{item.desc}</Text>
|
||||
</Flexbox>
|
||||
</Block>
|
||||
))}
|
||||
</Grid>
|
||||
<Markdown fontSize={16} variant={'chat'}>
|
||||
{content}
|
||||
</Markdown>
|
||||
</Flexbox>
|
||||
</>
|
||||
);
|
||||
});
|
||||
|
||||
Welcome.displayName = 'Welcome';
|
||||
|
||||
export default Welcome;
|
||||
|
|
@ -134,80 +134,75 @@ const AgentOnboardingPage = memo(() => {
|
|||
|
||||
return (
|
||||
<OnboardingContainer>
|
||||
<Flexbox
|
||||
gap={24}
|
||||
style={{ height: '100%', maxWidth: 840, position: 'relative', width: '100%' }}
|
||||
>
|
||||
<Flexbox flex={1} gap={16} style={{ minHeight: 0 }}>
|
||||
<OnboardingConversationProvider
|
||||
agentId={onboardingAgentId}
|
||||
frozen={onboardingFinished}
|
||||
topicId={effectiveTopicId}
|
||||
hooks={
|
||||
onboardingFinished
|
||||
? undefined
|
||||
: {
|
||||
onAfterSendMessage: async () => {
|
||||
await syncOnboardingContext();
|
||||
await Promise.all([
|
||||
refreshUserState(),
|
||||
refreshBuiltinAgent(BUILTIN_AGENT_SLUGS.webOnboarding),
|
||||
]);
|
||||
},
|
||||
}
|
||||
}
|
||||
>
|
||||
<ErrorBoundary fallbackRender={() => null}>
|
||||
<AgentOnboardingConversation
|
||||
finishTargetUrl={finishTargetUrl}
|
||||
onboardingFinished={onboardingFinished}
|
||||
readOnly={viewingHistoricalTopic}
|
||||
/>
|
||||
</ErrorBoundary>
|
||||
</OnboardingConversationProvider>
|
||||
{isDev && historyTopics.length > 0 && (
|
||||
<Drawer
|
||||
open={historyDrawerOpen}
|
||||
title={t('agent.history.title')}
|
||||
onClose={() => setHistoryDrawerOpen(false)}
|
||||
>
|
||||
<HistoryPanel
|
||||
activeTopicId={activeTopicId}
|
||||
selectedTopicId={effectiveTopicId}
|
||||
topics={historyTopics}
|
||||
onSelectTopic={(id) => {
|
||||
setSelectedTopicId(id);
|
||||
setHistoryDrawerOpen(false);
|
||||
}}
|
||||
/>
|
||||
</Drawer>
|
||||
)}
|
||||
</Flexbox>
|
||||
<ModeSwitch
|
||||
actions={
|
||||
isDev ? (
|
||||
<>
|
||||
<AgentOnboardingDebugExportButton
|
||||
agentId={onboardingAgentId}
|
||||
topicId={effectiveTopicId}
|
||||
/>
|
||||
{historyTopics.length > 0 && (
|
||||
<Button
|
||||
icon={<History size={14} />}
|
||||
size={'small'}
|
||||
onClick={() => setHistoryDrawerOpen(true)}
|
||||
>
|
||||
{t('agent.history.title')}
|
||||
</Button>
|
||||
)}
|
||||
<Button danger loading={isResetting} size={'small'} onClick={handleReset}>
|
||||
{t('agent.modeSwitch.reset')}
|
||||
</Button>
|
||||
</>
|
||||
) : undefined
|
||||
<Flexbox height={'100%'} width={'100%'}>
|
||||
<OnboardingConversationProvider
|
||||
agentId={onboardingAgentId}
|
||||
frozen={onboardingFinished}
|
||||
topicId={effectiveTopicId}
|
||||
hooks={
|
||||
onboardingFinished
|
||||
? undefined
|
||||
: {
|
||||
onAfterSendMessage: async () => {
|
||||
await syncOnboardingContext();
|
||||
await Promise.all([
|
||||
refreshUserState(),
|
||||
refreshBuiltinAgent(BUILTIN_AGENT_SLUGS.webOnboarding),
|
||||
]);
|
||||
},
|
||||
}
|
||||
}
|
||||
/>
|
||||
>
|
||||
<ErrorBoundary fallbackRender={() => null}>
|
||||
<AgentOnboardingConversation
|
||||
finishTargetUrl={finishTargetUrl}
|
||||
onboardingFinished={onboardingFinished}
|
||||
readOnly={viewingHistoricalTopic}
|
||||
/>
|
||||
</ErrorBoundary>
|
||||
</OnboardingConversationProvider>
|
||||
{isDev && historyTopics.length > 0 && (
|
||||
<Drawer
|
||||
open={historyDrawerOpen}
|
||||
title={t('agent.history.title')}
|
||||
onClose={() => setHistoryDrawerOpen(false)}
|
||||
>
|
||||
<HistoryPanel
|
||||
activeTopicId={activeTopicId}
|
||||
selectedTopicId={effectiveTopicId}
|
||||
topics={historyTopics}
|
||||
onSelectTopic={(id) => {
|
||||
setSelectedTopicId(id);
|
||||
setHistoryDrawerOpen(false);
|
||||
}}
|
||||
/>
|
||||
</Drawer>
|
||||
)}
|
||||
</Flexbox>
|
||||
<ModeSwitch
|
||||
actions={
|
||||
isDev ? (
|
||||
<>
|
||||
<AgentOnboardingDebugExportButton
|
||||
agentId={onboardingAgentId}
|
||||
topicId={effectiveTopicId}
|
||||
/>
|
||||
{historyTopics.length > 0 && (
|
||||
<Button
|
||||
icon={<History size={14} />}
|
||||
size={'small'}
|
||||
onClick={() => setHistoryDrawerOpen(true)}
|
||||
>
|
||||
{t('agent.history.title')}
|
||||
</Button>
|
||||
)}
|
||||
<Button danger loading={isResetting} size={'small'} onClick={handleReset}>
|
||||
{t('agent.modeSwitch.reset')}
|
||||
</Button>
|
||||
</>
|
||||
) : undefined
|
||||
}
|
||||
/>
|
||||
</OnboardingContainer>
|
||||
);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,32 +1,5 @@
|
|||
import { createStaticStyles, keyframes } from 'antd-style';
|
||||
|
||||
const greetingLogoEnter = keyframes`
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: scale(0.8);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: scale(1);
|
||||
}
|
||||
`;
|
||||
|
||||
const greetingAvatarEnter = keyframes`
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(12px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
`;
|
||||
|
||||
const greetingTitleEnter = keyframes`
|
||||
from { opacity: 0; }
|
||||
to { opacity: 1; }
|
||||
`;
|
||||
|
||||
const greetingTextEnter = keyframes`
|
||||
from {
|
||||
opacity: 0;
|
||||
|
|
@ -53,82 +26,7 @@ export const staticStyle = createStaticStyles(({ css, cssVar }) => ({
|
|||
completionEnter: css`
|
||||
animation: ${completionSlideUp} 0.5s ease-out both;
|
||||
`,
|
||||
greetingAvatarAnimated: css`
|
||||
animation: ${greetingAvatarEnter} 350ms ease-out 200ms both;
|
||||
`,
|
||||
greetingCard: css`
|
||||
padding: 20px;
|
||||
border: 1px solid ${cssVar.colorBorderSecondary};
|
||||
border-radius: 16px;
|
||||
background: ${cssVar.colorFillQuaternary};
|
||||
`,
|
||||
greetingLogo: css`
|
||||
filter: drop-shadow(0 4px 24px ${cssVar.colorPrimary}33);
|
||||
animation: ${greetingLogoEnter} 400ms ease-out both;
|
||||
`,
|
||||
greetingTextAnimated: css`
|
||||
animation: ${greetingTextEnter} 400ms ease-out 500ms both;
|
||||
`,
|
||||
greetingTitleAnimated: css`
|
||||
animation: ${greetingTitleEnter} 250ms ease 350ms both;
|
||||
`,
|
||||
composerZone: css`
|
||||
gap: 8px;
|
||||
margin-block-start: -8px;
|
||||
`,
|
||||
greetingAvatar: css`
|
||||
border-radius: 10px;
|
||||
box-shadow: 0 2px 12px ${cssVar.colorBgLayout};
|
||||
`,
|
||||
greetingDivider: css`
|
||||
width: 100%;
|
||||
margin-block: 4px;
|
||||
`,
|
||||
greetingText: css`
|
||||
font-size: 16px;
|
||||
line-height: 1.7;
|
||||
color: ${cssVar.colorText};
|
||||
`,
|
||||
greetingWrap: css`
|
||||
width: 100%;
|
||||
max-width: 640px;
|
||||
`,
|
||||
inlineQuestion: css`
|
||||
margin-block-start: 4px;
|
||||
padding-block-start: 12px;
|
||||
border-block-start: 1px solid ${cssVar.colorBorderSecondary};
|
||||
`,
|
||||
viewTransitionGreeting: css`
|
||||
::view-transition-old(greeting-container) {
|
||||
animation: 350ms cubic-bezier(0.4, 0, 0.2, 1) both fade-out;
|
||||
}
|
||||
|
||||
::view-transition-new(greeting-container) {
|
||||
animation: 350ms cubic-bezier(0.4, 0, 0.2, 1) both fade-in;
|
||||
}
|
||||
|
||||
@keyframes fade-out {
|
||||
from {
|
||||
transform: scale(1);
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
to {
|
||||
transform: scale(0.97);
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes fade-in {
|
||||
from {
|
||||
transform: scale(0.97);
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
to {
|
||||
transform: scale(1);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
`,
|
||||
}));
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ const ClassicOnboardingPage = memo(() => {
|
|||
|
||||
return (
|
||||
<OnboardingContainer>
|
||||
<Flexbox gap={24} style={{ maxWidth: 480, width: '100%' }}>
|
||||
<Flexbox gap={24} style={{ maxWidth: 600, width: '100%' }}>
|
||||
<ModeSwitch />
|
||||
{renderStep()}
|
||||
</Flexbox>
|
||||
|
|
|
|||
|
|
@ -2,14 +2,24 @@ export default {
|
|||
'agent.banner.label': 'Agent Onboarding',
|
||||
'agent.history.current': 'Current',
|
||||
'agent.history.title': 'History Topics',
|
||||
'agent.layout.mode.agent': 'agent mode',
|
||||
'agent.layout.mode.classic': 'classic mode',
|
||||
'agent.layout.skip': 'skip this step',
|
||||
'agent.layout.skipConfirm.content':
|
||||
'Leaving already? I could help personalize things for you in seconds.',
|
||||
'agent.layout.skipConfirm.ok': 'Skip for now',
|
||||
'agent.layout.skipConfirm.title': 'Skip onboarding for now?',
|
||||
'agent.layout.switchMessage':
|
||||
'Not feeling it today? You can switch to <modeLink><modeText>{{mode}}</modeText></modeLink> or <skipLink><skipText>{{skip}}</skipText></skipLink>.',
|
||||
'agent.modeSwitch.agent': 'Conversational',
|
||||
'agent.modeSwitch.classic': 'Classic',
|
||||
'agent.modeSwitch.debug': 'Debug Export',
|
||||
'agent.modeSwitch.label': 'Choose your onboarding mode',
|
||||
'agent.skipOnboarding': 'Skip onboarding',
|
||||
'agent.completionTitle': "You're All Set!",
|
||||
'agent.completionSubtitle': 'Your assistant is configured and ready to go.',
|
||||
'agent.enterApp': 'Enter App',
|
||||
'agent.completionTitle': 'You are almost there',
|
||||
'agent.completionSubtitle': "Everything's in place - let's get started when you're ready.",
|
||||
'agent.completion.sentence.readyWhenYouAre': 'Ready when you are :)',
|
||||
'agent.completion.sentence.readyWithName': "{{name}} here - I'm ready!",
|
||||
'agent.enterApp': "I'm ready",
|
||||
'agent.modeSwitch.reset': 'Reset Flow',
|
||||
'agent.progress': '{{currentStep}}/{{totalSteps}}',
|
||||
'agent.stage.agentIdentity': 'Agent Identity',
|
||||
|
|
@ -24,6 +34,19 @@ export default {
|
|||
'agent.summaryHint': 'Finish here if the setup summary looks right.',
|
||||
'agent.welcome':
|
||||
"...hm? I just woke up — my mind's a blank. Who are you? And — what should I be called? I need a name too.",
|
||||
'agent.welcome.guide.growTogether.desc':
|
||||
"With each chat, I'll understand you better and become a stronger teammate over time.",
|
||||
'agent.welcome.guide.growTogether.title': 'Grow with You',
|
||||
'agent.welcome.guide.knowYou.desc':
|
||||
"What's on your plate these days? A little context helps me support you better.",
|
||||
'agent.welcome.guide.knowYou.title': 'Get to Know You',
|
||||
'agent.welcome.guide.name.desc': 'Give me a name so this feels more personal from the start.',
|
||||
'agent.welcome.guide.name.title': 'Name Me',
|
||||
'agent.welcome.sentence.1': 'So nice to meet you! Let’s get to know each other.',
|
||||
'agent.welcome.sentence.2': 'What kind of partner do you want me to be?',
|
||||
'agent.welcome.sentence.3': 'First, give me a name :)',
|
||||
'agent.welcome.footer':
|
||||
'Configure your Lobe AI Agent. It lives on your server, learns from every interaction, and becomes more powerful the longer it runs.',
|
||||
'agent.greeting.prompt': 'Give me a name, a vibe, and an emoji',
|
||||
'agent.greeting.nameLabel': 'Name',
|
||||
'agent.greeting.namePlaceholder': 'e.g. Lumi, Atlas, Neko...',
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import { type UserCredSummary } from '@lobechat/types';
|
|||
import { CopyButton, Flexbox } from '@lobehub/ui';
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import { Alert, Descriptions, Modal, Skeleton, Typography } from 'antd';
|
||||
import { createStyles } from 'antd-style';
|
||||
import { createStaticStyles, cx } from 'antd-style';
|
||||
import { Eye, EyeOff } from 'lucide-react';
|
||||
import { type FC, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
|
@ -13,24 +13,24 @@ import { lambdaClient } from '@/libs/trpc/client';
|
|||
|
||||
const { Text } = Typography;
|
||||
|
||||
const useStyles = createStyles(({ css, token }) => ({
|
||||
const styles = createStaticStyles(({ css, cssVar }) => ({
|
||||
kvKey: css`
|
||||
min-width: 140px;
|
||||
padding-block: 8px;
|
||||
padding-inline: 12px;
|
||||
border-radius: ${token.borderRadius}px 0 0 ${token.borderRadius}px;
|
||||
border-radius: ${cssVar.borderRadius} 0 0 ${cssVar.borderRadius};
|
||||
|
||||
font-family: ${token.fontFamilyCode};
|
||||
font-family: ${cssVar.fontFamilyCode};
|
||||
font-size: 13px;
|
||||
color: ${token.colorTextSecondary};
|
||||
color: ${cssVar.colorTextSecondary};
|
||||
|
||||
background: ${token.colorFillQuaternary};
|
||||
background: ${cssVar.colorFillQuaternary};
|
||||
`,
|
||||
kvRow: css`
|
||||
display: flex;
|
||||
align-items: stretch;
|
||||
border: 1px solid ${token.colorBorderSecondary};
|
||||
border-radius: ${token.borderRadius}px;
|
||||
border: 1px solid ${cssVar.colorBorderSecondary};
|
||||
border-radius: ${cssVar.borderRadius};
|
||||
|
||||
&:not(:last-child) {
|
||||
margin-block-end: 8px;
|
||||
|
|
@ -45,15 +45,15 @@ const useStyles = createStyles(({ css, token }) => ({
|
|||
|
||||
padding-block: 8px;
|
||||
padding-inline: 12px;
|
||||
border-radius: 0 ${token.borderRadius}px ${token.borderRadius}px 0;
|
||||
border-radius: 0 ${cssVar.borderRadius} ${cssVar.borderRadius} 0;
|
||||
|
||||
font-family: ${token.fontFamilyCode};
|
||||
font-family: ${cssVar.fontFamilyCode};
|
||||
font-size: 13px;
|
||||
|
||||
background: ${token.colorBgContainer};
|
||||
background: ${cssVar.colorBgContainer};
|
||||
`,
|
||||
maskedValue: css`
|
||||
color: ${token.colorTextQuaternary};
|
||||
color: ${cssVar.colorTextQuaternary};
|
||||
letter-spacing: 2px;
|
||||
`,
|
||||
toggleBtn: css`
|
||||
|
|
@ -64,15 +64,15 @@ const useStyles = createStyles(({ css, token }) => ({
|
|||
justify-content: center;
|
||||
|
||||
padding: 4px;
|
||||
border-radius: ${token.borderRadiusSM}px;
|
||||
border-radius: ${cssVar.borderRadiusSM};
|
||||
|
||||
color: ${token.colorTextTertiary};
|
||||
color: ${cssVar.colorTextTertiary};
|
||||
|
||||
transition: all 0.2s;
|
||||
|
||||
&:hover {
|
||||
color: ${token.colorText};
|
||||
background: ${token.colorFillSecondary};
|
||||
color: ${cssVar.colorText};
|
||||
background: ${cssVar.colorFillSecondary};
|
||||
}
|
||||
`,
|
||||
valuesSection: css`
|
||||
|
|
@ -96,7 +96,6 @@ interface KVRowProps {
|
|||
}
|
||||
|
||||
const KVRow: FC<KVRowProps> = ({ keyName, value }) => {
|
||||
const { styles, cx } = useStyles();
|
||||
const [visible, setVisible] = useState(false);
|
||||
|
||||
return (
|
||||
|
|
@ -133,7 +132,6 @@ interface ViewCredModalProps {
|
|||
|
||||
const ViewCredModal: FC<ViewCredModalProps> = ({ cred, open, onClose }) => {
|
||||
const { t } = useTranslation('setting');
|
||||
const { styles } = useStyles();
|
||||
|
||||
const { data, isLoading, error } = useQuery({
|
||||
enabled: open && !!cred,
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import { render, screen } from '@testing-library/react';
|
||||
import { type ReactNode } from 'react';
|
||||
import { MemoryRouter } from 'react-router-dom';
|
||||
import { describe, expect, it, vi } from 'vitest';
|
||||
|
||||
|
|
@ -16,6 +17,34 @@ vi.mock('@/hooks/useIsDark', () => ({
|
|||
useIsDark: () => false,
|
||||
}));
|
||||
|
||||
vi.mock('react-i18next', () => ({
|
||||
Trans: ({
|
||||
components,
|
||||
values,
|
||||
}: {
|
||||
components: Record<string, ReactNode>;
|
||||
values?: { mode?: string; skip?: string };
|
||||
}) => {
|
||||
const modeText = values?.mode ?? '';
|
||||
const skipText = values?.skip ?? '';
|
||||
|
||||
return (
|
||||
<>
|
||||
{'Not feeling it today? You can switch to '}
|
||||
{components.modeLink}
|
||||
{' or '}
|
||||
{components.skipLink}
|
||||
{'.'}
|
||||
<span style={{ display: 'none' }}>{modeText}</span>
|
||||
<span style={{ display: 'none' }}>{skipText}</span>
|
||||
</>
|
||||
);
|
||||
},
|
||||
useTranslation: () => ({
|
||||
t: (key: string) => key,
|
||||
}),
|
||||
}));
|
||||
|
||||
describe('OnBoardingContainer', () => {
|
||||
it('renders onboarding content without footer copyright', () => {
|
||||
render(
|
||||
|
|
@ -42,6 +71,6 @@ describe('OnBoardingContainer', () => {
|
|||
</MemoryRouter>,
|
||||
);
|
||||
|
||||
expect(screen.getByRole('button', { name: 'agent.skipOnboarding' })).toBeInTheDocument();
|
||||
expect(screen.getByText('agent.layout.skip')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
'use client';
|
||||
|
||||
import { Button, Center, Flexbox } from '@lobehub/ui';
|
||||
import { Divider } from 'antd';
|
||||
import { Center, Flexbox, FluentEmoji, Text } from '@lobehub/ui';
|
||||
import { Divider, Popconfirm } from 'antd';
|
||||
import { cx, useTheme } from 'antd-style';
|
||||
import { type FC, type PropsWithChildren, useCallback } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { type FC, type MouseEvent, type PropsWithChildren, useCallback } from 'react';
|
||||
import { Trans, useTranslation } from 'react-i18next';
|
||||
import { useLocation, useNavigate } from 'react-router-dom';
|
||||
|
||||
import { ProductLogo } from '@/components/Branding';
|
||||
|
|
@ -18,17 +18,26 @@ import { styles } from './style';
|
|||
const OnBoardingContainer: FC<PropsWithChildren> = ({ children }) => {
|
||||
const isDarkMode = useIsDark();
|
||||
const theme = useTheme();
|
||||
const { t } = useTranslation('onboarding');
|
||||
const { t } = useTranslation(['onboarding', 'common']);
|
||||
const { pathname } = useLocation();
|
||||
const navigate = useNavigate();
|
||||
const finishOnboarding = useUserStore((s) => s.finishOnboarding);
|
||||
const isAgentOnboarding = pathname.startsWith('/onboarding/agent');
|
||||
|
||||
const handleSkip = useCallback(() => {
|
||||
const handleConfirmSkip = useCallback(() => {
|
||||
finishOnboarding();
|
||||
navigate('/');
|
||||
}, [finishOnboarding, navigate]);
|
||||
|
||||
const swichMode = useCallback(
|
||||
(e: MouseEvent) => {
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
navigate(isAgentOnboarding ? '/onboarding/classic' : '/onboarding/agent');
|
||||
},
|
||||
[isAgentOnboarding, navigate],
|
||||
);
|
||||
|
||||
return (
|
||||
<Flexbox className={styles.outerContainer} height={'100%'} padding={8} width={'100%'}>
|
||||
<Flexbox
|
||||
|
|
@ -51,16 +60,61 @@ const OnBoardingContainer: FC<PropsWithChildren> = ({ children }) => {
|
|||
<Divider className={styles.divider} orientation={'vertical'} />
|
||||
<ThemeButton placement={'bottomRight'} size={18} />
|
||||
</Flexbox>
|
||||
{isAgentOnboarding ? (
|
||||
<Button size={'small'} type={'text'} onClick={handleSkip}>
|
||||
{t('agent.skipOnboarding')}
|
||||
</Button>
|
||||
) : null}
|
||||
</Flexbox>
|
||||
</Flexbox>
|
||||
<Center height={'100%'} width={'100%'}>
|
||||
{children}
|
||||
</Center>
|
||||
<Center paddingBlock={'0 8px'} paddingInline={16}>
|
||||
<Text fontSize={12} type={'secondary'}>
|
||||
<Trans
|
||||
i18nKey={'agent.layout.switchMessage'}
|
||||
ns={'onboarding'}
|
||||
components={{
|
||||
modeLink: (
|
||||
<a
|
||||
href={isAgentOnboarding ? '/onboarding/classic' : '/onboarding/agent'}
|
||||
onClick={swichMode}
|
||||
/>
|
||||
),
|
||||
modeText: <Text as={'span'} />,
|
||||
skipLink: (
|
||||
<Popconfirm
|
||||
arrow={false}
|
||||
cancelButtonProps={{ type: 'text' }}
|
||||
cancelText={t('cancel', { ns: 'common' })}
|
||||
okText={t('agent.layout.skipConfirm.ok', { ns: 'onboarding' })}
|
||||
style={{ cursor: 'pointer' }}
|
||||
description={
|
||||
<Text fontSize={13} style={{ marginBottom: 8 }} type={'secondary'}>
|
||||
{t('agent.layout.skipConfirm.content', { ns: 'onboarding' })}
|
||||
</Text>
|
||||
}
|
||||
icon={
|
||||
<FluentEmoji
|
||||
emoji={'😗'}
|
||||
size={24}
|
||||
style={{ marginRight: 8 }}
|
||||
type={'anim'}
|
||||
/>
|
||||
}
|
||||
title={
|
||||
<Text fontSize={15}>{t('agent.completionTitle', { ns: 'onboarding' })}</Text>
|
||||
}
|
||||
onConfirm={handleConfirmSkip}
|
||||
/>
|
||||
),
|
||||
skipText: <Text as={'span'} style={{ cursor: 'pointer' }} />,
|
||||
}}
|
||||
values={{
|
||||
mode: isAgentOnboarding
|
||||
? t('agent.layout.mode.classic')
|
||||
: t('agent.layout.mode.agent'),
|
||||
skip: t('agent.layout.skip'),
|
||||
}}
|
||||
/>
|
||||
</Text>
|
||||
</Center>
|
||||
</Flexbox>
|
||||
</Flexbox>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { type FlexboxProps } from '@lobehub/ui';
|
||||
import { Avatar, type FlexboxProps } from '@lobehub/ui';
|
||||
import { Flexbox, Text } from '@lobehub/ui';
|
||||
import { type TypewriterEffectProps } from '@lobehub/ui/awesome';
|
||||
import { TypewriterEffect } from '@lobehub/ui/awesome';
|
||||
|
|
@ -9,32 +9,41 @@ import { useTranslation } from 'react-i18next';
|
|||
import { ProductLogo } from '@/components/Branding';
|
||||
|
||||
interface LobeMessageProps extends Omit<FlexboxProps, 'children'> {
|
||||
avatar?: string;
|
||||
avatarSize?: number;
|
||||
fontSize?: number;
|
||||
gap?: number;
|
||||
sentences: TypewriterEffectProps['sentences'];
|
||||
}
|
||||
|
||||
const LobeMessage = memo<LobeMessageProps>(({ sentences, fontSize = 24, ...rest }) => {
|
||||
const { i18n } = useTranslation();
|
||||
const locale = i18n.language;
|
||||
const LobeMessage = memo<LobeMessageProps>(
|
||||
({ gap = 8, avatar, avatarSize, sentences, fontSize = 24, ...rest }) => {
|
||||
const { i18n } = useTranslation();
|
||||
const locale = i18n.language;
|
||||
|
||||
return (
|
||||
<Flexbox gap={8} {...rest}>
|
||||
<ProductLogo size={fontSize * 2} />
|
||||
<Text as={'h1'} fontSize={fontSize} weight={'bold'}>
|
||||
<TypewriterEffect
|
||||
cursorCharacter={<LoadingDots size={fontSize} variant={'pulse'} />}
|
||||
cursorFade={false}
|
||||
deletePauseDuration={1000}
|
||||
deletingSpeed={32}
|
||||
hideCursorWhileTyping={'afterTyping'}
|
||||
key={locale}
|
||||
pauseDuration={16_000}
|
||||
sentences={sentences}
|
||||
typingSpeed={64}
|
||||
/>
|
||||
</Text>
|
||||
</Flexbox>
|
||||
);
|
||||
});
|
||||
return (
|
||||
<Flexbox gap={gap} {...rest}>
|
||||
{avatar ? (
|
||||
<Avatar avatar={avatar} size={avatarSize || fontSize * 2} />
|
||||
) : (
|
||||
<ProductLogo size={avatarSize || fontSize * 2} />
|
||||
)}
|
||||
<Text as={'h1'} fontSize={fontSize} weight={'bold'}>
|
||||
<TypewriterEffect
|
||||
cursorCharacter={<LoadingDots size={fontSize} variant={'pulse'} />}
|
||||
cursorFade={false}
|
||||
deletePauseDuration={1000}
|
||||
deletingSpeed={16}
|
||||
hideCursorWhileTyping={'afterTyping'}
|
||||
key={locale}
|
||||
pauseDuration={16_000}
|
||||
sentences={sentences}
|
||||
typingSpeed={32}
|
||||
/>
|
||||
</Text>
|
||||
</Flexbox>
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
export default LobeMessage;
|
||||
|
|
|
|||
Loading…
Reference in a new issue