@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 +6 -0
- package/package.json +1 -1
- package/src/limits-i18n.lib.mjs +145 -0
- package/src/limits.lib.mjs +46 -74
- package/src/locales/en.lino +52 -0
- package/src/locales/hi.lino +52 -0
- package/src/locales/ru.lino +53 -1
- package/src/locales/zh.lino +52 -0
- package/src/telegram-bot.mjs +9 -8
- package/src/telegram-safe-reply.lib.mjs +117 -14
- package/src/telegram-solve-queue-command.lib.mjs +18 -6
- package/src/telegram-solve-queue.helpers.lib.mjs +58 -6
- package/src/telegram-solve-queue.lib.mjs +65 -41
- package/src/version-info.lib.mjs +52 -15
package/CHANGELOG.md
CHANGED
package/package.json
CHANGED
package/src/limits-i18n.lib.mjs
CHANGED
|
@@ -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
|
+
}
|
package/src/limits.lib.mjs
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
section += `${
|
|
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
|
-
|
|
1117
|
-
|
|
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,
|
|
1087
|
+
sessionSection += `${formatLimitResetsIn(relativeTime, sessionResetTime, { locale })}\n`;
|
|
1120
1088
|
} else {
|
|
1121
|
-
sessionSection += `${formatLimitResetsAt(
|
|
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
|
-
|
|
1147
|
-
|
|
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,
|
|
1118
|
+
allModelsSection += `${formatLimitResetsIn(relativeTime, allModelsResetTime, { locale })}\n`;
|
|
1150
1119
|
} else {
|
|
1151
|
-
allModelsSection += `${formatLimitResetsAt(
|
|
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
|
-
|
|
1179
|
-
|
|
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,
|
|
1151
|
+
sonnetSection += `${formatLimitResetsIn(relativeTime, sonnetResetTime, { locale })}\n`;
|
|
1182
1152
|
} else {
|
|
1183
|
-
sonnetSection += `${formatLimitResetsAt(
|
|
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
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
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
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
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`;
|
package/src/locales/en.lino
CHANGED
|
@@ -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}}"
|
package/src/locales/hi.lino
CHANGED
|
@@ -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}}"
|
package/src/locales/ru.lino
CHANGED
|
@@ -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}}"
|