@link-assistant/hive-mind 0.52.0 → 0.52.1

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,16 @@
1
1
  # @link-assistant/hive-mind
2
2
 
3
+ ## 0.52.1
4
+
5
+ ### Patch Changes
6
+
7
+ - 1a4f1a2: Reduce Telegram messages by updating instead of sending new ones
8
+
9
+ The `/solve` and `/hive` commands now update the initial "Starting..." message with the success/error result instead of sending a separate message. This follows the same pattern already used by the `/limits` command.
10
+
11
+ **Before:** Two separate messages per command
12
+ **After:** Single message that gets updated with the result
13
+
3
14
  ## 0.52.0
4
15
 
5
16
  ### Minor Changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@link-assistant/hive-mind",
3
- "version": "0.52.0",
3
+ "version": "0.52.1",
4
4
  "description": "AI-powered issue solver and hive mind for collaborative problem solving",
5
5
  "main": "src/hive.mjs",
6
6
  "type": "module",
@@ -664,6 +664,35 @@ function validateGitHubUrl(args, options = {}) {
664
664
  * @param {string} text - Text to escape
665
665
  * @returns {string} Escaped text safe for Markdown parse_mode
666
666
  */
667
+ /**
668
+ * Execute a start-screen command and update the initial message with the result.
669
+ * Used by both /solve and /hive commands to reduce code duplication.
670
+ *
671
+ * @param {Object} ctx - Telegram context
672
+ * @param {Object} startingMessage - The initial message to update
673
+ * @param {string} commandName - Command name (e.g., 'solve' or 'hive')
674
+ * @param {string[]} args - Command arguments
675
+ * @param {string} infoBlock - Info block with request details
676
+ */
677
+ async function executeAndUpdateMessage(ctx, startingMessage, commandName, args, infoBlock) {
678
+ const result = await executeStartScreen(commandName, args);
679
+
680
+ if (result.warning) {
681
+ await ctx.telegram.editMessageText(startingMessage.chat.id, startingMessage.message_id, undefined, `⚠️ ${result.warning}`, { parse_mode: 'Markdown' });
682
+ return;
683
+ }
684
+
685
+ if (result.success) {
686
+ const sessionNameMatch = result.output.match(/session:\s*(\S+)/i) || result.output.match(/screen -r\s+(\S+)/);
687
+ const sessionName = sessionNameMatch ? sessionNameMatch[1] : 'unknown';
688
+ const response = `✅ ${commandName.charAt(0).toUpperCase() + commandName.slice(1)} command started successfully!\n\n📊 Session: \`${sessionName}\`\n\n${infoBlock}`;
689
+ await ctx.telegram.editMessageText(startingMessage.chat.id, startingMessage.message_id, undefined, response, { parse_mode: 'Markdown' });
690
+ } else {
691
+ const response = `❌ Error executing ${commandName} command:\n\n\`\`\`\n${result.error || result.output}\n\`\`\``;
692
+ await ctx.telegram.editMessageText(startingMessage.chat.id, startingMessage.message_id, undefined, response, { parse_mode: 'Markdown' });
693
+ }
694
+ }
695
+
667
696
  /**
668
697
  * Extract GitHub issue/PR URL from message text
669
698
  * Validates that message contains exactly one GitHub issue/PR link
@@ -1044,34 +1073,15 @@ bot.command(/^solve$/i, async ctx => {
1044
1073
  }
1045
1074
 
1046
1075
  const requester = buildUserMention({ user: ctx.from, parseMode: 'Markdown' });
1047
- // Escape URL to prevent Markdown parsing errors with underscores and asterisks
1048
1076
  const escapedUrl = escapeMarkdown(args[0]);
1049
- let statusMsg = `🚀 Starting solve command...\nRequested by: ${requester}\nURL: ${escapedUrl}\nOptions: ${args.slice(1).join(' ') || 'none'}`;
1077
+ const optionsText = args.slice(1).join(' ') || 'none';
1078
+ let infoBlock = `Requested by: ${requester}\nURL: ${escapedUrl}\nOptions: ${optionsText}`;
1050
1079
  if (solveOverrides.length > 0) {
1051
- statusMsg += `\n🔒 Locked options: ${solveOverrides.join(' ')}`;
1052
- }
1053
- await ctx.reply(statusMsg, { parse_mode: 'Markdown', reply_to_message_id: ctx.message.message_id });
1054
-
1055
- const result = await executeStartScreen('solve', args);
1056
-
1057
- if (result.warning) {
1058
- await ctx.reply(`⚠️ ${result.warning}`, { parse_mode: 'Markdown' });
1059
- return;
1080
+ infoBlock += `\n🔒 Locked options: ${solveOverrides.join(' ')}`;
1060
1081
  }
1061
1082
 
1062
- if (result.success) {
1063
- const sessionNameMatch = result.output.match(/session:\s*(\S+)/i) || result.output.match(/screen -r\s+(\S+)/);
1064
- const sessionName = sessionNameMatch ? sessionNameMatch[1] : 'unknown';
1065
-
1066
- let response = '✅ Solve command started successfully!\n\n';
1067
- response += `📊 *Session:* \`${sessionName}\`\n`;
1068
-
1069
- await ctx.reply(response, { parse_mode: 'Markdown', reply_to_message_id: ctx.message.message_id });
1070
- } else {
1071
- let response = '❌ Error executing solve command:\n\n';
1072
- response += `\`\`\`\n${result.error || result.output}\n\`\`\``;
1073
- await ctx.reply(response, { parse_mode: 'Markdown', reply_to_message_id: ctx.message.message_id });
1074
- }
1083
+ const startingMessage = await ctx.reply(`🚀 Starting solve command...\n\n${infoBlock}`, { parse_mode: 'Markdown', reply_to_message_id: ctx.message.message_id });
1084
+ await executeAndUpdateMessage(ctx, startingMessage, 'solve', args, infoBlock);
1075
1085
  });
1076
1086
 
1077
1087
  bot.command(/^hive$/i, async ctx => {
@@ -1198,34 +1208,15 @@ bot.command(/^hive$/i, async ctx => {
1198
1208
  }
1199
1209
 
1200
1210
  const requester = buildUserMention({ user: ctx.from, parseMode: 'Markdown' });
1201
- // Escape URL to prevent Markdown parsing errors with underscores and asterisks
1202
1211
  const escapedUrl = escapeMarkdown(args[0]);
1203
- let statusMsg = `🚀 Starting hive command...\nRequested by: ${requester}\nURL: ${escapedUrl}\nOptions: ${args.slice(1).join(' ') || 'none'}`;
1212
+ const optionsText = args.slice(1).join(' ') || 'none';
1213
+ let infoBlock = `Requested by: ${requester}\nURL: ${escapedUrl}\nOptions: ${optionsText}`;
1204
1214
  if (hiveOverrides.length > 0) {
1205
- statusMsg += `\n🔒 Locked options: ${hiveOverrides.join(' ')}`;
1215
+ infoBlock += `\n🔒 Locked options: ${hiveOverrides.join(' ')}`;
1206
1216
  }
1207
- await ctx.reply(statusMsg, { parse_mode: 'Markdown', reply_to_message_id: ctx.message.message_id });
1208
-
1209
- const result = await executeStartScreen('hive', args);
1210
1217
 
1211
- if (result.warning) {
1212
- await ctx.reply(`⚠️ ${result.warning}`, { parse_mode: 'Markdown' });
1213
- return;
1214
- }
1215
-
1216
- if (result.success) {
1217
- const sessionNameMatch = result.output.match(/session:\s*(\S+)/i) || result.output.match(/screen -r\s+(\S+)/);
1218
- const sessionName = sessionNameMatch ? sessionNameMatch[1] : 'unknown';
1219
-
1220
- let response = '✅ Hive command started successfully!\n\n';
1221
- response += `📊 *Session:* \`${sessionName}\`\n`;
1222
-
1223
- await ctx.reply(response, { parse_mode: 'Markdown', reply_to_message_id: ctx.message.message_id });
1224
- } else {
1225
- let response = '❌ Error executing hive command:\n\n';
1226
- response += `\`\`\`\n${result.error || result.output}\n\`\`\``;
1227
- await ctx.reply(response, { parse_mode: 'Markdown', reply_to_message_id: ctx.message.message_id });
1228
- }
1218
+ const startingMessage = await ctx.reply(`🚀 Starting hive command...\n\n${infoBlock}`, { parse_mode: 'Markdown', reply_to_message_id: ctx.message.message_id });
1219
+ await executeAndUpdateMessage(ctx, startingMessage, 'hive', args, infoBlock);
1229
1220
  });
1230
1221
 
1231
1222
  // Register /top command from separate module