@ihazz/bitrix24 1.1.7 → 1.1.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/i18n.ts CHANGED
@@ -10,6 +10,8 @@ export function resolveLocale(lang: string | undefined): string {
10
10
  return (lang ?? 'en').toLowerCase().slice(0, 2);
11
11
  }
12
12
 
13
+ const SUPPORTED_LOCALES = ['en', 'ru', 'de', 'es', 'fr', 'pt'] as const;
14
+
13
15
  function resolve<T>(dict: Record<string, T>, lang: string | undefined): T {
14
16
  const code = resolveLocale(lang);
15
17
  return dict[code] ?? dict.en;
@@ -216,6 +218,436 @@ export function onboardingMessage(
216
218
  : welcomeMessage(lang, botName);
217
219
  }
218
220
 
221
+ export type CommandGroup = 'status' | 'session' | 'options' | 'management' | 'tools' | 'export';
222
+
223
+ type CommandText = {
224
+ description: string;
225
+ params?: string;
226
+ };
227
+
228
+ type CommandTextMap = Record<string, CommandText>;
229
+
230
+ interface CommandHelpTextLabels {
231
+ conciseHeader: string;
232
+ fullHeader: string;
233
+ fullListLabel: string;
234
+ paramsLabel: string;
235
+ }
236
+
237
+ interface ModelsCommandReplyLabels {
238
+ header: string;
239
+ showProviderModels: string;
240
+ switchModel: string;
241
+ }
242
+
243
+ interface NewSessionReplyTexts {
244
+ started: string;
245
+ active: string;
246
+ }
247
+
248
+ const I18N_COMMAND_GROUP_LABELS: Record<string, Record<CommandGroup, string>> = {
249
+ en: {
250
+ status: 'Help and status',
251
+ session: 'Session',
252
+ options: 'Options',
253
+ management: 'Management',
254
+ tools: 'Tools',
255
+ export: 'Export',
256
+ },
257
+ ru: {
258
+ status: 'Справка и статус',
259
+ session: 'Сессия',
260
+ options: 'Параметры',
261
+ management: 'Управление',
262
+ tools: 'Инструменты',
263
+ export: 'Экспорт',
264
+ },
265
+ de: {
266
+ status: 'Hilfe und Status',
267
+ session: 'Sitzung',
268
+ options: 'Optionen',
269
+ management: 'Verwaltung',
270
+ tools: 'Werkzeuge',
271
+ export: 'Export',
272
+ },
273
+ es: {
274
+ status: 'Ayuda y estado',
275
+ session: 'Sesion',
276
+ options: 'Opciones',
277
+ management: 'Administracion',
278
+ tools: 'Herramientas',
279
+ export: 'Exportacion',
280
+ },
281
+ fr: {
282
+ status: 'Aide et statut',
283
+ session: 'Session',
284
+ options: 'Options',
285
+ management: 'Gestion',
286
+ tools: 'Outils',
287
+ export: 'Export',
288
+ },
289
+ pt: {
290
+ status: 'Ajuda e status',
291
+ session: 'Sessao',
292
+ options: 'Opcoes',
293
+ management: 'Gerenciamento',
294
+ tools: 'Ferramentas',
295
+ export: 'Exportacao',
296
+ },
297
+ };
298
+
299
+ const I18N_COMMAND_HELP_TEXT_LABELS: Record<string, CommandHelpTextLabels> = {
300
+ en: {
301
+ conciseHeader: 'Key commands',
302
+ fullHeader: 'Available commands',
303
+ fullListLabel: 'Full list',
304
+ paramsLabel: 'Params',
305
+ },
306
+ ru: {
307
+ conciseHeader: 'Основные команды',
308
+ fullHeader: 'Доступные команды',
309
+ fullListLabel: 'Полный список',
310
+ paramsLabel: 'Параметры',
311
+ },
312
+ de: {
313
+ conciseHeader: 'Wichtige Befehle',
314
+ fullHeader: 'Verfuegbare Befehle',
315
+ fullListLabel: 'Vollstaendige Liste',
316
+ paramsLabel: 'Parameter',
317
+ },
318
+ es: {
319
+ conciseHeader: 'Comandos clave',
320
+ fullHeader: 'Comandos disponibles',
321
+ fullListLabel: 'Lista completa',
322
+ paramsLabel: 'Parametros',
323
+ },
324
+ fr: {
325
+ conciseHeader: 'Commandes principales',
326
+ fullHeader: 'Commandes disponibles',
327
+ fullListLabel: 'Liste complete',
328
+ paramsLabel: 'Parametres',
329
+ },
330
+ pt: {
331
+ conciseHeader: 'Comandos principais',
332
+ fullHeader: 'Comandos disponiveis',
333
+ fullListLabel: 'Lista completa',
334
+ paramsLabel: 'Parametros',
335
+ },
336
+ };
337
+
338
+ const I18N_COMMAND_TEXTS: Record<string, CommandTextMap> = {
339
+ en: {
340
+ help: { description: 'Show available commands' },
341
+ commands: { description: 'List all slash commands' },
342
+ status: { description: 'Show current status' },
343
+ context: { description: 'Explain how context is built' },
344
+ whoami: { description: 'Show your sender ID' },
345
+ usage: { description: 'Usage and cost summary', params: 'off | tokens | full | cost' },
346
+ new: { description: 'Start a new session' },
347
+ reset: { description: 'Reset the current session' },
348
+ stop: { description: 'Stop the current run' },
349
+ compact: { description: 'Compact the session context', params: 'instructions' },
350
+ session: { description: 'Manage session settings', params: 'ttl | ...' },
351
+ model: { description: 'Show or set the model', params: 'model name' },
352
+ models: { description: 'List available models', params: 'provider' },
353
+ think: { description: 'Set thinking level', params: 'off | low | medium | high' },
354
+ verbose: { description: 'Toggle verbose mode', params: 'on | off' },
355
+ reasoning: { description: 'Toggle reasoning visibility', params: 'on | off | stream' },
356
+ elevated: { description: 'Toggle elevated mode', params: 'on | off | ask | full' },
357
+ exec: { description: 'Set exec defaults', params: 'host | security | ask | node' },
358
+ queue: { description: 'Adjust queue settings', params: 'mode | debounce | cap | drop' },
359
+ config: { description: 'Show or set config values', params: 'show | get | set | unset' },
360
+ debug: { description: 'Set runtime debug overrides', params: 'show | reset | set | unset' },
361
+ approve: { description: 'Approve or deny exec requests' },
362
+ activation: { description: 'Set group activation mode', params: 'mention | always' },
363
+ send: { description: 'Set send policy', params: 'on | off | inherit' },
364
+ subagents: { description: 'Manage subagent runs' },
365
+ kill: { description: 'Kill a running subagent', params: 'id | all' },
366
+ steer: { description: 'Send guidance to a subagent', params: 'message' },
367
+ skill: { description: 'Run a skill by name', params: 'name' },
368
+ restart: { description: 'Restart OpenClaw' },
369
+ 'export-session': { description: 'Export session to HTML' },
370
+ },
371
+ ru: {
372
+ help: { description: 'Показать доступные команды' },
373
+ commands: { description: 'Показать все команды' },
374
+ status: { description: 'Показать текущий статус' },
375
+ context: { description: 'Объяснить, как формируется контекст' },
376
+ whoami: { description: 'Показать ваш ID' },
377
+ usage: { description: 'Использование и стоимость', params: 'off | tokens | full | cost' },
378
+ new: { description: 'Начать новую сессию' },
379
+ reset: { description: 'Сбросить текущую сессию' },
380
+ stop: { description: 'Остановить текущий запуск' },
381
+ compact: { description: 'Сжать контекст сессии', params: 'instructions' },
382
+ session: { description: 'Настройки сессии', params: 'ttl | ...' },
383
+ model: { description: 'Показать или сменить модель', params: 'model name' },
384
+ models: { description: 'Показать модели', params: 'provider' },
385
+ think: { description: 'Уровень размышлений', params: 'off | low | medium | high' },
386
+ verbose: { description: 'Подробный режим', params: 'on | off' },
387
+ reasoning: { description: 'Видимость рассуждений', params: 'on | off | stream' },
388
+ elevated: { description: 'Режим с расширенными правами', params: 'on | off | ask | full' },
389
+ exec: { description: 'Настройки выполнения', params: 'host | security | ask | node' },
390
+ queue: { description: 'Настройки очереди', params: 'mode | debounce | cap | drop' },
391
+ config: { description: 'Показать или изменить конфигурацию', params: 'show | get | set | unset' },
392
+ debug: { description: 'Отладочные настройки', params: 'show | reset | set | unset' },
393
+ approve: { description: 'Одобрить или отклонить запросы' },
394
+ activation: { description: 'Режим активации в группах', params: 'mention | always' },
395
+ send: { description: 'Политика отправки', params: 'on | off | inherit' },
396
+ subagents: { description: 'Управление субагентами' },
397
+ kill: { description: 'Остановить субагента', params: 'id | all' },
398
+ steer: { description: 'Направить субагента', params: 'message' },
399
+ skill: { description: 'Запустить навык', params: 'name' },
400
+ restart: { description: 'Перезапустить OpenClaw' },
401
+ 'export-session': { description: 'Экспорт сессии в HTML' },
402
+ },
403
+ de: {
404
+ help: { description: 'Verfuegbare Befehle anzeigen' },
405
+ commands: { description: 'Alle Slash-Befehle auflisten' },
406
+ status: { description: 'Aktuellen Status anzeigen' },
407
+ context: { description: 'Erklaeren, wie der Kontext aufgebaut wird' },
408
+ whoami: { description: 'Ihre Sender-ID anzeigen' },
409
+ usage: { description: 'Nutzung und Kostenuebersicht', params: 'off | tokens | full | cost' },
410
+ new: { description: 'Neue Sitzung starten' },
411
+ reset: { description: 'Aktuelle Sitzung zuruecksetzen' },
412
+ stop: { description: 'Aktuellen Lauf stoppen' },
413
+ compact: { description: 'Sitzungskontext komprimieren', params: 'instructions' },
414
+ session: { description: 'Sitzungseinstellungen verwalten', params: 'ttl | ...' },
415
+ model: { description: 'Modell anzeigen oder festlegen', params: 'Modellname' },
416
+ models: { description: 'Verfuegbare Modelle auflisten', params: 'Anbieter' },
417
+ think: { description: 'Denkstufe festlegen', params: 'off | low | medium | high' },
418
+ verbose: { description: 'Ausfuehrlichen Modus umschalten', params: 'on | off' },
419
+ reasoning: { description: 'Sichtbarkeit des Reasonings umschalten', params: 'on | off | stream' },
420
+ elevated: { description: 'Erweiterten Modus umschalten', params: 'on | off | ask | full' },
421
+ exec: { description: 'Exec-Standards festlegen', params: 'host | security | ask | node' },
422
+ queue: { description: 'Warteschlangeneinstellungen anpassen', params: 'mode | debounce | cap | drop' },
423
+ config: { description: 'Konfigurationswerte anzeigen oder setzen', params: 'show | get | set | unset' },
424
+ debug: { description: 'Debug-Ueberschreibungen festlegen', params: 'show | reset | set | unset' },
425
+ approve: { description: 'Exec-Anfragen genehmigen oder ablehnen' },
426
+ activation: { description: 'Gruppenaktivierungsmodus festlegen', params: 'mention | always' },
427
+ send: { description: 'Sendeverhalten festlegen', params: 'on | off | inherit' },
428
+ subagents: { description: 'Subagent-Laeufe verwalten' },
429
+ kill: { description: 'Laufenden Subagenten beenden', params: 'id | all' },
430
+ steer: { description: 'Hinweise an einen Subagenten senden', params: 'Nachricht' },
431
+ skill: { description: 'Skill nach Namen ausfuehren', params: 'Name' },
432
+ restart: { description: 'OpenClaw neu starten' },
433
+ 'export-session': { description: 'Sitzung nach HTML exportieren' },
434
+ },
435
+ es: {
436
+ help: { description: 'Mostrar comandos disponibles' },
437
+ commands: { description: 'Listar todos los comandos con barra' },
438
+ status: { description: 'Mostrar el estado actual' },
439
+ context: { description: 'Explicar como se construye el contexto' },
440
+ whoami: { description: 'Mostrar su ID de remitente' },
441
+ usage: { description: 'Resumen de uso y costo', params: 'off | tokens | full | cost' },
442
+ new: { description: 'Iniciar una nueva sesion' },
443
+ reset: { description: 'Restablecer la sesion actual' },
444
+ stop: { description: 'Detener la ejecucion actual' },
445
+ compact: { description: 'Compactar el contexto de la sesion', params: 'instructions' },
446
+ session: { description: 'Gestionar la configuracion de la sesion', params: 'ttl | ...' },
447
+ model: { description: 'Mostrar o cambiar el modelo', params: 'nombre del modelo' },
448
+ models: { description: 'Listar modelos disponibles', params: 'proveedor' },
449
+ think: { description: 'Definir el nivel de razonamiento', params: 'off | low | medium | high' },
450
+ verbose: { description: 'Alternar el modo detallado', params: 'on | off' },
451
+ reasoning: { description: 'Alternar la visibilidad del razonamiento', params: 'on | off | stream' },
452
+ elevated: { description: 'Alternar el modo elevado', params: 'on | off | ask | full' },
453
+ exec: { description: 'Definir valores predeterminados de exec', params: 'host | security | ask | node' },
454
+ queue: { description: 'Ajustar la configuracion de la cola', params: 'mode | debounce | cap | drop' },
455
+ config: { description: 'Mostrar o establecer valores de configuracion', params: 'show | get | set | unset' },
456
+ debug: { description: 'Definir anulaciones de depuracion', params: 'show | reset | set | unset' },
457
+ approve: { description: 'Aprobar o rechazar solicitudes de exec' },
458
+ activation: { description: 'Definir el modo de activacion en grupos', params: 'mention | always' },
459
+ send: { description: 'Definir la politica de envio', params: 'on | off | inherit' },
460
+ subagents: { description: 'Gestionar ejecuciones de subagentes' },
461
+ kill: { description: 'Finalizar un subagente en ejecucion', params: 'id | all' },
462
+ steer: { description: 'Enviar instrucciones a un subagente', params: 'mensaje' },
463
+ skill: { description: 'Ejecutar una habilidad por nombre', params: 'nombre' },
464
+ restart: { description: 'Reiniciar OpenClaw' },
465
+ 'export-session': { description: 'Exportar la sesion a HTML' },
466
+ },
467
+ fr: {
468
+ help: { description: 'Afficher les commandes disponibles' },
469
+ commands: { description: 'Lister toutes les commandes slash' },
470
+ status: { description: 'Afficher le statut actuel' },
471
+ context: { description: 'Expliquer comment le contexte est construit' },
472
+ whoami: { description: 'Afficher votre identifiant expediteur' },
473
+ usage: { description: 'Resume de l utilisation et du cout', params: 'off | tokens | full | cost' },
474
+ new: { description: 'Demarrer une nouvelle session' },
475
+ reset: { description: 'Reinitialiser la session actuelle' },
476
+ stop: { description: 'Arreter l execution en cours' },
477
+ compact: { description: 'Compacter le contexte de la session', params: 'instructions' },
478
+ session: { description: 'Gerer les parametres de session', params: 'ttl | ...' },
479
+ model: { description: 'Afficher ou definir le modele', params: 'nom du modele' },
480
+ models: { description: 'Lister les modeles disponibles', params: 'fournisseur' },
481
+ think: { description: 'Definir le niveau de reflexion', params: 'off | low | medium | high' },
482
+ verbose: { description: 'Activer ou desactiver le mode verbeux', params: 'on | off' },
483
+ reasoning: { description: 'Afficher ou masquer le raisonnement', params: 'on | off | stream' },
484
+ elevated: { description: 'Activer ou desactiver le mode eleve', params: 'on | off | ask | full' },
485
+ exec: { description: 'Definir les valeurs exec par defaut', params: 'host | security | ask | node' },
486
+ queue: { description: 'Ajuster les parametres de file', params: 'mode | debounce | cap | drop' },
487
+ config: { description: 'Afficher ou definir les valeurs de configuration', params: 'show | get | set | unset' },
488
+ debug: { description: 'Definir les surcharges de debug', params: 'show | reset | set | unset' },
489
+ approve: { description: 'Approuver ou refuser les demandes exec' },
490
+ activation: { description: 'Definir le mode d activation en groupe', params: 'mention | always' },
491
+ send: { description: 'Definir la politique d envoi', params: 'on | off | inherit' },
492
+ subagents: { description: 'Gerer les executions de sous-agents' },
493
+ kill: { description: 'Arreter un sous-agent en cours', params: 'id | all' },
494
+ steer: { description: 'Envoyer des instructions a un sous-agent', params: 'message' },
495
+ skill: { description: 'Executer une competence par nom', params: 'nom' },
496
+ restart: { description: 'Redemarrer OpenClaw' },
497
+ 'export-session': { description: 'Exporter la session en HTML' },
498
+ },
499
+ pt: {
500
+ help: { description: 'Mostrar comandos disponiveis' },
501
+ commands: { description: 'Listar todos os comandos com barra' },
502
+ status: { description: 'Mostrar o status atual' },
503
+ context: { description: 'Explicar como o contexto e montado' },
504
+ whoami: { description: 'Mostrar seu ID de remetente' },
505
+ usage: { description: 'Resumo de uso e custo', params: 'off | tokens | full | cost' },
506
+ new: { description: 'Iniciar uma nova sessao' },
507
+ reset: { description: 'Redefinir a sessao atual' },
508
+ stop: { description: 'Parar a execucao atual' },
509
+ compact: { description: 'Compactar o contexto da sessao', params: 'instructions' },
510
+ session: { description: 'Gerenciar configuracoes da sessao', params: 'ttl | ...' },
511
+ model: { description: 'Mostrar ou definir o modelo', params: 'nome do modelo' },
512
+ models: { description: 'Listar modelos disponiveis', params: 'provedor' },
513
+ think: { description: 'Definir nivel de raciocinio', params: 'off | low | medium | high' },
514
+ verbose: { description: 'Alternar modo detalhado', params: 'on | off' },
515
+ reasoning: { description: 'Alternar visibilidade do raciocinio', params: 'on | off | stream' },
516
+ elevated: { description: 'Alternar modo elevado', params: 'on | off | ask | full' },
517
+ exec: { description: 'Definir padroes de exec', params: 'host | security | ask | node' },
518
+ queue: { description: 'Ajustar configuracoes da fila', params: 'mode | debounce | cap | drop' },
519
+ config: { description: 'Mostrar ou definir valores de configuracao', params: 'show | get | set | unset' },
520
+ debug: { description: 'Definir sobrescritas de debug', params: 'show | reset | set | unset' },
521
+ approve: { description: 'Aprovar ou recusar solicitacoes de exec' },
522
+ activation: { description: 'Definir modo de ativacao em grupos', params: 'mention | always' },
523
+ send: { description: 'Definir politica de envio', params: 'on | off | inherit' },
524
+ subagents: { description: 'Gerenciar execucoes de subagentes' },
525
+ kill: { description: 'Encerrar um subagente em execucao', params: 'id | all' },
526
+ steer: { description: 'Enviar orientacao para um subagente', params: 'mensagem' },
527
+ skill: { description: 'Executar uma habilidade pelo nome', params: 'nome' },
528
+ restart: { description: 'Reiniciar OpenClaw' },
529
+ 'export-session': { description: 'Exportar a sessao para HTML' },
530
+ },
531
+ };
532
+
533
+ const I18N_MODELS_COMMAND_REPLY_LABELS: Record<string, ModelsCommandReplyLabels> = {
534
+ en: {
535
+ header: 'Providers',
536
+ showProviderModels: 'Show provider models',
537
+ switchModel: 'Switch model',
538
+ },
539
+ ru: {
540
+ header: 'Провайдеры',
541
+ showProviderModels: 'Модели провайдера',
542
+ switchModel: 'Сменить модель',
543
+ },
544
+ de: {
545
+ header: 'Anbieter',
546
+ showProviderModels: 'Anbietermodelle anzeigen',
547
+ switchModel: 'Modell wechseln',
548
+ },
549
+ es: {
550
+ header: 'Proveedores',
551
+ showProviderModels: 'Mostrar modelos del proveedor',
552
+ switchModel: 'Cambiar modelo',
553
+ },
554
+ fr: {
555
+ header: 'Fournisseurs',
556
+ showProviderModels: 'Afficher les modeles du fournisseur',
557
+ switchModel: 'Changer de modele',
558
+ },
559
+ pt: {
560
+ header: 'Provedores',
561
+ showProviderModels: 'Mostrar modelos do provedor',
562
+ switchModel: 'Trocar modelo',
563
+ },
564
+ };
565
+
566
+ const I18N_NEW_SESSION_REPLY_TEXTS: Record<string, NewSessionReplyTexts> = {
567
+ en: {
568
+ started: 'Started a new session.',
569
+ active: 'You are now in a new session.',
570
+ },
571
+ ru: {
572
+ started: 'Начата новая сессия.',
573
+ active: 'Теперь вы в новой сессии.',
574
+ },
575
+ de: {
576
+ started: 'Neue Sitzung gestartet.',
577
+ active: 'Sie sind jetzt in einer neuen Sitzung.',
578
+ },
579
+ es: {
580
+ started: 'Nueva sesion iniciada.',
581
+ active: 'Ahora esta en una nueva sesion.',
582
+ },
583
+ fr: {
584
+ started: 'Nouvelle session demarree.',
585
+ active: 'Vous etes maintenant dans une nouvelle session.',
586
+ },
587
+ pt: {
588
+ started: 'Nova sessao iniciada.',
589
+ active: 'Agora voce esta em uma nova sessao.',
590
+ },
591
+ };
592
+
593
+ function resolveCommandTextMap(lang: string | undefined): CommandTextMap {
594
+ return resolve(I18N_COMMAND_TEXTS, lang);
595
+ }
596
+
597
+ function resolveCommandText(command: string, lang: string | undefined): CommandText | undefined {
598
+ const localized = resolveCommandTextMap(lang)[command];
599
+ if (localized) {
600
+ return localized;
601
+ }
602
+
603
+ return I18N_COMMAND_TEXTS.en[command];
604
+ }
605
+
606
+ export function commandGroupLabel(lang: string | undefined, group: CommandGroup): string {
607
+ return resolve(I18N_COMMAND_GROUP_LABELS, lang)[group];
608
+ }
609
+
610
+ export function commandHelpTextLabels(lang: string | undefined): CommandHelpTextLabels {
611
+ return resolve(I18N_COMMAND_HELP_TEXT_LABELS, lang);
612
+ }
613
+
614
+ export function commandDescription(lang: string | undefined, command: string): string {
615
+ return resolveCommandText(command, lang)?.description ?? command;
616
+ }
617
+
618
+ export function commandParams(lang: string | undefined, command: string): string | undefined {
619
+ return resolveCommandText(command, lang)?.params;
620
+ }
621
+
622
+ export function commandRegistrationTitle(command: string): Record<string, string> {
623
+ return Object.fromEntries(
624
+ SUPPORTED_LOCALES.map((locale) => [
625
+ locale,
626
+ I18N_COMMAND_TEXTS[locale]?.[command]?.description ?? I18N_COMMAND_TEXTS.en[command]?.description ?? command,
627
+ ]),
628
+ );
629
+ }
630
+
631
+ export function commandRegistrationParams(command: string): Record<string, string> | undefined {
632
+ const entries = SUPPORTED_LOCALES
633
+ .map((locale) => [locale, I18N_COMMAND_TEXTS[locale]?.[command]?.params ?? I18N_COMMAND_TEXTS.en[command]?.params])
634
+ .filter((entry): entry is [string, string] => typeof entry[1] === 'string');
635
+
636
+ if (entries.length === 0) {
637
+ return undefined;
638
+ }
639
+
640
+ return Object.fromEntries(entries);
641
+ }
642
+
643
+ export function modelsCommandReplyLabels(lang: string | undefined): ModelsCommandReplyLabels {
644
+ return resolve(I18N_MODELS_COMMAND_REPLY_LABELS, lang);
645
+ }
646
+
647
+ export function newSessionReplyTexts(lang: string | undefined): NewSessionReplyTexts {
648
+ return resolve(I18N_NEW_SESSION_REPLY_TEXTS, lang);
649
+ }
650
+
219
651
  interface CommandKeyboardLabels {
220
652
  help: string;
221
653
  status: string;
@@ -224,6 +656,14 @@ interface CommandKeyboardLabels {
224
656
  models: string;
225
657
  }
226
658
 
659
+ interface WelcomeKeyboardLabels {
660
+ todayTasks: string;
661
+ stalledDeals: string;
662
+ help: string;
663
+ newSession: string;
664
+ commands: string;
665
+ }
666
+
227
667
  const I18N_COMMAND_KEYBOARD_LABELS: Record<string, CommandKeyboardLabels> = {
228
668
  en: {
229
669
  help: 'Help',
@@ -273,6 +713,55 @@ export function commandKeyboardLabels(lang: string | undefined): CommandKeyboard
273
713
  return resolve(I18N_COMMAND_KEYBOARD_LABELS, lang);
274
714
  }
275
715
 
716
+ const I18N_WELCOME_KEYBOARD_LABELS: Record<string, WelcomeKeyboardLabels> = {
717
+ en: {
718
+ todayTasks: "Today's tasks",
719
+ stalledDeals: 'Stalled deals',
720
+ help: 'Help',
721
+ newSession: 'New session',
722
+ commands: 'Commands',
723
+ },
724
+ ru: {
725
+ todayTasks: 'Задачи на сегодня',
726
+ stalledDeals: 'Зависшие сделки',
727
+ help: 'Помощь',
728
+ newSession: 'Новая сессия',
729
+ commands: 'Команды',
730
+ },
731
+ de: {
732
+ todayTasks: 'Heutige Aufgaben',
733
+ stalledDeals: 'Blockierte Deals',
734
+ help: 'Hilfe',
735
+ newSession: 'Neue Sitzung',
736
+ commands: 'Befehle',
737
+ },
738
+ es: {
739
+ todayTasks: 'Tareas de hoy',
740
+ stalledDeals: 'Negocios atascados',
741
+ help: 'Ayuda',
742
+ newSession: 'Nueva sesion',
743
+ commands: 'Comandos',
744
+ },
745
+ fr: {
746
+ todayTasks: 'Taches du jour',
747
+ stalledDeals: 'Affaires bloquees',
748
+ help: 'Aide',
749
+ newSession: 'Nouvelle session',
750
+ commands: 'Commandes',
751
+ },
752
+ pt: {
753
+ todayTasks: 'Tarefas de hoje',
754
+ stalledDeals: 'Negocios travados',
755
+ help: 'Ajuda',
756
+ newSession: 'Nova sessao',
757
+ commands: 'Comandos',
758
+ },
759
+ };
760
+
761
+ export function welcomeKeyboardLabels(lang: string | undefined): WelcomeKeyboardLabels {
762
+ return resolve(I18N_WELCOME_KEYBOARD_LABELS, lang);
763
+ }
764
+
276
765
  const I18N_REPLY_GENERATION_FAILED: Record<string, string> = {
277
766
  en: 'I could not prepare a final reply. Please try again. If your request needs web search or external tools, check that they are configured on the server.',
278
767
  ru: 'Не удалось подготовить итоговый ответ. Попробуйте повторить запрос. Если вопрос требует веб-поиска или внешних инструментов, проверьте, что они настроены на сервере.',
@@ -285,3 +774,26 @@ const I18N_REPLY_GENERATION_FAILED: Record<string, string> = {
285
774
  export function replyGenerationFailed(lang: string | undefined): string {
286
775
  return resolve(I18N_REPLY_GENERATION_FAILED, lang);
287
776
  }
777
+
778
+ export function normalizeNewSessionReply(lang: string | undefined, text: string): string | null {
779
+ const normalized = text.trim();
780
+ if (!normalized) {
781
+ return null;
782
+ }
783
+
784
+ const texts = resolve(I18N_NEW_SESSION_REPLY_TEXTS, lang);
785
+
786
+ if (/^(?:started|created|opened)(?: a)? new (?:chat|conversation|session)\.?$/i.test(normalized)) {
787
+ return texts.started;
788
+ }
789
+
790
+ if (/^you are now in a new (?:chat|conversation|session)\.?$/i.test(normalized)) {
791
+ return texts.active;
792
+ }
793
+
794
+ if (/^(?:hey|hi|hello)\b[\s\S]*\b(?:ready to dive in|ready to get started|ready to help)\b[\s\S]*\b(?:what would you like to work on today|what would you like to work on|how can i help(?: you)? today)\b[.!?]?$/i.test(normalized)) {
795
+ return texts.started;
796
+ }
797
+
798
+ return null;
799
+ }