zardbot-telegram 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (111) hide show
  1. package/.env.example +116 -0
  2. package/LICENSE +21 -0
  3. package/README.md +250 -0
  4. package/dist/agent/manager.js +88 -0
  5. package/dist/agent/types.js +26 -0
  6. package/dist/app/start-bot-app.js +49 -0
  7. package/dist/bot/commands/abort.js +121 -0
  8. package/dist/bot/commands/commands.js +480 -0
  9. package/dist/bot/commands/definitions.js +27 -0
  10. package/dist/bot/commands/help.js +10 -0
  11. package/dist/bot/commands/models.js +38 -0
  12. package/dist/bot/commands/new.js +70 -0
  13. package/dist/bot/commands/opencode-start.js +101 -0
  14. package/dist/bot/commands/opencode-stop.js +44 -0
  15. package/dist/bot/commands/projects.js +223 -0
  16. package/dist/bot/commands/rename.js +139 -0
  17. package/dist/bot/commands/sessions.js +351 -0
  18. package/dist/bot/commands/start.js +43 -0
  19. package/dist/bot/commands/status.js +95 -0
  20. package/dist/bot/commands/task.js +399 -0
  21. package/dist/bot/commands/tasklist.js +220 -0
  22. package/dist/bot/commands/voice.js +145 -0
  23. package/dist/bot/handlers/agent.js +118 -0
  24. package/dist/bot/handlers/context.js +100 -0
  25. package/dist/bot/handlers/document.js +65 -0
  26. package/dist/bot/handlers/inline-menu.js +119 -0
  27. package/dist/bot/handlers/model.js +143 -0
  28. package/dist/bot/handlers/permission.js +235 -0
  29. package/dist/bot/handlers/prompt.js +240 -0
  30. package/dist/bot/handlers/question.js +390 -0
  31. package/dist/bot/handlers/tts.js +89 -0
  32. package/dist/bot/handlers/variant.js +138 -0
  33. package/dist/bot/handlers/voice.js +173 -0
  34. package/dist/bot/index.js +977 -0
  35. package/dist/bot/message-patterns.js +4 -0
  36. package/dist/bot/middleware/auth.js +30 -0
  37. package/dist/bot/middleware/interaction-guard.js +95 -0
  38. package/dist/bot/middleware/unknown-command.js +22 -0
  39. package/dist/bot/streaming/response-streamer.js +286 -0
  40. package/dist/bot/streaming/tool-call-streamer.js +285 -0
  41. package/dist/bot/utils/busy-guard.js +15 -0
  42. package/dist/bot/utils/commands.js +21 -0
  43. package/dist/bot/utils/file-download.js +91 -0
  44. package/dist/bot/utils/finalize-assistant-response.js +52 -0
  45. package/dist/bot/utils/keyboard.js +69 -0
  46. package/dist/bot/utils/send-with-markdown-fallback.js +165 -0
  47. package/dist/bot/utils/telegram-text.js +28 -0
  48. package/dist/bot/utils/thinking-message.js +8 -0
  49. package/dist/cli/args.js +98 -0
  50. package/dist/cli.js +80 -0
  51. package/dist/config.js +97 -0
  52. package/dist/i18n/de.js +357 -0
  53. package/dist/i18n/en.js +357 -0
  54. package/dist/i18n/es.js +357 -0
  55. package/dist/i18n/fr.js +357 -0
  56. package/dist/i18n/index.js +109 -0
  57. package/dist/i18n/ru.js +357 -0
  58. package/dist/i18n/zh.js +357 -0
  59. package/dist/index.js +26 -0
  60. package/dist/interaction/busy.js +8 -0
  61. package/dist/interaction/cleanup.js +32 -0
  62. package/dist/interaction/guard.js +140 -0
  63. package/dist/interaction/manager.js +106 -0
  64. package/dist/interaction/types.js +1 -0
  65. package/dist/keyboard/manager.js +172 -0
  66. package/dist/keyboard/types.js +1 -0
  67. package/dist/model/capabilities.js +62 -0
  68. package/dist/model/context-limit.js +57 -0
  69. package/dist/model/manager.js +259 -0
  70. package/dist/model/types.js +24 -0
  71. package/dist/opencode/client.js +13 -0
  72. package/dist/opencode/events.js +140 -0
  73. package/dist/permission/manager.js +100 -0
  74. package/dist/permission/types.js +1 -0
  75. package/dist/pinned/format.js +29 -0
  76. package/dist/pinned/manager.js +682 -0
  77. package/dist/pinned/types.js +1 -0
  78. package/dist/process/manager.js +273 -0
  79. package/dist/process/types.js +1 -0
  80. package/dist/project/manager.js +88 -0
  81. package/dist/question/manager.js +176 -0
  82. package/dist/question/types.js +1 -0
  83. package/dist/rename/manager.js +53 -0
  84. package/dist/runtime/bootstrap.js +350 -0
  85. package/dist/runtime/mode.js +74 -0
  86. package/dist/runtime/paths.js +37 -0
  87. package/dist/scheduled-task/creation-manager.js +113 -0
  88. package/dist/scheduled-task/display.js +239 -0
  89. package/dist/scheduled-task/executor.js +87 -0
  90. package/dist/scheduled-task/foreground-state.js +32 -0
  91. package/dist/scheduled-task/next-run.js +207 -0
  92. package/dist/scheduled-task/runtime.js +368 -0
  93. package/dist/scheduled-task/schedule-parser.js +169 -0
  94. package/dist/scheduled-task/store.js +65 -0
  95. package/dist/scheduled-task/types.js +19 -0
  96. package/dist/session/cache-manager.js +455 -0
  97. package/dist/session/manager.js +10 -0
  98. package/dist/settings/manager.js +158 -0
  99. package/dist/stt/client.js +97 -0
  100. package/dist/summary/aggregator.js +1136 -0
  101. package/dist/summary/formatter.js +491 -0
  102. package/dist/summary/subagent-formatter.js +63 -0
  103. package/dist/summary/tool-message-batcher.js +90 -0
  104. package/dist/tts/client.js +130 -0
  105. package/dist/utils/error-format.js +29 -0
  106. package/dist/utils/logger.js +127 -0
  107. package/dist/utils/safe-background-task.js +33 -0
  108. package/dist/utils/telegram-rate-limit-retry.js +93 -0
  109. package/dist/variant/manager.js +103 -0
  110. package/dist/variant/types.js +1 -0
  111. package/package.json +79 -0
@@ -0,0 +1,357 @@
1
+ export const ru = {
2
+ "cmd.description.status": "Статус сервера и сессии",
3
+ "cmd.description.new": "Создать новую сессию",
4
+ "cmd.description.stop": "Прервать текущее действие",
5
+ "cmd.description.sessions": "Список сессий",
6
+ "cmd.description.projects": "Список проектов",
7
+ "cmd.description.task": "Создать задачу по расписанию",
8
+ "cmd.description.tasklist": "Список задач по расписанию",
9
+ "cmd.description.commands": "Пользовательские команды",
10
+ "cmd.description.voice": "Выбрать голос TTS",
11
+ "cmd.description.opencode_start": "Запустить OpenCode сервер",
12
+ "cmd.description.opencode_stop": "Остановить OpenCode сервер",
13
+ "cmd.description.help": "Справка",
14
+ "callback.unknown_command": "Неизвестная команда",
15
+ "callback.processing_error": "Ошибка обработки",
16
+ "error.load_agents": "❌ Ошибка при загрузке списка агентов",
17
+ "error.load_models": "❌ Ошибка при загрузке списка моделей",
18
+ "error.load_variants": "❌ Ошибка при загрузке списка вариантов",
19
+ "error.context_button": "❌ Ошибка при обработке кнопки контекста",
20
+ "error.generic": "🔴 Произошла ошибка.",
21
+ "interaction.blocked.expired": "⚠️ Текущая интеракция устарела. Запустите ее снова.",
22
+ "interaction.blocked.expected_callback": "⚠️ Для этого шага используйте inline-кнопки или нажмите Отмена.",
23
+ "interaction.blocked.expected_text": "⚠️ Для этого шага отправьте текстовое сообщение.",
24
+ "interaction.blocked.expected_command": "⚠️ Для этого шага отправьте команду.",
25
+ "interaction.blocked.command_not_allowed": "⚠️ Эта команда недоступна на текущем шаге.",
26
+ "interaction.blocked.finish_current": "⚠️ Сначала завершите текущую интеракцию (ответьте или отмените), затем откройте другое меню.",
27
+ "inline.blocked.expected_choice": "⚠️ Выберите вариант через inline-кнопки или нажмите Отмена.",
28
+ "inline.blocked.command_not_allowed": "⚠️ Эта команда недоступна, пока активно inline-меню.",
29
+ "question.blocked.expected_answer": "⚠️ Ответьте на текущий вопрос кнопками, через Свой ответ, или нажмите Отмена.",
30
+ "question.blocked.command_not_allowed": "⚠️ Эта команда недоступна, пока не завершен текущий опрос.",
31
+ "inline.button.cancel": "❌ Отмена",
32
+ "inline.inactive_callback": "Это меню уже неактивно",
33
+ "inline.cancelled_callback": "Отменено",
34
+ "common.unknown": "неизвестна",
35
+ "common.unknown_error": "неизвестная ошибка",
36
+ "start.welcome": "👋 Добро пожаловать в OpenCode Telegram Bot!\n\nИспользуйте команды:\n/projects — выбрать проект\n/sessions — список сессий\n/new — новая сессия\n/task — задача по расписанию\n/tasklist — список задач по расписанию\n/status — статус\n/help — справка\n\nРежим, модель и вариант выбираются кнопками внизу.",
37
+ "help.keyboard_hint": "💡 Режим, модель, вариант и действия с контекстом доступны через нижние кнопки клавиатуры.",
38
+ "help.text": "📖 **Справка**\n\n/status - Проверить статус сервера\n/sessions - Список сессий\n/new - Создать новую сессию\n/help - Справка",
39
+ "bot.thinking": "💭 Думаю...",
40
+ "bot.project_not_selected": "🏗 Проект не выбран.\n\nСначала выберите проект командой /projects.",
41
+ "bot.creating_session": "🔄 Создаю новую сессию...",
42
+ "bot.create_session_error": "🔴 Не удалось создать сессию. Попробуйте команду /new или проверьте статус сервера /status.",
43
+ "bot.session_created": "✅ Сессия создана: {title}",
44
+ "bot.session_busy": "⏳ Агент уже выполняет задачу. Дождитесь завершения или используйте /abort, чтобы прервать текущий запуск.",
45
+ "bot.session_reset_project_mismatch": "⚠️ Активная сессия не соответствует выбранному проекту, поэтому была сброшена. Используйте /sessions для выбора или /new для создания новой сессии.",
46
+ "bot.prompt_send_error": "Не удалось отправить запрос в OpenCode.",
47
+ "bot.session_error": "🔴 OpenCode вернул ошибку: {message}",
48
+ "bot.session_retry": "🔁 {message}\n\nПровайдер возвращает одну и ту же ошибку при повторных запросах. Используйте /abort для остановки.",
49
+ "bot.unknown_command": "⚠️ Неизвестная команда: {command}. Используйте /help для списка команд.",
50
+ "bot.photo_downloading": "⏳ Скачиваю фото...",
51
+ "bot.photo_too_large": "⚠️ Фото слишком большое (макс. {maxSizeMb}МБ)",
52
+ "bot.photo_model_no_image": "⚠️ Текущая модель не поддерживает изображения. Отправляю только текст.",
53
+ "bot.photo_download_error": "🔴 Не удалось скачать фото",
54
+ "bot.photo_no_caption": "💡 Совет: Добавьте подпись, чтобы описать, что делать с этим фото.",
55
+ "bot.file_downloading": "⏳ Скачиваю файл...",
56
+ "bot.file_too_large": "⚠️ Файл слишком большой (макс. {maxSizeMb}МБ)",
57
+ "bot.file_download_error": "🔴 Не удалось скачать файл",
58
+ "bot.model_no_pdf": "⚠️ Текущая модель не поддерживает PDF. Отправляю только текст.",
59
+ "bot.text_file_too_large": "⚠️ Текстовый файл слишком большой (макс. {maxSizeKb}КБ)",
60
+ "status.header_running": "🟢 OpenCode Server запущен",
61
+ "status.health.healthy": "Healthy",
62
+ "status.health.unhealthy": "Unhealthy",
63
+ "status.line.health": "Статус: {health}",
64
+ "status.line.version": "Версия: {version}",
65
+ "status.line.managed_yes": "Запущен ботом: Да",
66
+ "status.line.managed_no": "Запущен ботом: Нет",
67
+ "status.line.pid": "PID: {pid}",
68
+ "status.line.uptime_sec": "Uptime: {seconds} сек",
69
+ "status.line.mode": "Режим: {mode}",
70
+ "status.line.model": "Модель: {model}",
71
+ "status.agent_not_set": "не установлен",
72
+ "status.project_selected": "Проект: {project}",
73
+ "status.project_not_selected": "Проект: не выбран",
74
+ "status.project_hint": "Используйте /projects для выбора проекта",
75
+ "status.session_selected": "Текущая сессия: {title}",
76
+ "status.session_not_selected": "Текущая сессия: не выбрана",
77
+ "status.session_hint": "Используйте /sessions для выбора или /new для создания",
78
+ "status.server_unavailable": "🔴 OpenCode Server недоступен\n\nИспользуйте /opencode_start для запуска сервера.",
79
+ "projects.empty": "📭 Проектов нет.\n\nОткройте директорию в OpenCode и создайте хотя бы одну сессию, после этого она появится здесь.",
80
+ "projects.select": "Выберите проект:",
81
+ "projects.select_with_current": "Выберите проект:\n\nТекущий: 🏗 {project}",
82
+ "projects.page_indicator": "Страница {current}/{total}",
83
+ "projects.prev_page": "⬅️ Назад",
84
+ "projects.next_page": "Вперёд ➡️",
85
+ "projects.fetch_error": "🔴 OpenCode Server недоступен или произошла ошибка при получении списка проектов.",
86
+ "projects.page_load_error": "Не удалось загрузить эту страницу. Попробуйте снова.",
87
+ "projects.selected": "✅ Проект выбран: {project}\n\n📋 Сессия сброшена. Используйте /sessions или /new для работы с этим проектом.",
88
+ "projects.select_error": "🔴 Ошибка при выборе проекта.",
89
+ "sessions.project_not_selected": "🏗 Проект не выбран.\n\nСначала выберите проект командой /projects.",
90
+ "sessions.empty": "📭 Сессий нет.\n\nСоздайте новую сессию командой /new.",
91
+ "sessions.select": "Выберите сессию:",
92
+ "sessions.select_page": "Выберите сессию (страница {page}):",
93
+ "sessions.fetch_error": "🔴 OpenCode Server недоступен или произошла ошибка при получении списка сессий.",
94
+ "sessions.select_project_first": "🔴 Проект не выбран. Используйте /projects.",
95
+ "sessions.page_empty_callback": "На этой странице нет сессий",
96
+ "sessions.page_load_error_callback": "Не удалось загрузить эту страницу. Пожалуйста, попробуйте снова.",
97
+ "sessions.button.prev_page": "⬅️ Назад",
98
+ "sessions.button.next_page": "Вперёд ➡️",
99
+ "sessions.loading_context": "⏳ Загружаю контекст и последние сообщения...",
100
+ "sessions.selected": "✅ Сессия выбрана: {title}",
101
+ "sessions.select_error": "🔴 Ошибка при выборе сессии.",
102
+ "sessions.preview.empty": "Последних сообщений нет.",
103
+ "sessions.preview.title": "Последние сообщения:",
104
+ "sessions.preview.you": "Вы:",
105
+ "sessions.preview.agent": "Агент:",
106
+ "new.project_not_selected": "🏗 Проект не выбран.\n\nСначала выберите проект командой /projects.",
107
+ "new.created": "✅ Создана новая сессия: {title}",
108
+ "new.create_error": "🔴 OpenCode Server недоступен или произошла ошибка при создании сессии.",
109
+ "stop.no_active_session": "🛑 Агент не был запущен\n\nСначала создайте сессию командой /new или выберите существующую через /sessions.",
110
+ "stop.in_progress": "🛑 Отключил поток событий и отправляю сигнал прерывания...\n\nОжидание остановки агента.",
111
+ "stop.warn_unconfirmed": "⚠️ Поток событий остановлен, но сервер не подтвердил прерывание.\n\nПроверьте /status и повторите /abort через пару секунд.",
112
+ "stop.warn_maybe_finished": "⚠️ Поток событий остановлен, но агент мог уже завершиться к моменту запроса.",
113
+ "stop.success": "✅ Действие агента прервано. Новые сообщения от текущего запуска больше не придут.",
114
+ "stop.warn_still_busy": "⚠️ Сигнал отправлен, но агент еще busy.\n\nПоток событий уже отключен, поэтому бот не будет присылать промежуточные сообщения.",
115
+ "stop.warn_timeout": "⚠️ Таймаут запроса на прерывание.\n\nПоток событий уже отключен, повторите /abort через пару секунд.",
116
+ "stop.warn_local_only": "⚠️ Поток событий остановлен локально, но при прерывании на сервере произошла ошибка.",
117
+ "stop.error": "🔴 Ошибка при прерывании действия.\n\nПоток событий остановлен, попробуйте /abort еще раз.",
118
+ "opencode_start.already_running_managed": "⚠️ OpenCode Server уже запущен\n\nPID: {pid}\nUptime: {seconds} секунд",
119
+ "opencode_start.already_running_external": "✅ OpenCode Server уже запущен внешним процессом\n\nВерсия: {version}\n\nЭтот сервер не был запущен через бота, поэтому команда /opencode-stop не сможет его остановить.",
120
+ "opencode_start.starting": "🔄 Запускаю OpenCode Server...",
121
+ "opencode_start.start_error": "🔴 Не удалось запустить OpenCode Server\n\nОшибка: {error}\n\nПроверьте, что OpenCode CLI установлен и доступен в PATH:\nopencode --version\nnpm install -g @opencode-ai/cli",
122
+ "opencode_start.started_not_ready": "⚠️ OpenCode Server запущен, но не отвечает\n\nPID: {pid}\n\nСервер может запускаться. Попробуйте /status через несколько секунд.",
123
+ "opencode_start.success": "✅ OpenCode Server успешно запущен\n\nPID: {pid}\nВерсия: {version}",
124
+ "opencode_start.error": "🔴 Произошла ошибка при запуске сервера.\n\nПроверьте логи приложения для подробностей.",
125
+ "opencode_stop.external_running": "⚠️ OpenCode Server запущен внешним процессом\n\nЭтот сервер не был запущен через /opencode-start.\nОстановите его вручную или используйте /status для проверки состояния.",
126
+ "opencode_stop.not_running": "⚠️ OpenCode Server не запущен",
127
+ "opencode_stop.stopping": "🛑 Останавливаю OpenCode Server...\n\nPID: {pid}",
128
+ "opencode_stop.stop_error": "🔴 Не удалось остановить OpenCode Server\n\nОшибка: {error}",
129
+ "opencode_stop.success": "✅ OpenCode Server успешно остановлен",
130
+ "opencode_stop.error": "🔴 Произошла ошибка при остановке сервера.\n\nПроверьте логи приложения для подробностей.",
131
+ "agent.changed_callback": "Режим изменен: {name}",
132
+ "agent.changed_message": "✅ Режим изменен на: {name}",
133
+ "agent.change_error_callback": "Ошибка при смене режима",
134
+ "agent.menu.current": "Текущий режим: {name}\n\nВыберите режим:",
135
+ "agent.menu.select": "Выберите режим работы:",
136
+ "agent.menu.empty": "⚠️ Нет доступных агентов",
137
+ "agent.menu.error": "🔴 Не удалось получить список агентов",
138
+ "model.changed_callback": "Модель изменена: {name}",
139
+ "model.changed_message": "✅ Модель изменена на: {name}",
140
+ "model.change_error_callback": "Ошибка при смене модели",
141
+ "model.menu.empty": "⚠️ Нет доступных моделей",
142
+ "model.menu.select": "Выберите модель:",
143
+ "model.menu.current": "Текущая модель: {name}\n\nВыберите модель:",
144
+ "model.menu.favorites_title": "⭐ Избранное (Добавляйте модели в избранное через OpenCode CLI)",
145
+ "model.menu.favorites_empty": "— Список пуст.",
146
+ "model.menu.recent_title": "🕘 Недавние",
147
+ "model.menu.recent_empty": "— Список пуст.",
148
+ "model.menu.favorites_hint": "ℹ️ Добавляйте модели в избранное через OpenCode CLI, чтобы они были вверху списка.",
149
+ "model.menu.error": "🔴 Не удалось получить список моделей",
150
+ "variant.model_not_selected_callback": "Ошибка: модель не выбрана",
151
+ "variant.changed_callback": "Вариант изменен: {name}",
152
+ "variant.changed_message": "✅ Вариант изменен на: {name}",
153
+ "variant.change_error_callback": "Ошибка при смене варианта",
154
+ "variant.select_model_first": "⚠️ Сначала выберите модель",
155
+ "variant.menu.empty": "⚠️ Нет доступных вариантов",
156
+ "variant.menu.current": "Текущий вариант: {name}\n\nВыберите вариант:",
157
+ "variant.menu.error": "🔴 Не удалось получить список вариантов",
158
+ "context.button.confirm": "✅ Да, сжать контекст",
159
+ "context.no_active_session": "⚠️ Нет активной сессии. Создайте сессию командой /new",
160
+ "context.confirm_text": '📊 Сжатие контекста для сессии "{title}"\n\nЭто уменьшит использование контекста, удалив старые сообщения из истории. Текущая задача не будет прервана.\n\nПродолжить?',
161
+ "context.callback_session_not_found": "Сессия не найдена",
162
+ "context.callback_compacting": "Сжатие контекста...",
163
+ "context.progress": "⏳ Сжимаю контекст...",
164
+ "context.error": "❌ Ошибка при сжатии контекста",
165
+ "context.success": "✅ Контекст успешно сжат",
166
+ "permission.inactive_callback": "Запрос разрешения неактивен",
167
+ "permission.processing_error_callback": "Ошибка при обработке",
168
+ "permission.no_active_request_callback": "Ошибка: нет активного запроса",
169
+ "permission.reply.once": "Разрешено однократно",
170
+ "permission.reply.always": "Разрешено всегда",
171
+ "permission.reply.reject": "Отклонено",
172
+ "permission.send_reply_error": "❌ Не удалось отправить ответ на запрос разрешения",
173
+ "permission.blocked.expected_reply": "⚠️ Сначала ответьте на запрос разрешения кнопками выше.",
174
+ "permission.blocked.command_not_allowed": "⚠️ Эта команда недоступна, пока вы не ответите на запрос разрешения.",
175
+ "permission.header": "{emoji} Запрос разрешения: {name}\n\n",
176
+ "permission.button.allow": "✅ Разрешить один раз",
177
+ "permission.button.always": "🔓 Разрешить всегда",
178
+ "permission.button.reject": "❌ Отклонить",
179
+ "permission.name.bash": "Bash",
180
+ "permission.name.edit": "Edit",
181
+ "permission.name.write": "Write",
182
+ "permission.name.read": "Read",
183
+ "permission.name.webfetch": "Web Fetch",
184
+ "permission.name.websearch": "Web Search",
185
+ "permission.name.glob": "File Search",
186
+ "permission.name.grep": "Content Search",
187
+ "permission.name.list": "List Directory",
188
+ "permission.name.task": "Task",
189
+ "permission.name.lsp": "LSP",
190
+ "permission.name.external_directory": "Внешняя директория",
191
+ "question.inactive_callback": "Опрос неактивен",
192
+ "question.processing_error_callback": "Ошибка при обработке",
193
+ "question.select_one_required_callback": "Выберите хотя бы один вариант",
194
+ "question.enter_custom_callback": "Введите свой ответ сообщением",
195
+ "question.cancelled": "❌ Опрос отменен",
196
+ "question.answer_already_received": "Ответ уже получен, подождите...",
197
+ "question.completed_no_answers": "✅ Опрос завершен (без ответов)",
198
+ "question.no_active_project": "❌ Нет активного проекта",
199
+ "question.no_active_request": "❌ Нет активного запроса",
200
+ "question.send_answers_error": "❌ Не удалось отправить ответы агенту",
201
+ "question.multi_hint": "\n(Можно выбрать несколько вариантов)",
202
+ "question.button.submit": "✅ Готово",
203
+ "question.button.custom": "🔤 Свой ответ",
204
+ "question.button.cancel": "❌ Отмена",
205
+ "question.use_custom_button_first": '⚠️ Чтобы отправить текст, сначала нажмите кнопку "Свой ответ" для текущего вопроса.',
206
+ "question.summary.title": "✅ Опрос завершен!\n\n",
207
+ "question.summary.question": "Вопрос {index}:\n{question}\n\n",
208
+ "question.summary.answer": "Ответ:\n{answer}\n\n",
209
+ "keyboard.agent_mode": "{emoji} {name} Mode",
210
+ "keyboard.context": "📊 {used} / {limit} ({percent}%)",
211
+ "keyboard.context_empty": "📊 0",
212
+ "keyboard.variant": "💭 {name}",
213
+ "keyboard.variant_default": "💡 Default",
214
+ "keyboard.updated": "⌨️ Клавиатура обновлена",
215
+ "pinned.default_session_title": "новая сессия",
216
+ "pinned.unknown": "Неизвестно",
217
+ "pinned.line.project": "Проект: {project}",
218
+ "pinned.line.model": "Модель: {model}",
219
+ "pinned.line.context": "Контекст: {used} / {limit} ({percent}%)",
220
+ "pinned.line.cost": "Стоимость: {cost} потрачено",
221
+ "subagent.header": "Сабагент {agent}: {description}",
222
+ "subagent.line.status": "Статус: {status}",
223
+ "subagent.line.task": "Задача: {task}",
224
+ "subagent.line.agent": "Агент: {agent}",
225
+ "subagent.working": "В работе...",
226
+ "subagent.working_with_details": "В работе: {details}",
227
+ "subagent.completed": "Завершена",
228
+ "subagent.failed": "Ошибка задачи",
229
+ "subagent.status.pending": "ожидание",
230
+ "subagent.status.running": "в работе",
231
+ "subagent.status.completed": "завершен",
232
+ "subagent.status.error": "ошибка",
233
+ "pinned.files.title": "Файлы ({count}):",
234
+ "pinned.files.item": " {path}{diff}",
235
+ "pinned.files.more": " ... и еще {count}",
236
+ "tool.todo.overflow": "*(ещё {count} задач)*",
237
+ "tool.file_header.write": "Write File/Path: {path}\n============================================================\n\n",
238
+ "tool.file_header.edit": "Edit File/Path: {path}\n============================================================\n\n",
239
+ "runtime.wizard.ask_token": "Введите токен Telegram-бота (получить у @BotFather).\n> ",
240
+ "runtime.wizard.ask_language": "Выберите язык интерфейса.\nВведите номер языка из списка или код локали.\nНажмите Enter, чтобы оставить язык по умолчанию: {defaultLocale}\n{options}\n> ",
241
+ "runtime.wizard.language_invalid": "Введите номер языка из списка или поддерживаемый код локали.\n",
242
+ "runtime.wizard.language_selected": "Выбран язык: {language}\n",
243
+ "runtime.wizard.token_required": "Токен обязателен. Попробуйте еще раз.\n",
244
+ "runtime.wizard.token_invalid": "Похоже на невалидный токен (ожидается формат <id>:<secret>). Попробуйте еще раз.\n",
245
+ "runtime.wizard.ask_user_id": "Введите ваш Telegram User ID (можно узнать у @userinfobot).\n> ",
246
+ "runtime.wizard.user_id_invalid": "Введите положительное целое число (> 0).\n",
247
+ "runtime.wizard.ask_api_url": "Введите URL OpenCode API (опционально).\nНажмите Enter для значения по умолчанию: {defaultUrl}\n> ",
248
+ "runtime.wizard.ask_server_username": "Введите логин OpenCode сервера (опционально).\nНажмите Enter для значения по умолчанию: {defaultUsername}\n> ",
249
+ "runtime.wizard.ask_server_password": "Введите пароль OpenCode сервера (опционально).\nНажмите Enter, чтобы оставить пустым.\n> ",
250
+ "runtime.wizard.api_url_invalid": "Введите корректный URL (http/https) или нажмите Enter для значения по умолчанию.\n",
251
+ "runtime.wizard.start": "Настройка OpenCode Telegram Bot.\n",
252
+ "runtime.wizard.saved": "Конфигурация сохранена:\n- {envPath}\n- {settingsPath}\n",
253
+ "runtime.wizard.not_configured_starting": "Приложение еще не сконфигурировано. Запускаю wizard...\n",
254
+ "runtime.wizard.tty_required": "Интерактивный wizard требует TTY-терминал. Запустите `opencode-telegram config` в интерактивной оболочке.",
255
+ "rename.no_session": "⚠️ Нет активной сессии. Сначала создайте или выберите сессию.",
256
+ "rename.prompt": "📝 Введите новое название сессии:\n\nТекущее: {title}",
257
+ "rename.empty_title": "⚠️ Название не может быть пустым.",
258
+ "rename.success": "✅ Сессия переименована в: {title}",
259
+ "rename.error": "🔴 Не удалось переименовать сессию.",
260
+ "rename.cancelled": "❌ Переименование отменено.",
261
+ "rename.inactive_callback": "Запрос переименования неактивен",
262
+ "rename.inactive": "⚠️ Запрос переименования неактивен. Выполните /rename снова.",
263
+ "rename.blocked.expected_name": "⚠️ Введите новое название текстом или нажмите Отмена в сообщении переименования.",
264
+ "rename.blocked.command_not_allowed": "⚠️ Эта команда недоступна, пока ожидается новое название сессии.",
265
+ "rename.button.cancel": "❌ Отмена",
266
+ "task.prompt.schedule": "⏰ Отправьте расписание задачи обычным языком.\n\nПримеры:\n- каждые 5 минут\n- каждый день в 17:00\n- завтра в 12:00",
267
+ "task.schedule_empty": "⚠️ Расписание не может быть пустым.",
268
+ "task.parse.in_progress": "⏳ Распознаю расписание...",
269
+ "task.parse_error": "🔴 Не удалось распознать расписание.\n\n{message}\n\nОтправьте период еще раз в более явном виде.",
270
+ "task.schedule_preview": "✅ Расписание распознано\n\nКак я понял: {summary}\n{cronLine}Часовой пояс: {timezone}\nТип: {kind}\nСледующий запуск: {nextRunAt}",
271
+ "task.schedule_preview.cron": "Cron: {cron}",
272
+ "task.prompt.body": "📝 Теперь отправьте текст задачи, которую нужно выполнять по расписанию.",
273
+ "task.prompt_empty": "⚠️ Текст задачи не может быть пустым.",
274
+ "task.created": "✅ Задача по расписанию создана\n\nЗадача: {description}\nПроект: {project}\nМодель: {model}\nРасписание: {schedule}\n{cronLine}Следующий запуск: {nextRunAt}",
275
+ "task.created.cron": "Cron: {cron}",
276
+ "task.button.retry_schedule": "🔁 Ввести период заново",
277
+ "task.button.cancel": "❌ Отмена",
278
+ "task.retry_schedule_callback": "Возвращаю ввод периода...",
279
+ "task.cancel_callback": "Отменяю...",
280
+ "task.cancelled": "❌ Создание задачи по расписанию отменено.",
281
+ "task.inactive_callback": "Этот сценарий создания задачи уже неактивен",
282
+ "task.inactive": "⚠️ Сценарий создания задачи неактивен. Запустите /task снова.",
283
+ "task.blocked.expected_input": "⚠️ Сначала завершите создание задачи по расписанию: отправьте текст или используйте кнопку в сообщении с расписанием.",
284
+ "task.blocked.command_not_allowed": "⚠️ Эта команда недоступна, пока идет создание задачи по расписанию.",
285
+ "task.limit_reached": "⚠️ Достигнут лимит задач ({limit}). Сначала удалите одну из существующих задач по расписанию.",
286
+ "task.schedule_too_frequent": "Повторяющееся расписание слишком частое. Минимально допустимый интервал - один запуск в 5 минут.",
287
+ "task.kind.cron": "повторяющаяся",
288
+ "task.kind.once": "однократная",
289
+ "task.run.success": "⏰ Задача по расписанию выполнена: {description}",
290
+ "task.run.error": "🔴 Ошибка выполнения задачи по расписанию: {description}\n\nОшибка: {error}",
291
+ "tasklist.empty": "📭 Задач по расписанию пока нет.",
292
+ "tasklist.select": "Выберите задачу по расписанию:",
293
+ "tasklist.details": "⏰ Задача по расписанию\n\nЗадача: {prompt}\nПроект: {project}\nРасписание: {schedule}\n{cronLine}Часовой пояс: {timezone}\nСледующий запуск: {nextRunAt}\nПоследний запуск: {lastRunAt}\nКоличество запусков: {runCount}",
294
+ "tasklist.details.cron": "Cron: {cron}",
295
+ "tasklist.button.delete": "🗑 Удалить",
296
+ "tasklist.button.cancel": "❌ Отмена",
297
+ "tasklist.deleted_callback": "Удалено",
298
+ "tasklist.cancelled_callback": "Отменено",
299
+ "tasklist.inactive_callback": "Это меню задач по расписанию уже неактивно",
300
+ "tasklist.load_error": "🔴 Не удалось загрузить задачи по расписанию.",
301
+ "commands.select": "Выберите команду OpenCode:",
302
+ "commands.empty": "📭 Для этого проекта нет доступных команд OpenCode.",
303
+ "commands.fetch_error": "🔴 Не удалось загрузить список команд OpenCode.",
304
+ "commands.no_description": "Без описания",
305
+ "commands.button.execute": "✅ Выполнить",
306
+ "commands.button.cancel": "❌ Отмена",
307
+ "commands.confirm": "Подтвердите выполнение команды {command}. Для выполнения с аргументами отправьте аргументы отдельным сообщением.",
308
+ "commands.inactive_callback": "Это меню команд уже неактивно",
309
+ "commands.cancelled_callback": "Отменено",
310
+ "commands.execute_callback": "Запускаю команду...",
311
+ "commands.executing_prefix": "⚡ Выполнение команды:",
312
+ "commands.arguments_empty": "⚠️ Аргументы не могут быть пустыми. Отправьте текст или нажмите Выполнить.",
313
+ "commands.execute_error": "🔴 Не удалось выполнить команду OpenCode.",
314
+ "commands.select_page": "Выберите команду OpenCode (страница {page}):",
315
+ "commands.button.prev_page": "⬅️ Назад",
316
+ "commands.button.next_page": "Вперёд ➡️",
317
+ "commands.page_empty_callback": "На этой странице нет команд",
318
+ "commands.page_load_error_callback": "Не удалось загрузить эту страницу. Пожалуйста, попробуйте снова.",
319
+ "cmd.description.rename": "Переименовать текущую сессию",
320
+ "cli.usage": "Использование:\n opencode-telegram [start] [--mode sources|installed]\n opencode-telegram status\n opencode-telegram stop\n opencode-telegram config\n\nЗаметки:\n - Без команды по умолчанию используется `start`\n - `--mode` сейчас поддерживается только для `start`",
321
+ "cli.placeholder.status": "Команда `status` пока работает как заглушка. Реальная проверка статуса появится на этапе service-слоя (Этап 5).",
322
+ "cli.placeholder.stop": "Команда `stop` пока работает как заглушка. Реальная остановка фонового процесса появится на этапе service-слоя (Этап 5).",
323
+ "cli.placeholder.unavailable": "Команда недоступна.",
324
+ "cli.error.prefix": "CLI error: {message}",
325
+ "cli.args.unknown_command": "Неизвестная команда: {value}",
326
+ "cli.args.mode_requires_value": "Опция --mode требует значение: sources|installed",
327
+ "cli.args.invalid_mode": "Некорректное значение --mode: {value}. Ожидается sources|installed",
328
+ "cli.args.unknown_option": "Неизвестная опция: {value}",
329
+ "cli.args.mode_only_start": "Опция --mode поддерживается только для команды start",
330
+ "legacy.models.fetch_error": "🔴 Не удалось получить список моделей. Проверьте статус сервера /status.",
331
+ "legacy.models.empty": "📋 Нет доступных моделей. Настройте провайдеры через OpenCode.",
332
+ "legacy.models.header": "📋 Доступные модели:\n\n",
333
+ "legacy.models.no_provider_models": " ⚠️ Нет доступных моделей\n",
334
+ "legacy.models.env_hint": "💡 Для использования модели в .env:\n",
335
+ "legacy.models.error": "🔴 Произошла ошибка при получении списка моделей.",
336
+ "stt.recognizing": "🎤 Распознаю аудио...",
337
+ "stt.recognized": "🎤 Распознано:\n{text}",
338
+ "stt.not_configured": "🎤 Распознавание голоса не настроено.\n\nУстановите STT_API_URL и STT_API_KEY в .env для включения.",
339
+ "stt.error": "🔴 Не удалось распознать аудио: {error}",
340
+ "stt.empty_result": "🎤 В аудиосообщении не обнаружена речь.",
341
+ "tts.not_configured": "🔊 Синтез речи не настроен.\n\nУстановите TTS_API_URL в .env для включения.\n\nРекомендуется: Используйте pocket-tts-server для локального TTS.\nhttps://github.com/ai-joe-git/pocket-tts-server",
342
+ "tts.voice_changed": "🔊 Голос изменён: {voice}",
343
+ "tts.voice_error": "🔴 Не удалось изменить голос: {error}",
344
+ "tts.fetch_voices_error": "🔴 Не удалось получить голоса от TTS-сервера.",
345
+ "tts.synthesis_error": "🔴 Ошибка синтеза речи: {error}",
346
+ "tts.speaking": "🔊 Воспроизведение...",
347
+ "tts.menu_title": "Выберите голос:",
348
+ "tts.menu_current": "Текущий голос: {voice}\n\nВыберите голос:",
349
+ "tts.menu_empty": "⚠️ Нет доступных голосов. Проверьте конфигурацию TTS-сервера.",
350
+ "tts.menu_loading": "⏳ Загрузка голосов...",
351
+ "tts.menu_error": "🔴 Не удалось загрузить голоса.",
352
+ "tts.button.off": "🔇 TTS Выкл",
353
+ "tts.button.off_description": "Отключить голосовые ответы",
354
+ "tts.button.prev_page": "⬅️ Назад",
355
+ "tts.button.next_page": "Далее ➡️",
356
+ "tts.off_success": "🔇 Голосовые ответы отключены.",
357
+ };