@link-assistant/hive-mind 1.35.2 ā 1.35.4
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 +16 -0
- package/package.json +1 -1
- package/src/buildUserMention.lib.mjs +5 -2
- package/src/solve.auto-merge.lib.mjs +1 -1
- package/src/solve.watch.lib.mjs +1 -1
- package/src/telegram-bot.mjs +37 -22
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,21 @@
|
|
|
1
1
|
# @link-assistant/hive-mind
|
|
2
2
|
|
|
3
|
+
## 1.35.4
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 0df2139: Harden Telegram message formatting: escape special characters in user mentions, options text, and server overrides. Add safeReply with plain text fallback and diagnostic logging when Telegram rejects Markdown. Improve error messages with user identity context for root cause analysis.
|
|
8
|
+
|
|
9
|
+
## 1.35.3
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- 22ae6d6: fix: rename "attempt" to "iteration" in auto-restart messages (Issue #1456)
|
|
14
|
+
|
|
15
|
+
The auto-restart PR comment title and log message now use "iteration" instead of "attempt" to match the project's terminology. Affected messages:
|
|
16
|
+
- PR comment: `Auto-restart triggered (iteration N)` (was `attempt N`)
|
|
17
|
+
- Log: `Exiting auto-restart mode after N iterations` (was `attempts`)
|
|
18
|
+
|
|
3
19
|
## 1.35.2
|
|
4
20
|
|
|
5
21
|
### Patch Changes
|
package/package.json
CHANGED
|
@@ -40,9 +40,12 @@ export function buildUserMention({ user, id: idParam, username: usernameParam, f
|
|
|
40
40
|
const link = username ? `https://t.me/${username}` : `tg://user?id=${id}`;
|
|
41
41
|
|
|
42
42
|
switch (parseMode) {
|
|
43
|
-
case 'Markdown':
|
|
43
|
+
case 'Markdown': {
|
|
44
44
|
// Legacy Markdown: [text](url)
|
|
45
|
-
|
|
45
|
+
// Escape _ and * in display name to prevent "can't find end of entity" errors (issue #1460)
|
|
46
|
+
const escapedMarkdownName = displayName.replace(/_/g, '\\_').replace(/\*/g, '\\*');
|
|
47
|
+
return `[${escapedMarkdownName}](${link})`;
|
|
48
|
+
}
|
|
46
49
|
case 'MarkdownV2': {
|
|
47
50
|
// MarkdownV2 requires escaping special characters
|
|
48
51
|
const escapedName = displayName.replace(/([_*[\]()~`>#+\-=|{}.!])/g, '\\$1');
|
|
@@ -658,7 +658,7 @@ Once the billing issue is resolved, you can re-run the CI checks or push a new c
|
|
|
658
658
|
// Post a comment to PR about the restart
|
|
659
659
|
// Issue #1356: Include restart count for tracking and add deduplication
|
|
660
660
|
try {
|
|
661
|
-
const commentBody = `## š Auto-restart triggered (
|
|
661
|
+
const commentBody = `## š Auto-restart triggered (iteration ${restartCount})\n\n**Reason:** ${restartReason}\n\nStarting new session to address the issues.\n\n---\n*Auto-restart-until-mergeable mode is active. Will continue until PR becomes mergeable.*`;
|
|
662
662
|
await $`gh pr comment ${prNumber} --repo ${owner}/${repo} --body ${commentBody}`;
|
|
663
663
|
await log(formatAligned('', 'š¬ Posted auto-restart notification to PR', '', 2));
|
|
664
664
|
} catch (commentError) {
|
package/src/solve.watch.lib.mjs
CHANGED
|
@@ -112,7 +112,7 @@ export const watchForFeedback = async params => {
|
|
|
112
112
|
// Check if we've reached max iterations
|
|
113
113
|
if (autoRestartCount >= maxAutoRestartIterations) {
|
|
114
114
|
await log('');
|
|
115
|
-
await log(formatAligned('ā ļø', 'MAX ITERATIONS REACHED', `Exiting auto-restart mode after ${autoRestartCount}
|
|
115
|
+
await log(formatAligned('ā ļø', 'MAX ITERATIONS REACHED', `Exiting auto-restart mode after ${autoRestartCount} iterations`));
|
|
116
116
|
await log(formatAligned('', 'Some uncommitted changes may remain', '', 2));
|
|
117
117
|
await log(formatAligned('', 'Please review and commit manually if needed', '', 2));
|
|
118
118
|
await log('');
|
package/src/telegram-bot.mjs
CHANGED
|
@@ -992,9 +992,11 @@ async function handleSolveCommand(ctx) {
|
|
|
992
992
|
|
|
993
993
|
const requester = buildUserMention({ user: ctx.from, parseMode: 'Markdown' });
|
|
994
994
|
// Issue #1228: Show only user-provided options (exclude locked overrides to avoid duplication)
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
995
|
+
// Issue #1460: Escape options text to prevent Markdown parsing errors
|
|
996
|
+
const userOptionsRaw = userArgs.slice(1).join(' ');
|
|
997
|
+
let infoBlock = `Requested by: ${requester}\nURL: ${escapeMarkdown(normalizedUrl)}`;
|
|
998
|
+
if (userOptionsRaw) infoBlock += `\n\nš Options: ${escapeMarkdown(userOptionsRaw)}`;
|
|
999
|
+
if (solveOverrides.length > 0) infoBlock += `${userOptionsRaw ? '\n' : '\n\n'}š Locked options: ${escapeMarkdown(solveOverrides.join(' '))}`;
|
|
998
1000
|
const solveQueue = getSolveQueue({ verbose: VERBOSE });
|
|
999
1001
|
|
|
1000
1002
|
// Check for duplicate URL in queue
|
|
@@ -1162,10 +1164,12 @@ async function handleHiveCommand(ctx) {
|
|
|
1162
1164
|
const requester = buildUserMention({ user: ctx.from, parseMode: 'Markdown' });
|
|
1163
1165
|
const escapedUrl = escapeMarkdown(args[0]);
|
|
1164
1166
|
// Issue #1228: Show only user-provided options (exclude locked overrides to avoid duplication)
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
+
// Issue #1460: Escape options text to prevent Markdown parsing errors
|
|
1168
|
+
const userOptionsRaw = normalizedArgs.slice(1).join(' ');
|
|
1169
|
+
let infoBlock = `Requested by: ${requester}\nURL: ${escapedUrl}`;
|
|
1170
|
+
if (userOptionsRaw) infoBlock += `\n\nš Options: ${escapeMarkdown(userOptionsRaw)}`;
|
|
1167
1171
|
if (hiveOverrides.length > 0) {
|
|
1168
|
-
infoBlock +=
|
|
1172
|
+
infoBlock += `${userOptionsRaw ? '\n' : '\n\n'}š Locked options: ${escapeMarkdown(hiveOverrides.join(' '))}`;
|
|
1169
1173
|
}
|
|
1170
1174
|
|
|
1171
1175
|
const startingMessage = await ctx.reply(`š Starting hive command...\n\n${infoBlock}`, { parse_mode: 'Markdown', reply_to_message_id: ctx.message.message_id });
|
|
@@ -1305,18 +1309,22 @@ bot.catch((error, ctx) => {
|
|
|
1305
1309
|
let errorMessage;
|
|
1306
1310
|
|
|
1307
1311
|
if (isTelegramParsingError) {
|
|
1308
|
-
//
|
|
1309
|
-
|
|
1310
|
-
|
|
1312
|
+
// Issue #1460: Log detailed context for root cause analysis (always logged, not just in verbose mode)
|
|
1313
|
+
const userInfo = ctx.from ? { id: ctx.from.id, username: ctx.from.username, first_name: ctx.from.first_name, last_name: ctx.from.last_name } : 'unknown';
|
|
1314
|
+
console.error(`[telegram-bot] Parsing error: ${error.message}`);
|
|
1315
|
+
console.error(`[telegram-bot] Parsing error context - user: ${JSON.stringify(userInfo)}, command: ${ctx.message?.text?.split(' ')[0] || 'unknown'}`);
|
|
1316
|
+
console.error(`[telegram-bot] User input text: ${ctx.message?.text || 'none'}`);
|
|
1311
1317
|
if (ctx.message?.text) {
|
|
1318
|
+
const visibleInput = makeSpecialCharsVisible(ctx.message.text, { maxLength: 500 });
|
|
1319
|
+
console.error(`[telegram-bot] User input (special chars visible): ${visibleInput}`);
|
|
1312
1320
|
const cleanedInput = cleanNonPrintableChars(ctx.message.text);
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
if (VERBOSE) {
|
|
1317
|
-
const escapedError = escapeMarkdown(error.message || 'Unknown error');
|
|
1318
|
-
errorMessage += `\n\nš Debug info: ${escapedError}\nUpdate ID: ${ctx.update.update_id}`;
|
|
1321
|
+
if (cleanedInput !== ctx.message.text) {
|
|
1322
|
+
console.error(`[telegram-bot] ${ctx.message.text.length - cleanedInput.length} hidden character(s) detected in input`);
|
|
1323
|
+
}
|
|
1319
1324
|
}
|
|
1325
|
+
|
|
1326
|
+
// Issue #1460: Show user a simple, non-confusing message ā all details are in the logs
|
|
1327
|
+
errorMessage = `ā Failed to send formatted message. Please try your command again.\n\nIf the issue persists, contact support with Update ID: ${ctx.update.update_id}`;
|
|
1320
1328
|
} else {
|
|
1321
1329
|
// Build informative error message for other errors
|
|
1322
1330
|
errorMessage = 'ā An error occurred while processing your request.\n\n';
|
|
@@ -1334,14 +1342,21 @@ bot.catch((error, ctx) => {
|
|
|
1334
1342
|
if (VERBOSE) errorMessage += `\n\nš Debug info: Update ID: ${ctx.update.update_id}`;
|
|
1335
1343
|
}
|
|
1336
1344
|
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
console.error('Failed to send fallback error message:', fallbackError);
|
|
1345
|
+
// Issue #1460: For parsing errors, always send as plain text (we already know Markdown is the problem)
|
|
1346
|
+
// For other errors, try Markdown first, then fall back to plain text
|
|
1347
|
+
if (isTelegramParsingError) {
|
|
1348
|
+
ctx.reply(errorMessage).catch(fallbackError => {
|
|
1349
|
+
console.error('Failed to send plain text error message:', fallbackError);
|
|
1343
1350
|
});
|
|
1344
|
-
}
|
|
1351
|
+
} else {
|
|
1352
|
+
ctx.reply(errorMessage, { parse_mode: 'Markdown' }).catch(replyError => {
|
|
1353
|
+
console.error('Failed to send error message to user:', replyError);
|
|
1354
|
+
const plainMessage = `An error occurred while processing your request. Please try again or contact support.\n\nError: ${error.message || 'Unknown error'}`;
|
|
1355
|
+
ctx.reply(plainMessage).catch(fallbackError => {
|
|
1356
|
+
console.error('Failed to send fallback error message:', fallbackError);
|
|
1357
|
+
});
|
|
1358
|
+
});
|
|
1359
|
+
}
|
|
1345
1360
|
}
|
|
1346
1361
|
});
|
|
1347
1362
|
|