@link-assistant/hive-mind 1.69.3 ā 1.69.5
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 +14 -0
- package/package.json +3 -2
- package/src/auto-language.lib.mjs +94 -0
- package/src/limits-i18n.lib.mjs +71 -0
- package/src/limits.lib.mjs +78 -80
- package/src/locales/en.lino +124 -0
- package/src/locales/hi.lino +124 -0
- package/src/locales/ru.lino +124 -0
- package/src/locales/zh.lino +124 -0
- package/src/session-monitor.lib.mjs +4 -2
- package/src/solve.auto-pr-fork-diagnostic.lib.mjs +70 -0
- package/src/solve.auto-pr.lib.mjs +13 -6
- package/src/solve.branch.lib.mjs +122 -0
- package/src/solve.config.lib.mjs +21 -0
- package/src/solve.error-handlers.lib.mjs +5 -2
- package/src/solve.mjs +13 -11
- package/src/telegram-bot.mjs +69 -135
- package/src/telegram-command-execution.lib.mjs +5 -4
- package/src/telegram-show-limits.lib.mjs +39 -32
- package/src/telegram-solve-queue.lib.mjs +7 -3
- package/src/telegram-ui-messages.lib.mjs +112 -0
- package/src/work-session-formatting.lib.mjs +33 -14
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { t } from './i18n.lib.mjs';
|
|
2
|
+
|
|
3
|
+
function tr(key, params = {}, locale = null) {
|
|
4
|
+
return t(key, params, { locale });
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
function addLine(parts, key, params, locale) {
|
|
8
|
+
parts.push(tr(key, params, locale));
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function buildTelegramInfoBlock({ locale = null, requester = '', urlKind = 'url', url = '', optionsRaw = '', lockedOptions = '' } = {}) {
|
|
12
|
+
const labelKey = urlKind === 'issue' ? 'telegram.info_issue_label' : urlKind === 'pullRequest' ? 'telegram.info_pull_request_label' : 'telegram.info_url_label';
|
|
13
|
+
let infoBlock = `${tr('telegram.info_requested_by_label', {}, locale)}: ${requester}\n${tr(labelKey, {}, locale)}: ${url}`;
|
|
14
|
+
if (optionsRaw) infoBlock += `\n\n${tr('telegram.info_options_label', {}, locale)}: ${optionsRaw}`;
|
|
15
|
+
if (lockedOptions) infoBlock += `${optionsRaw ? '\n' : '\n\n'}${tr('telegram.info_locked_options_label', {}, locale)}: ${lockedOptions}`;
|
|
16
|
+
return infoBlock;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function buildSolveQueuedMessage({ locale = null, tool = 'claude', position = 1, infoBlock = '', reason = '' } = {}) {
|
|
20
|
+
let message = tr('telegram.solve_queued', { tool, position }, locale);
|
|
21
|
+
if (infoBlock) message += `\n\n${infoBlock}`;
|
|
22
|
+
if (reason) message += `\n\n${tr('telegram.waiting_label', {}, locale)}: ${reason}`;
|
|
23
|
+
return message;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export function buildTelegramHelpMessage({ locale = null, chatId, chatType = '', chatTitle = '', topicId = null, isStopped = false, stopInfo = null, stopReason = '', solveEnabled = true, taskEnabled = true, hiveEnabled = true, solveOverrides = [], hiveOverrides = [], showLimitsEnabled = false, isolationBackend = null, modelDescription = '', restrictedMode = false, authorized = null, allowTopicHint = '' } = {}) {
|
|
27
|
+
const message = [];
|
|
28
|
+
addLine(message, 'telegram.help_title', {}, locale);
|
|
29
|
+
message.push('');
|
|
30
|
+
|
|
31
|
+
if (isStopped) {
|
|
32
|
+
addLine(message, 'telegram.help_status_stopped', {}, locale);
|
|
33
|
+
addLine(message, 'telegram.help_reason', { reason: stopReason }, locale);
|
|
34
|
+
if (stopInfo?.stoppedAt) addLine(message, 'telegram.help_stopped', { stoppedAt: stopInfo.stoppedAt.toISOString() }, locale);
|
|
35
|
+
addLine(message, 'telegram.help_resume', {}, locale);
|
|
36
|
+
message.push('');
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
addLine(message, 'telegram.help_diagnostic_information', {}, locale);
|
|
40
|
+
addLine(message, 'telegram.help_chat_id', { chatId }, locale);
|
|
41
|
+
if (topicId) addLine(message, 'telegram.help_topic_id', { topicId }, locale);
|
|
42
|
+
addLine(message, 'telegram.help_chat_type', { chatType }, locale);
|
|
43
|
+
addLine(message, 'telegram.help_chat_title', { chatTitle }, locale);
|
|
44
|
+
message.push('');
|
|
45
|
+
addLine(message, 'telegram.help_available_commands', {}, locale);
|
|
46
|
+
message.push('');
|
|
47
|
+
|
|
48
|
+
if (solveEnabled) {
|
|
49
|
+
addLine(message, 'telegram.help_solve_enabled', {}, locale);
|
|
50
|
+
addLine(message, 'telegram.help_solve_usage', {}, locale);
|
|
51
|
+
addLine(message, 'telegram.help_solve_example', {}, locale);
|
|
52
|
+
addLine(message, 'telegram.help_solve_alias_detail', {}, locale);
|
|
53
|
+
addLine(message, 'telegram.help_solve_reply', {}, locale);
|
|
54
|
+
if (solveOverrides.length > 0) addLine(message, 'telegram.help_locked_options', { options: solveOverrides.join(' ') }, locale);
|
|
55
|
+
message.push('');
|
|
56
|
+
} else {
|
|
57
|
+
addLine(message, 'telegram.help_solve_disabled', {}, locale);
|
|
58
|
+
message.push('');
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
if (taskEnabled) {
|
|
62
|
+
addLine(message, 'telegram.help_task_enabled', {}, locale);
|
|
63
|
+
addLine(message, 'telegram.help_task_usage', {}, locale);
|
|
64
|
+
addLine(message, 'telegram.help_task_example', {}, locale);
|
|
65
|
+
addLine(message, 'telegram.help_split_enabled', {}, locale);
|
|
66
|
+
addLine(message, 'telegram.help_split_usage', {}, locale);
|
|
67
|
+
addLine(message, 'telegram.help_split_example', {}, locale);
|
|
68
|
+
message.push('');
|
|
69
|
+
} else {
|
|
70
|
+
addLine(message, 'telegram.help_task_disabled', {}, locale);
|
|
71
|
+
message.push('');
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
if (hiveEnabled) {
|
|
75
|
+
addLine(message, 'telegram.help_hive_enabled', {}, locale);
|
|
76
|
+
addLine(message, 'telegram.help_hive_usage', {}, locale);
|
|
77
|
+
addLine(message, 'telegram.help_hive_example', {}, locale);
|
|
78
|
+
if (hiveOverrides.length > 0) addLine(message, 'telegram.help_locked_options', { options: hiveOverrides.join(' ') }, locale);
|
|
79
|
+
message.push('');
|
|
80
|
+
} else {
|
|
81
|
+
addLine(message, 'telegram.help_hive_disabled', {}, locale);
|
|
82
|
+
message.push('');
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const simpleCommandKeys = ['telegram.help_solve_queue', 'telegram.help_limits', 'telegram.help_version', 'telegram.help_language', 'telegram.help_accept_invites', 'telegram.help_merge', 'telegram.help_merge_usage', 'telegram.help_merge_description', 'telegram.help_subscribe', 'telegram.help_help', 'telegram.help_stop_start', 'telegram.help_stop_uuid', 'telegram.help_log', 'telegram.help_terminal_watch'];
|
|
86
|
+
for (const key of simpleCommandKeys) addLine(message, key, {}, locale);
|
|
87
|
+
message.push('');
|
|
88
|
+
addLine(message, 'telegram.help_notifications', {}, locale);
|
|
89
|
+
if (isolationBackend) addLine(message, 'telegram.help_isolation_mode', { isolationBackend }, locale);
|
|
90
|
+
message.push('');
|
|
91
|
+
addLine(message, 'telegram.help_group_note', {}, locale);
|
|
92
|
+
message.push('');
|
|
93
|
+
addLine(message, 'telegram.help_common_options', {}, locale);
|
|
94
|
+
addLine(message, 'telegram.help_model_option', { modelDescription }, locale);
|
|
95
|
+
addLine(message, 'telegram.help_base_branch_option', {}, locale);
|
|
96
|
+
addLine(message, 'telegram.help_think_option', {}, locale);
|
|
97
|
+
addLine(message, 'telegram.help_verbose_option', {}, locale);
|
|
98
|
+
if (showLimitsEnabled) addLine(message, 'telegram.help_show_limits_option', {}, locale);
|
|
99
|
+
addLine(message, 'telegram.help_tip', {}, locale);
|
|
100
|
+
|
|
101
|
+
if (restrictedMode) {
|
|
102
|
+
message.push('');
|
|
103
|
+
addLine(message, 'telegram.help_restricted_mode', { authorized: authorized ? tr('telegram.yes', {}, locale) : tr('telegram.no', {}, locale) }, locale);
|
|
104
|
+
if (!authorized && allowTopicHint) addLine(message, 'telegram.help_allow_topic_hint', { allowTopicHint }, locale);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
message.push('');
|
|
108
|
+
message.push('');
|
|
109
|
+
addLine(message, 'telegram.help_troubleshooting_header', {}, locale);
|
|
110
|
+
addLine(message, 'telegram.help_troubleshooting_body', {}, locale);
|
|
111
|
+
return message.join('\n');
|
|
112
|
+
}
|
|
@@ -1,5 +1,12 @@
|
|
|
1
|
+
import { t } from './i18n.lib.mjs';
|
|
2
|
+
|
|
1
3
|
const FAILURE_STATUSES = new Set(['failed', 'cancelled', 'canceled', 'error']);
|
|
2
4
|
|
|
5
|
+
function text(locale, key, fallback, params = {}) {
|
|
6
|
+
if (!locale) return fallback;
|
|
7
|
+
return t(key, params, { locale });
|
|
8
|
+
}
|
|
9
|
+
|
|
3
10
|
function parseDateValue(value) {
|
|
4
11
|
if (!value) return null;
|
|
5
12
|
const date = value instanceof Date ? value : new Date(value);
|
|
@@ -41,15 +48,17 @@ export function formatSessionDurationSeconds(seconds) {
|
|
|
41
48
|
return parts.join(' ');
|
|
42
49
|
}
|
|
43
50
|
|
|
44
|
-
export function formatStartingWorkSessionMessage({ infoBlock = '' } = {}) {
|
|
51
|
+
export function formatStartingWorkSessionMessage({ infoBlock = '', locale = null } = {}) {
|
|
45
52
|
const details = infoBlock ? `\n\n${infoBlock}` : '';
|
|
46
|
-
return
|
|
53
|
+
return `${text(locale, 'telegram.work_session_starting', 'š Starting...')}${details}`;
|
|
47
54
|
}
|
|
48
55
|
|
|
49
|
-
export function formatExecutingWorkSessionMessage({ sessionName = 'unknown', isolationBackend = null, infoBlock = '' } = {}) {
|
|
50
|
-
const
|
|
56
|
+
export function formatExecutingWorkSessionMessage({ sessionName = 'unknown', isolationBackend = null, infoBlock = '', locale = null } = {}) {
|
|
57
|
+
const sessionLabel = text(locale, 'telegram.session_label', 'Session');
|
|
58
|
+
const isolationLabel = text(locale, 'telegram.isolation_label', 'Isolation');
|
|
59
|
+
const isolationInfo = isolationBackend ? `\nš ${isolationLabel}: \`${isolationBackend}\`` : '';
|
|
51
60
|
const details = infoBlock ? `\n\n${infoBlock}` : '';
|
|
52
|
-
return
|
|
61
|
+
return `${text(locale, 'telegram.work_session_executing', 'ā³ Executing...')}\n\nš ${sessionLabel}: \`${sessionName}\`${isolationInfo}${details}`;
|
|
53
62
|
}
|
|
54
63
|
|
|
55
64
|
/**
|
|
@@ -63,18 +72,24 @@ export function formatExecutingWorkSessionMessage({ sessionName = 'unknown', iso
|
|
|
63
72
|
*
|
|
64
73
|
* @see https://github.com/link-assistant/hive-mind/issues/1688
|
|
65
74
|
*/
|
|
66
|
-
export function appendPullRequestLine(infoBlock, pullRequestUrl) {
|
|
75
|
+
export function appendPullRequestLine(infoBlock, pullRequestUrl, { locale = null } = {}) {
|
|
67
76
|
if (!pullRequestUrl || !infoBlock) return infoBlock || '';
|
|
68
77
|
if (infoBlock.includes(pullRequestUrl)) return infoBlock;
|
|
69
78
|
|
|
70
79
|
const lines = infoBlock.split('\n');
|
|
71
80
|
let lastUrlLineIdx = -1;
|
|
81
|
+
const urlLabels = ['Issue', 'Pull request', 'URL'];
|
|
82
|
+
if (locale) {
|
|
83
|
+
urlLabels.push(t('telegram.info_issue_label', {}, { locale }));
|
|
84
|
+
urlLabels.push(t('telegram.info_pull_request_label', {}, { locale }));
|
|
85
|
+
urlLabels.push(t('telegram.info_url_label', {}, { locale }));
|
|
86
|
+
}
|
|
72
87
|
for (let i = 0; i < lines.length; i++) {
|
|
73
|
-
if (
|
|
88
|
+
if (urlLabels.some(label => lines[i].startsWith(`${label}: `))) {
|
|
74
89
|
lastUrlLineIdx = i;
|
|
75
90
|
}
|
|
76
91
|
}
|
|
77
|
-
const prLine =
|
|
92
|
+
const prLine = `${text(locale, 'telegram.info_pull_request_label', 'Pull request')}: ${pullRequestUrl}`;
|
|
78
93
|
if (lastUrlLineIdx === -1) {
|
|
79
94
|
return `${infoBlock}\n${prLine}`;
|
|
80
95
|
}
|
|
@@ -83,24 +98,28 @@ export function appendPullRequestLine(infoBlock, pullRequestUrl) {
|
|
|
83
98
|
return [...before, prLine, ...after].join('\n');
|
|
84
99
|
}
|
|
85
100
|
|
|
86
|
-
export function formatSessionCompletionMessage({ sessionName, sessionInfo, statusResult = null, observedEndTime = new Date(), exitCode = null, infoBlock = '', pullRequestUrl = null, extraSections = [] } = {}) {
|
|
101
|
+
export function formatSessionCompletionMessage({ sessionName, sessionInfo, statusResult = null, observedEndTime = new Date(), exitCode = null, infoBlock = '', pullRequestUrl = null, extraSections = [], locale = null } = {}) {
|
|
87
102
|
const finalExitCode = getSessionCompletionExitCode({ exitCode, statusResult });
|
|
88
103
|
const failed = finalExitCode !== null && finalExitCode !== 0;
|
|
89
104
|
const statusEmoji = failed ? 'ā' : 'ā
';
|
|
90
|
-
const
|
|
91
|
-
const
|
|
105
|
+
const messageLocale = locale || sessionInfo?.locale || null;
|
|
106
|
+
const statusText = failed ? text(messageLocale, 'telegram.work_session_failed', `Work session failed (exit code: ${finalExitCode})`, { exitCode: finalExitCode }) : text(messageLocale, 'telegram.work_session_finished', 'Work session finished successfully');
|
|
107
|
+
const durationLabel = text(messageLocale, 'telegram.duration_label', 'Duration');
|
|
108
|
+
const sessionLabel = text(messageLocale, 'telegram.session_label', 'Session');
|
|
109
|
+
const isolationLabel = text(messageLocale, 'telegram.isolation_label', 'Isolation');
|
|
110
|
+
const isolationInfo = sessionInfo?.isolationBackend ? `\nš ${isolationLabel}: \`${sessionInfo.isolationBackend}\`` : '';
|
|
92
111
|
const startTime = parseDateValue(statusResult?.startTime) || parseDateValue(sessionInfo?.startTime) || observedEndTime;
|
|
93
112
|
const endTime = parseDateValue(statusResult?.endTime) || observedEndTime;
|
|
94
113
|
const durationSeconds = Math.max(0, (endTime.getTime() - startTime.getTime()) / 1000);
|
|
95
114
|
let resolvedInfoBlock = infoBlock || sessionInfo?.infoBlock || '';
|
|
96
115
|
// Issue #1688: When the agent created a PR for an issue-driven /solve, append
|
|
97
116
|
// a 'Pull request:' line so the completion message includes both Issue and PR links.
|
|
98
|
-
if (pullRequestUrl) resolvedInfoBlock = appendPullRequestLine(resolvedInfoBlock, pullRequestUrl);
|
|
117
|
+
if (pullRequestUrl) resolvedInfoBlock = appendPullRequestLine(resolvedInfoBlock, pullRequestUrl, { locale: messageLocale });
|
|
99
118
|
const details = resolvedInfoBlock ? `\n\n${resolvedInfoBlock}` : '';
|
|
100
119
|
|
|
101
120
|
let message = `${statusEmoji} *${statusText}*\n\n`;
|
|
102
|
-
message += `ā±ļø
|
|
103
|
-
message += `š
|
|
121
|
+
message += `ā±ļø ${durationLabel}: ${formatSessionDurationSeconds(durationSeconds)}\n`;
|
|
122
|
+
message += `š ${sessionLabel}: \`${sessionName || 'unknown'}\`${isolationInfo}${details}`;
|
|
104
123
|
|
|
105
124
|
// Issue #594: --show-limits virtual option appends snapshot/delta sections
|
|
106
125
|
// (Markdown code blocks) below the standard completion details.
|