@link-assistant/hive-mind 1.69.11 → 1.69.12

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/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # @link-assistant/hive-mind
2
2
 
3
+ ## 1.69.12
4
+
5
+ ### Patch Changes
6
+
7
+ - 8ca35d6: Fix Telegram bot localization fallbacks for supported languages.
8
+
3
9
  ## 1.69.11
4
10
 
5
11
  ### Patch Changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@link-assistant/hive-mind",
3
- "version": "1.69.11",
3
+ "version": "1.69.12",
4
4
  "description": "AI-powered issue solver and hive mind for collaborative problem solving",
5
5
  "main": "src/hive.mjs",
6
6
  "type": "module",
@@ -1,4 +1,8 @@
1
1
  import { t } from './i18n.lib.mjs';
2
+ import dayjs from 'dayjs';
3
+ import utc from 'dayjs/plugin/utc.js';
4
+
5
+ dayjs.extend(utc);
2
6
 
3
7
  const ENGLISH_LIMITS = {
4
8
  additional_codex_limits: 'Additional Codex limits',
@@ -15,6 +19,10 @@ const ENGLISH_LIMITS = {
15
19
  current_week_sonnet_only: 'Current week (Sonnet only)',
16
20
  disabled_by_admin: '`--show-limits` is disabled by the bot administrator.',
17
21
  disk_space: 'Disk space',
22
+ duration_day_short: 'd',
23
+ duration_hour_short: 'h',
24
+ duration_minute_short: 'm',
25
+ duration_second_short: 's',
18
26
  end: 'End',
19
27
  five_hour_session: '5h session',
20
28
  five_min_load_avg: '5m load avg',
@@ -27,9 +35,41 @@ const ENGLISH_LIMITS = {
27
35
  passed: 'passed',
28
36
  plan: 'Plan',
29
37
  ram: 'RAM',
38
+ reason_claude_5_hour_session: 'Claude 5 hour session limit is {{currentPercent}}% (threshold: {{thresholdPercent}})',
39
+ reason_claude_running: 'Claude process is already running',
40
+ reason_claude_weekly: 'Claude weekly limit is {{currentPercent}}% (threshold: {{thresholdPercent}})',
41
+ reason_codex_5_hour_session: 'Codex 5 hour session limit is {{currentPercent}}% (threshold: {{thresholdPercent}})',
42
+ reason_codex_running: 'Codex process is already running',
43
+ reason_codex_weekly: 'Codex weekly limit is {{currentPercent}}% (threshold: {{thresholdPercent}})',
44
+ reason_cpu_usage: 'CPU usage is {{currentPercent}}% (threshold: {{thresholdPercent}})',
45
+ reason_disk_usage: 'Disk usage is {{currentPercent}}% (threshold: {{thresholdPercent}})',
46
+ reason_gemini_running: 'Gemini CLI process is already running',
47
+ reason_github_api: 'GitHub API usage is {{currentPercent}}% (threshold: {{thresholdPercent}})',
48
+ reason_min_interval: 'Minimum interval between commands not reached',
49
+ reason_qwen_running: 'Qwen Code process is already running',
50
+ reason_ram_usage: 'RAM usage is {{currentPercent}}% (threshold: {{thresholdPercent}})',
51
+ reason_threshold_exceeded: '{{metric}} threshold exceeded',
52
+ remaining: '{{duration}} remaining',
30
53
  requests: 'requests',
31
54
  resets_at: 'Resets {{time}}',
32
55
  resets_in: 'Resets in {{duration}}',
56
+ resource_limit_exceeded: 'Resource limit exceeded',
57
+ solve_queue_status: 'Solve Queue Status',
58
+ queue_completed: 'Completed',
59
+ queue_failed: 'Failed',
60
+ queue_and_more: 'and {{count}} more',
61
+ queue_pending: 'pending',
62
+ queue_processing: 'processing',
63
+ queue_processes: '{{count}} processes',
64
+ queue_status_cancelled: 'cancelled',
65
+ queue_status_failed: 'failed',
66
+ queue_status_queued: 'queued',
67
+ queue_status_started: 'started',
68
+ queue_status_starting: 'starting',
69
+ queue_status_waiting: 'waiting',
70
+ queue_waiting_current_command: 'waiting for current command',
71
+ queue_waiting_in_queue: 'Waiting in queue',
72
+ queues: 'Queues',
33
73
  seven_day_all_models: '7d all models',
34
74
  seven_day_sonnet_only: '7d Sonnet only',
35
75
  session: 'session',
@@ -69,3 +109,108 @@ export function formatLimitResetsIn(duration, resetTime, options = {}) {
69
109
  export function formatLimitResetsAt(resetTime, options = {}) {
70
110
  return lt('resets_at', { time: resetTime }, options);
71
111
  }
112
+
113
+ export function formatLocalizedResetTime(isoDate, includeTimezone = true, options = {}) {
114
+ if (typeof includeTimezone === 'object') return formatLocalizedResetTime(isoDate, true, includeTimezone);
115
+ const locale = resolveLimitLocale(options);
116
+ if (!isoDate) return null;
117
+
118
+ try {
119
+ const date = dayjs(isoDate).utc();
120
+ if (!date.isValid()) return isoDate;
121
+
122
+ if (locale && locale !== 'en') {
123
+ const localeTag = locale === 'ru' ? 'ru-RU' : locale === 'zh' ? 'zh-CN' : locale === 'hi' ? 'hi-IN' : locale;
124
+ const formatted = new Intl.DateTimeFormat(localeTag, {
125
+ timeZone: 'UTC',
126
+ month: 'short',
127
+ day: 'numeric',
128
+ hour: '2-digit',
129
+ minute: '2-digit',
130
+ hour12: false,
131
+ })
132
+ .format(date.toDate())
133
+ .replace(/\s*г\./g, '')
134
+ .replace(',', '');
135
+ return includeTimezone ? `${formatted} UTC` : formatted;
136
+ }
137
+
138
+ const timeStr = date.format('MMM D, h:mma');
139
+ return includeTimezone ? `${timeStr} UTC` : timeStr;
140
+ } catch {
141
+ return isoDate;
142
+ }
143
+ }
144
+
145
+ function formatDurationFromParts(parts, options = {}) {
146
+ const locale = resolveLimitLocale(options);
147
+ const labels =
148
+ locale && locale !== 'en'
149
+ ? {
150
+ d: lt('duration_day_short', {}, { locale }),
151
+ h: lt('duration_hour_short', {}, { locale }),
152
+ m: lt('duration_minute_short', {}, { locale }),
153
+ s: lt('duration_second_short', {}, { locale }),
154
+ }
155
+ : { d: 'd', h: 'h', m: 'm', s: 's' };
156
+ const spacer = locale && locale !== 'en' ? ' ' : '';
157
+ return parts
158
+ .filter(part => part.value > 0 || part.always)
159
+ .map(part => `${part.value}${spacer}${labels[part.unit]}`)
160
+ .join(' ');
161
+ }
162
+
163
+ export function localizeCompactDuration(duration, options = {}) {
164
+ const locale = resolveLimitLocale(options);
165
+ if (!duration || !locale || locale === 'en') return duration;
166
+ const matches = [...String(duration).matchAll(/(\d+)\s*([dhms])/g)];
167
+ if (matches.length === 0) return duration;
168
+ return formatDurationFromParts(
169
+ matches.map(match => ({ value: Number(match[1]), unit: match[2] })),
170
+ { locale }
171
+ );
172
+ }
173
+
174
+ export function formatLocalizedRelativeTime(isoDate, options = {}) {
175
+ const locale = resolveLimitLocale(options);
176
+ if (!isoDate) return null;
177
+
178
+ try {
179
+ const target = dayjs(isoDate);
180
+ if (!target.isValid()) return null;
181
+
182
+ const diffMs = target.diff(dayjs());
183
+ if (diffMs < 0) return null;
184
+
185
+ const totalMinutes = Math.floor(diffMs / (1000 * 60));
186
+ const totalHours = Math.floor(totalMinutes / 60);
187
+ const days = Math.floor(totalHours / 24);
188
+ const hours = totalHours % 24;
189
+ const minutes = totalMinutes % 60;
190
+
191
+ if (!locale || locale === 'en') return days > 0 ? `${days}d ${hours}h ${minutes}m` : `${hours}h ${minutes}m`;
192
+ if (days > 0) {
193
+ return formatDurationFromParts(
194
+ [
195
+ { value: days, unit: 'd' },
196
+ { value: hours, unit: 'h' },
197
+ { value: minutes, unit: 'm' },
198
+ ],
199
+ { locale }
200
+ );
201
+ }
202
+ return formatDurationFromParts(
203
+ [
204
+ { value: hours, unit: 'h', always: true },
205
+ { value: minutes, unit: 'm' },
206
+ ],
207
+ { locale }
208
+ );
209
+ } catch {
210
+ return null;
211
+ }
212
+ }
213
+
214
+ export function formatLocalizedCurrentTime(options = {}) {
215
+ return formatLocalizedResetTime(new Date().toISOString(), true, options);
216
+ }
@@ -13,7 +13,7 @@ import dayjs from 'dayjs';
13
13
  import utc from 'dayjs/plugin/utc.js';
14
14
 
15
15
  import { wrapDollarWithGhRetry as _wrapDollarWithGhRetry, execGhWithRetry } from './github-rate-limit.lib.mjs'; // rate-limit marker (#1726): gh API calls flow through $ wrapped by caller. execGhWithRetry adds transient-network retry (#1756).
16
- import { formatLimitResetsAt, formatLimitResetsIn, lt, resolveLimitLocale } from './limits-i18n.lib.mjs';
16
+ import { formatLimitResetsAt, formatLimitResetsIn, formatLocalizedCurrentTime, formatLocalizedRelativeTime, formatLocalizedResetTime, localizeCompactDuration, lt, resolveLimitLocale } from './limits-i18n.lib.mjs';
17
17
  // Initialize dayjs plugins
18
18
  dayjs.extend(utc);
19
19
 
@@ -203,56 +203,12 @@ export function formatRetryAfterMessage(retryAfter) {
203
203
  * @param {boolean} includeTimezone - Whether to include timezone suffix (default: true)
204
204
  * @returns {string} Human-readable reset time (e.g., "Dec 3, 6:59pm UTC")
205
205
  */
206
- function formatResetTime(isoDate, includeTimezone = true) {
207
- if (!isoDate) return null;
208
-
209
- try {
210
- const date = dayjs(isoDate).utc();
211
- if (!date.isValid()) return isoDate;
212
-
213
- // dayjs format: MMM=Jan, D=day, h=12-hour, mm=minutes, a=am/pm
214
- const timeStr = date.format('MMM D, h:mma');
215
- return includeTimezone ? `${timeStr} UTC` : timeStr;
216
- } catch {
217
- return isoDate;
218
- }
206
+ function formatResetTime(isoDate, includeTimezone = true, options = {}) {
207
+ return formatLocalizedResetTime(isoDate, includeTimezone, options);
219
208
  }
220
209
 
221
- /**
222
- * Format relative time from now to a future date using dayjs
223
- *
224
- * @param {string} isoDate - ISO date string
225
- * @returns {string|null} Relative time string (e.g., "1h 34m" or "6d 20h 13m") or null if date is in the past
226
- */
227
- function formatRelativeTime(isoDate) {
228
- if (!isoDate) return null;
229
-
230
- try {
231
- const now = dayjs();
232
- const target = dayjs(isoDate);
233
-
234
- if (!target.isValid()) return null;
235
-
236
- const diffMs = target.diff(now);
237
- if (diffMs < 0) return null; // Past date
238
-
239
- const totalMinutes = Math.floor(diffMs / (1000 * 60));
240
- const totalHours = Math.floor(totalMinutes / 60);
241
- const totalDays = Math.floor(totalHours / 24);
242
-
243
- const days = totalDays;
244
- const hours = totalHours % 24;
245
- const minutes = totalMinutes % 60;
246
-
247
- // If hours >= 24, show days
248
- if (days > 0) {
249
- return `${days}d ${hours}h ${minutes}m`;
250
- }
251
-
252
- return `${hours}h ${minutes}m`;
253
- } catch {
254
- return null;
255
- }
210
+ function formatRelativeTime(isoDate, options = {}) {
211
+ return formatLocalizedRelativeTime(isoDate, options);
256
212
  }
257
213
 
258
214
  /**
@@ -260,8 +216,8 @@ function formatRelativeTime(isoDate) {
260
216
  *
261
217
  * @returns {string} Current time in UTC (e.g., "Dec 3, 6:45pm UTC")
262
218
  */
263
- function formatCurrentTime() {
264
- return dayjs().utc().format('MMM D, h:mma [UTC]');
219
+ function formatCurrentTime(options = {}) {
220
+ return formatLocalizedCurrentTime(options);
265
221
  }
266
222
 
267
223
  /**
@@ -313,6 +269,15 @@ function hasLimitPercentage(window) {
313
269
  return window?.percentage !== null && window?.percentage !== undefined;
314
270
  }
315
271
 
272
+ function getLocalizedResetTime(window, options = {}) {
273
+ if (!window) return null;
274
+ return formatResetTime(window.resetsAt, true, options) || window.resetTime || null;
275
+ }
276
+
277
+ function getLocalizedRelativeReset(window, options = {}, fallbackRelative = null) {
278
+ return formatRelativeTime(window?.resetsAt, options) || localizeCompactDuration(fallbackRelative, options);
279
+ }
280
+
316
281
  /**
317
282
  * Get GitHub API rate limits by calling gh api rate_limit
318
283
  * Returns rate limit info for core, search, graphql, and other resources
@@ -1037,7 +1002,7 @@ export function formatUsageMessage(usage, diskSpace = null, githubRateLimit = nu
1037
1002
  const locale = resolveLimitLocale(options);
1038
1003
  const sections = [];
1039
1004
 
1040
- sections.push(`${lt('current_time', {}, { locale })}: ${formatCurrentTime()}\n`);
1005
+ sections.push(`${lt('current_time', {}, { locale })}: ${formatCurrentTime({ locale })}\n`);
1041
1006
 
1042
1007
  if (cpuLoad) {
1043
1008
  let section = `${lt('cpu', {}, { locale })}\n`;
@@ -1083,10 +1048,12 @@ export function formatUsageMessage(usage, diskSpace = null, githubRateLimit = nu
1083
1048
  const suffix = githubRateLimit.usedPercentage >= DISPLAY_THRESHOLDS.GITHUB_API ? ' ⚠️' : ` ${lt('used', {}, { locale })}`;
1084
1049
  section += `${usedBar} ${githubRateLimit.usedPercentage}%${suffix}\n`;
1085
1050
  section += `${githubRateLimit.used}/${githubRateLimit.limit} ${lt('requests', {}, { locale })}\n`;
1086
- if (githubRateLimit.relativeReset) {
1087
- section += `${formatLimitResetsIn(githubRateLimit.relativeReset, githubRateLimit.resetTime, { locale })}\n`;
1088
- } else if (githubRateLimit.resetTime) {
1089
- section += `${formatLimitResetsAt(githubRateLimit.resetTime, { locale })}\n`;
1051
+ const githubResetTime = getLocalizedResetTime(githubRateLimit, { locale });
1052
+ const githubRelativeReset = getLocalizedRelativeReset(githubRateLimit, { locale }, githubRateLimit.relativeReset);
1053
+ if (githubRelativeReset && githubResetTime) {
1054
+ section += `${formatLimitResetsIn(githubRelativeReset, githubResetTime, { locale })}\n`;
1055
+ } else if (githubResetTime) {
1056
+ section += `${formatLimitResetsAt(githubResetTime, { locale })}\n`;
1090
1057
  }
1091
1058
  sections.push(section);
1092
1059
  }
@@ -1113,12 +1080,13 @@ export function formatUsageMessage(usage, diskSpace = null, githubRateLimit = nu
1113
1080
  const suffix = pct >= DISPLAY_THRESHOLDS.CLAUDE_5_HOUR_SESSION ? ' ⚠️' : ` ${lt('used', {}, { locale })}`;
1114
1081
  sessionSection += `${bar} ${pct}%${suffix}\n`;
1115
1082
 
1116
- if (usage.currentSession.resetTime) {
1117
- const relativeTime = formatRelativeTime(usage.currentSession.resetsAt);
1083
+ const sessionResetTime = getLocalizedResetTime(usage.currentSession, { locale });
1084
+ if (sessionResetTime) {
1085
+ const relativeTime = getLocalizedRelativeReset(usage.currentSession, { locale });
1118
1086
  if (relativeTime) {
1119
- sessionSection += `${formatLimitResetsIn(relativeTime, usage.currentSession.resetTime, { locale })}\n`;
1087
+ sessionSection += `${formatLimitResetsIn(relativeTime, sessionResetTime, { locale })}\n`;
1120
1088
  } else {
1121
- sessionSection += `${formatLimitResetsAt(usage.currentSession.resetTime, { locale })}\n`;
1089
+ sessionSection += `${formatLimitResetsAt(sessionResetTime, { locale })}\n`;
1122
1090
  }
1123
1091
  }
1124
1092
  } else {
@@ -1143,12 +1111,13 @@ export function formatUsageMessage(usage, diskSpace = null, githubRateLimit = nu
1143
1111
  const suffix = pct >= DISPLAY_THRESHOLDS.CLAUDE_WEEKLY ? ' ⚠️' : ` ${lt('used', {}, { locale })}`;
1144
1112
  allModelsSection += `${bar} ${pct}%${suffix}\n`;
1145
1113
 
1146
- if (usage.allModels.resetTime) {
1147
- const relativeTime = formatRelativeTime(usage.allModels.resetsAt);
1114
+ const allModelsResetTime = getLocalizedResetTime(usage.allModels, { locale });
1115
+ if (allModelsResetTime) {
1116
+ const relativeTime = getLocalizedRelativeReset(usage.allModels, { locale });
1148
1117
  if (relativeTime) {
1149
- allModelsSection += `${formatLimitResetsIn(relativeTime, usage.allModels.resetTime, { locale })}\n`;
1118
+ allModelsSection += `${formatLimitResetsIn(relativeTime, allModelsResetTime, { locale })}\n`;
1150
1119
  } else {
1151
- allModelsSection += `${formatLimitResetsAt(usage.allModels.resetTime, { locale })}\n`;
1120
+ allModelsSection += `${formatLimitResetsAt(allModelsResetTime, { locale })}\n`;
1152
1121
  }
1153
1122
  }
1154
1123
  } else {
@@ -1175,12 +1144,13 @@ export function formatUsageMessage(usage, diskSpace = null, githubRateLimit = nu
1175
1144
  const suffix = pct >= DISPLAY_THRESHOLDS.CLAUDE_WEEKLY ? ' ⚠️' : ` ${lt('used', {}, { locale })}`;
1176
1145
  sonnetSection += `${bar} ${pct}%${suffix}\n`;
1177
1146
 
1178
- if (usage.sonnetOnly.resetTime) {
1179
- const relativeTime = formatRelativeTime(usage.sonnetOnly.resetsAt);
1147
+ const sonnetResetTime = getLocalizedResetTime(usage.sonnetOnly, { locale });
1148
+ if (sonnetResetTime) {
1149
+ const relativeTime = getLocalizedRelativeReset(usage.sonnetOnly, { locale });
1180
1150
  if (relativeTime) {
1181
- sonnetSection += `${formatLimitResetsIn(relativeTime, usage.sonnetOnly.resetTime, { locale })}\n`;
1151
+ sonnetSection += `${formatLimitResetsIn(relativeTime, sonnetResetTime, { locale })}\n`;
1182
1152
  } else {
1183
- sonnetSection += `${formatLimitResetsAt(usage.sonnetOnly.resetTime, { locale })}\n`;
1153
+ sonnetSection += `${formatLimitResetsAt(sonnetResetTime, { locale })}\n`;
1184
1154
  }
1185
1155
  }
1186
1156
  } else {
@@ -1233,9 +1203,10 @@ export function formatCodexLimitsSection(codexLimits, codexError = null, options
1233
1203
  const bar = getProgressBar(pct, DISPLAY_THRESHOLDS.CODEX_5_HOUR_SESSION);
1234
1204
  const suffix = pct >= DISPLAY_THRESHOLDS.CODEX_5_HOUR_SESSION ? ' ⚠️' : ` ${lt('used', {}, { locale })}`;
1235
1205
  sessionSection += `${bar} ${pct}%${suffix}\n`;
1236
- if (usage.currentSession.resetTime) {
1237
- const relativeTime = formatRelativeTime(usage.currentSession.resetsAt);
1238
- sessionSection += relativeTime ? `${formatLimitResetsIn(relativeTime, usage.currentSession.resetTime, { locale })}\n` : `${formatLimitResetsAt(usage.currentSession.resetTime, { locale })}\n`;
1206
+ const sessionResetTime = getLocalizedResetTime(usage.currentSession, { locale });
1207
+ if (sessionResetTime) {
1208
+ const relativeTime = getLocalizedRelativeReset(usage.currentSession, { locale });
1209
+ sessionSection += relativeTime ? `${formatLimitResetsIn(relativeTime, sessionResetTime, { locale })}\n` : `${formatLimitResetsAt(sessionResetTime, { locale })}\n`;
1239
1210
  }
1240
1211
  } else {
1241
1212
  sessionSection += `${lt('na', {}, { locale })}\n`;
@@ -1251,9 +1222,10 @@ export function formatCodexLimitsSection(codexLimits, codexError = null, options
1251
1222
  const bar = getProgressBar(pct, DISPLAY_THRESHOLDS.CODEX_WEEKLY);
1252
1223
  const suffix = pct >= DISPLAY_THRESHOLDS.CODEX_WEEKLY ? ' ⚠️' : ` ${lt('used', {}, { locale })}`;
1253
1224
  weeklySection += `${bar} ${pct}%${suffix}\n`;
1254
- if (usage.allModels.resetTime) {
1255
- const relativeTime = formatRelativeTime(usage.allModels.resetsAt);
1256
- weeklySection += relativeTime ? `${formatLimitResetsIn(relativeTime, usage.allModels.resetTime, { locale })}\n` : `${formatLimitResetsAt(usage.allModels.resetTime, { locale })}\n`;
1225
+ const weeklyResetTime = getLocalizedResetTime(usage.allModels, { locale });
1226
+ if (weeklyResetTime) {
1227
+ const relativeTime = getLocalizedRelativeReset(usage.allModels, { locale });
1228
+ weeklySection += relativeTime ? `${formatLimitResetsIn(relativeTime, weeklyResetTime, { locale })}\n` : `${formatLimitResetsAt(weeklyResetTime, { locale })}\n`;
1257
1229
  }
1258
1230
  } else {
1259
1231
  weeklySection += `${lt('na', {}, { locale })}\n`;
@@ -80,6 +80,10 @@ en
80
80
  limits.current_week_sonnet_only "Current week (Sonnet only)"
81
81
  limits.disabled_by_admin "`--show-limits` is disabled by the bot administrator."
82
82
  limits.disk_space "Disk space"
83
+ limits.duration_day_short "d"
84
+ limits.duration_hour_short "h"
85
+ limits.duration_minute_short "m"
86
+ limits.duration_second_short "s"
83
87
  limits.end "End"
84
88
  limits.five_hour_session "5h session"
85
89
  limits.five_min_load_avg "5m load avg"
@@ -92,9 +96,41 @@ en
92
96
  limits.passed "passed"
93
97
  limits.plan "Plan"
94
98
  limits.ram "RAM"
99
+ limits.reason_claude_5_hour_session "Claude 5 hour session limit is {{currentPercent}}% (threshold: {{thresholdPercent}})"
100
+ limits.reason_claude_running "Claude process is already running"
101
+ limits.reason_claude_weekly "Claude weekly limit is {{currentPercent}}% (threshold: {{thresholdPercent}})"
102
+ limits.reason_codex_5_hour_session "Codex 5 hour session limit is {{currentPercent}}% (threshold: {{thresholdPercent}})"
103
+ limits.reason_codex_running "Codex process is already running"
104
+ limits.reason_codex_weekly "Codex weekly limit is {{currentPercent}}% (threshold: {{thresholdPercent}})"
105
+ limits.reason_cpu_usage "CPU usage is {{currentPercent}}% (threshold: {{thresholdPercent}})"
106
+ limits.reason_disk_usage "Disk usage is {{currentPercent}}% (threshold: {{thresholdPercent}})"
107
+ limits.reason_gemini_running "Gemini CLI process is already running"
108
+ limits.reason_github_api "GitHub API usage is {{currentPercent}}% (threshold: {{thresholdPercent}})"
109
+ limits.reason_min_interval "Minimum interval between commands not reached"
110
+ limits.reason_qwen_running "Qwen Code process is already running"
111
+ limits.reason_ram_usage "RAM usage is {{currentPercent}}% (threshold: {{thresholdPercent}})"
112
+ limits.reason_threshold_exceeded "{{metric}} threshold exceeded"
113
+ limits.remaining "{{duration}} remaining"
95
114
  limits.requests "requests"
96
115
  limits.resets_at "Resets {{time}}"
97
116
  limits.resets_in "Resets in {{duration}}"
117
+ limits.resource_limit_exceeded "Resource limit exceeded"
118
+ limits.solve_queue_status "Solve Queue Status"
119
+ limits.queue_completed "Completed"
120
+ limits.queue_failed "Failed"
121
+ limits.queue_and_more "and {{count}} more"
122
+ limits.queue_pending "pending"
123
+ limits.queue_processing "processing"
124
+ limits.queue_processes "{{count}} processes"
125
+ limits.queue_status_cancelled "cancelled"
126
+ limits.queue_status_failed "failed"
127
+ limits.queue_status_queued "queued"
128
+ limits.queue_status_started "started"
129
+ limits.queue_status_starting "starting"
130
+ limits.queue_status_waiting "waiting"
131
+ limits.queue_waiting_current_command "waiting for current command"
132
+ limits.queue_waiting_in_queue "Waiting in queue"
133
+ limits.queues "Queues"
98
134
  limits.seven_day_all_models "7d all models"
99
135
  limits.seven_day_sonnet_only "7d Sonnet only"
100
136
  limits.session "session"
@@ -108,9 +144,11 @@ en
108
144
  telegram.gathering_version "🔄 Gathering version information..."
109
145
  telegram.usage_limits_title "📊 *Usage Limits*"
110
146
  telegram.version_information_title "🤖 *Version Information*"
147
+ telegram.formatting_fallback_warning "⚠️ Formatting error detected. Showing plain text fallback."
111
148
  telegram.limits_only_in_groups "❌ The /limits command only works in group chats. Please add this bot to a group and make it an admin."
112
149
  telegram.version_only_in_groups "❌ The /version command only works in group chats. Please add this bot to a group and make it an admin."
113
150
  telegram.solve_only_in_groups "❌ The {{commandDisplay}} command only works in group chats. Please add this bot to a group and make it an admin."
151
+ telegram.solve_queue_only_in_groups "❌ The /solve_queue command only works in group chats. Please add this bot to a group and make it an admin."
114
152
  telegram.hive_only_in_groups "❌ The /hive command only works in group chats. Please add this bot to a group and make it an admin."
115
153
  telegram.solve_disabled "❌ The solve command is disabled on this bot instance."
116
154
  telegram.hive_disabled "❌ The /hive command is disabled on this bot instance."
@@ -215,6 +253,20 @@ en
215
253
  language.ru "Russian"
216
254
  language.zh "Chinese"
217
255
  language.hi "Hindi"
256
+ version.ai_agents "AI Agents"
257
+ version.browsers "Browsers"
258
+ version.browser_automation "Browser Automation"
259
+ version.connected "connected"
260
+ version.development_tools "Development Tools"
261
+ version.environment "Environment"
262
+ version.architecture "Architecture"
263
+ version.kernel "Kernel"
264
+ version.not_connected "not connected"
265
+ version.os "OS"
266
+ version.platform "Platform"
267
+ version.process_running_restart_needed "Process running: `{{processVersion}}` (restart needed)"
268
+ version.system "System"
269
+ version.version "Version"
218
270
  prompt.user.issue_to_solve "Issue to solve: {{issueUrl}}"
219
271
  prompt.user.issue_linked_to_pr "Issue to solve: Issue linked to PR #{{prNumber}}"
220
272
  prompt.user.prepared_branch "Your prepared branch: {{branchName}}"
@@ -80,6 +80,10 @@ hi
80
80
  limits.current_week_sonnet_only "वर्तमान सप्ताह (केवल Sonnet)"
81
81
  limits.disabled_by_admin "`--show-limits` बॉट व्यवस्थापक द्वारा अक्षम है।"
82
82
  limits.disk_space "डिस्क स्थान"
83
+ limits.duration_day_short "दि"
84
+ limits.duration_hour_short "घं"
85
+ limits.duration_minute_short "मि"
86
+ limits.duration_second_short "से"
83
87
  limits.end "समाप्ति"
84
88
  limits.five_hour_session "5 घंटे का सत्र"
85
89
  limits.five_min_load_avg "5 मिनट औसत लोड"
@@ -92,9 +96,41 @@ hi
92
96
  limits.passed "बीता"
93
97
  limits.plan "प्लान"
94
98
  limits.ram "RAM"
99
+ limits.reason_claude_5_hour_session "Claude 5 घंटे सत्र सीमा {{currentPercent}}% है (थ्रेशोल्ड: {{thresholdPercent}})"
100
+ limits.reason_claude_running "Claude प्रक्रिया पहले से चल रही है"
101
+ limits.reason_claude_weekly "Claude साप्ताहिक सीमा {{currentPercent}}% है (थ्रेशोल्ड: {{thresholdPercent}})"
102
+ limits.reason_codex_5_hour_session "Codex 5 घंटे सत्र सीमा {{currentPercent}}% है (थ्रेशोल्ड: {{thresholdPercent}})"
103
+ limits.reason_codex_running "Codex प्रक्रिया पहले से चल रही है"
104
+ limits.reason_codex_weekly "Codex साप्ताहिक सीमा {{currentPercent}}% है (थ्रेशोल्ड: {{thresholdPercent}})"
105
+ limits.reason_cpu_usage "CPU उपयोग {{currentPercent}}% है (थ्रेशोल्ड: {{thresholdPercent}})"
106
+ limits.reason_disk_usage "डिस्क उपयोग {{currentPercent}}% है (थ्रेशोल्ड: {{thresholdPercent}})"
107
+ limits.reason_gemini_running "Gemini CLI प्रक्रिया पहले से चल रही है"
108
+ limits.reason_github_api "GitHub API उपयोग {{currentPercent}}% है (थ्रेशोल्ड: {{thresholdPercent}})"
109
+ limits.reason_min_interval "कमांडों के बीच न्यूनतम अंतराल अभी पूरा नहीं हुआ"
110
+ limits.reason_qwen_running "Qwen Code प्रक्रिया पहले से चल रही है"
111
+ limits.reason_ram_usage "RAM उपयोग {{currentPercent}}% है (थ्रेशोल्ड: {{thresholdPercent}})"
112
+ limits.reason_threshold_exceeded "{{metric}} थ्रेशोल्ड पार हो गया"
113
+ limits.remaining "{{duration}} शेष"
95
114
  limits.requests "अनुरोध"
96
115
  limits.resets_at "{{time}} रीसेट"
97
116
  limits.resets_in "{{duration}} में रीसेट"
117
+ limits.resource_limit_exceeded "संसाधन सीमा पार हो गई"
118
+ limits.solve_queue_status "Solve कतार स्थिति"
119
+ limits.queue_completed "पूर्ण"
120
+ limits.queue_failed "विफल"
121
+ limits.queue_and_more "और {{count}}"
122
+ limits.queue_pending "प्रतीक्षारत"
123
+ limits.queue_processing "चल रहा"
124
+ limits.queue_processes "{{count}} प्रक्रियाएँ"
125
+ limits.queue_status_cancelled "रद्द"
126
+ limits.queue_status_failed "विफल"
127
+ limits.queue_status_queued "कतार में"
128
+ limits.queue_status_started "शुरू"
129
+ limits.queue_status_starting "शुरू हो रहा"
130
+ limits.queue_status_waiting "प्रतीक्षा"
131
+ limits.queue_waiting_current_command "वर्तमान कमांड की प्रतीक्षा"
132
+ limits.queue_waiting_in_queue "कतार में प्रतीक्षा"
133
+ limits.queues "कतारें"
98
134
  limits.seven_day_all_models "7 दिन सभी मॉडल"
99
135
  limits.seven_day_sonnet_only "7 दिन केवल Sonnet"
100
136
  limits.session "सत्र"
@@ -108,9 +144,11 @@ hi
108
144
  telegram.gathering_version "🔄 संस्करण जानकारी एकत्र की जा रही है..."
109
145
  telegram.usage_limits_title "📊 *उपयोग सीमाएँ*"
110
146
  telegram.version_information_title "🤖 *संस्करण जानकारी*"
147
+ telegram.formatting_fallback_warning "⚠️ फ़ॉर्मैटिंग त्रुटि मिली। सादा पाठ fallback दिखाया जा रहा है।"
111
148
  telegram.limits_only_in_groups "❌ /limits कमांड केवल समूह चैट में काम करती है। कृपया बॉट को समूह में जोड़ें और व्यवस्थापक बनाएँ।"
112
149
  telegram.version_only_in_groups "❌ /version कमांड केवल समूह चैट में काम करती है। कृपया बॉट को समूह में जोड़ें और व्यवस्थापक बनाएँ।"
113
150
  telegram.solve_only_in_groups "❌ {{commandDisplay}} कमांड केवल समूह चैट में काम करती है। कृपया बॉट को समूह में जोड़ें और व्यवस्थापक बनाएँ।"
151
+ telegram.solve_queue_only_in_groups "❌ /solve_queue कमांड केवल समूह चैट में काम करती है। कृपया बॉट को समूह में जोड़ें और व्यवस्थापक बनाएँ।"
114
152
  telegram.hive_only_in_groups "❌ /hive कमांड केवल समूह चैट में काम करती है। कृपया बॉट को समूह में जोड़ें और व्यवस्थापक बनाएँ।"
115
153
  telegram.solve_disabled "❌ इस बॉट इंस्टेंस पर solve कमांड अक्षम है।"
116
154
  telegram.hive_disabled "❌ इस बॉट इंस्टेंस पर /hive कमांड अक्षम है।"
@@ -215,6 +253,20 @@ hi
215
253
  language.ru "रूसी"
216
254
  language.zh "चीनी"
217
255
  language.hi "हिन्दी"
256
+ version.ai_agents "AI एजेंट"
257
+ version.browsers "ब्राउज़र"
258
+ version.browser_automation "ब्राउज़र ऑटोमेशन"
259
+ version.connected "कनेक्टेड"
260
+ version.development_tools "डेवलपमेंट टूल्स"
261
+ version.environment "पर्यावरण"
262
+ version.architecture "आर्किटेक्चर"
263
+ version.kernel "कर्नेल"
264
+ version.not_connected "कनेक्टेड नहीं"
265
+ version.os "OS"
266
+ version.platform "प्लेटफ़ॉर्म"
267
+ version.process_running_restart_needed "चल रही प्रक्रिया: `{{processVersion}}` (रीस्टार्ट आवश्यक)"
268
+ version.system "सिस्टम"
269
+ version.version "संस्करण"
218
270
  prompt.user.issue_to_solve "हल करने के लिए मुद्दा: {{issueUrl}}"
219
271
  prompt.user.issue_linked_to_pr "हल करने के लिए मुद्दा: PR #{{prNumber}} से जुड़ा मुद्दा"
220
272
  prompt.user.prepared_branch "आपकी तैयार ब्रांच: {{branchName}}"
@@ -80,6 +80,10 @@ ru
80
80
  limits.current_week_sonnet_only "Текущая неделя (только Sonnet)"
81
81
  limits.disabled_by_admin "`--show-limits` отключён администратором бота."
82
82
  limits.disk_space "Дисковое пространство"
83
+ limits.duration_day_short "д"
84
+ limits.duration_hour_short "ч"
85
+ limits.duration_minute_short "мин"
86
+ limits.duration_second_short "с"
83
87
  limits.end "Конец"
84
88
  limits.five_hour_session "5-часовой сеанс"
85
89
  limits.five_min_load_avg "средняя нагрузка за 5 мин"
@@ -92,9 +96,41 @@ ru
92
96
  limits.passed "прошло"
93
97
  limits.plan "План"
94
98
  limits.ram "RAM"
99
+ limits.reason_claude_5_hour_session "Лимит 5-часового сеанса Claude {{currentPercent}}% (порог: {{thresholdPercent}})"
100
+ limits.reason_claude_running "Процесс Claude уже выполняется"
101
+ limits.reason_claude_weekly "Недельный лимит Claude {{currentPercent}}% (порог: {{thresholdPercent}})"
102
+ limits.reason_codex_5_hour_session "Лимит 5-часового сеанса Codex {{currentPercent}}% (порог: {{thresholdPercent}})"
103
+ limits.reason_codex_running "Процесс Codex уже выполняется"
104
+ limits.reason_codex_weekly "Недельный лимит Codex {{currentPercent}}% (порог: {{thresholdPercent}})"
105
+ limits.reason_cpu_usage "Использование CPU {{currentPercent}}% (порог: {{thresholdPercent}})"
106
+ limits.reason_disk_usage "Использование диска {{currentPercent}}% (порог: {{thresholdPercent}})"
107
+ limits.reason_gemini_running "Процесс Gemini CLI уже выполняется"
108
+ limits.reason_github_api "Использование GitHub API {{currentPercent}}% (порог: {{thresholdPercent}})"
109
+ limits.reason_min_interval "Минимальный интервал между командами ещё не прошёл"
110
+ limits.reason_qwen_running "Процесс Qwen Code уже выполняется"
111
+ limits.reason_ram_usage "Использование RAM {{currentPercent}}% (порог: {{thresholdPercent}})"
112
+ limits.reason_threshold_exceeded "Превышен порог {{metric}}"
113
+ limits.remaining "осталось {{duration}}"
95
114
  limits.requests "запросов"
96
115
  limits.resets_at "Сброс {{time}}"
97
116
  limits.resets_in "Сброс через {{duration}}"
117
+ limits.resource_limit_exceeded "Превышен лимит ресурсов"
118
+ limits.solve_queue_status "Статус очереди solve"
119
+ limits.queue_completed "Завершено"
120
+ limits.queue_failed "С ошибкой"
121
+ limits.queue_and_more "и ещё {{count}}"
122
+ limits.queue_pending "ожидает"
123
+ limits.queue_processing "выполняется"
124
+ limits.queue_processes "процессов: {{count}}"
125
+ limits.queue_status_cancelled "отменено"
126
+ limits.queue_status_failed "ошибка"
127
+ limits.queue_status_queued "в очереди"
128
+ limits.queue_status_started "запущено"
129
+ limits.queue_status_starting "запускается"
130
+ limits.queue_status_waiting "ожидание"
131
+ limits.queue_waiting_current_command "ожидание текущей команды"
132
+ limits.queue_waiting_in_queue "Ожидание в очереди"
133
+ limits.queues "Очереди"
98
134
  limits.seven_day_all_models "7 дней, все модели"
99
135
  limits.seven_day_sonnet_only "7 дней, только Sonnet"
100
136
  limits.session "сеанс"
@@ -107,10 +143,12 @@ ru
107
143
  telegram.fetching_limits "🔄 Получение лимитов использования..."
108
144
  telegram.gathering_version "🔄 Сбор информации о версии..."
109
145
  telegram.usage_limits_title "📊 *Лимиты использования*"
110
- telegram.version_information_title "🤖 *Информация о версии*"
146
+ telegram.version_information_title "🤖 *Информация о версиях*"
147
+ telegram.formatting_fallback_warning "⚠️ Обнаружена ошибка форматирования. Показываю обычный текст."
111
148
  telegram.limits_only_in_groups "❌ Команда /limits работает только в групповых чатах. Добавьте бота в группу и сделайте его администратором."
112
149
  telegram.version_only_in_groups "❌ Команда /version работает только в групповых чатах. Добавьте бота в группу и сделайте его администратором."
113
150
  telegram.solve_only_in_groups "❌ Команда {{commandDisplay}} работает только в групповых чатах. Добавьте бота в группу и сделайте его администратором."
151
+ telegram.solve_queue_only_in_groups "❌ Команда /solve_queue работает только в групповых чатах. Добавьте бота в группу и сделайте его администратором."
114
152
  telegram.hive_only_in_groups "❌ Команда /hive работает только в групповых чатах. Добавьте бота в группу и сделайте его администратором."
115
153
  telegram.solve_disabled "❌ Команда solve отключена в этом экземпляре бота."
116
154
  telegram.hive_disabled "❌ Команда /hive отключена в этом экземпляре бота."
@@ -215,6 +253,20 @@ ru
215
253
  language.ru "Русский"
216
254
  language.zh "Китайский"
217
255
  language.hi "Хинди"
256
+ version.ai_agents "AI-агенты"
257
+ version.browsers "Браузеры"
258
+ version.browser_automation "Автоматизация браузера"
259
+ version.connected "подключено"
260
+ version.development_tools "Инструменты разработки"
261
+ version.environment "Среда"
262
+ version.architecture "Архитектура"
263
+ version.kernel "Ядро"
264
+ version.not_connected "не подключено"
265
+ version.os "ОС"
266
+ version.platform "Платформа"
267
+ version.process_running_restart_needed "Запущенный процесс: `{{processVersion}}` (требуется перезапуск)"
268
+ version.system "Система"
269
+ version.version "Версия"
218
270
  prompt.user.issue_to_solve "Задача для решения: {{issueUrl}}"
219
271
  prompt.user.issue_linked_to_pr "Задача для решения: задача, связанная с PR #{{prNumber}}"
220
272
  prompt.user.prepared_branch "Подготовленная ветка: {{branchName}}"