@link-assistant/hive-mind 0.51.21 → 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,27 @@
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
+
14
+ ## 0.52.0
15
+
16
+ ### Minor Changes
17
+
18
+ - b280bcc: Add `--prompt-playwright-mcp` flag to control Playwright MCP hints in system prompt
19
+
20
+ Users can now explicitly control whether Playwright MCP browser automation hints appear in the AI's system prompt:
21
+ - Use `--no-prompt-playwright-mcp` to disable hints even when Playwright MCP is installed
22
+ - Use `--prompt-playwright-mcp` to explicitly enable hints
23
+ - Omit the flag to keep the default auto-detection behavior
24
+
3
25
  ## 0.51.21
4
26
 
5
27
  ### Patch Changes
package/README.md CHANGED
@@ -301,100 +301,54 @@ review --repo owner/repo --pr 456
301
301
 
302
302
  ```bash
303
303
  solve <issue-url> [options]
304
-
305
- --model, -m Model (sonnet, opus for claude; grok-code-fast-1, gpt4o for opencode; gpt5, gpt5-codex, o3 for codex; grok, sonnet, haiku for agent)
306
- [default: sonnet for claude, grok-code-fast-1 for opencode, gpt-5 for codex, grok-code-fast-1 for agent]
307
- --tool AI tool (claude, opencode, codex, agent) [default: claude]
308
- --fork, -f Fork repo if no write access [default: false]
309
- --auto-fork Automatically fork public repos without write access (fails for private)
310
- [default: true]
311
- --base-branch, -b Target branch for PR [default: repo default]
312
- --resume, -r Resume from session ID
313
- --verbose, -v Enable verbose logging [default: false]
314
- --dry-run, -n Prepare only, don't execute [default: false]
315
- --only-prepare-command Only prepare and print the command [default: false]
316
- --skip-tool-check Skip tool connection check (use --no-tool-check to disable)
317
- [default: false]
318
- --auto-pull-request-creation Create draft PR before execution [default: true]
319
- --attach-logs Attach logs to PR (⚠️ sensitive) [default: false]
320
- --auto-close-pull-request-on-fail Close PR on fail [default: false]
321
- --auto-continue Continue with existing PR when issue URL is provided
322
- [default: true]
323
- --auto-continue-limit, -c Auto-continue when limit resets [default: false]
324
- --auto-resume-on-errors Auto-resume on network errors (503, etc.)
325
- [default: false]
326
- --auto-continue-only-on-new-comments Fail if no new comments
327
- [default: false]
328
- --auto-commit-uncommitted-changes Auto-commit changes [default: false]
329
- --auto-merge-default-branch-to-pull-request-branch Merge default branch to PR branch
330
- (only in continue mode) [default: false]
331
- --allow-fork-divergence-resolution-using-force-push-with-lease
332
- Allow force-push with --force-with-lease when fork diverges
333
- (DANGEROUS: can overwrite fork history) [default: false]
334
- --prefix-fork-name-with-owner-name Prefix fork name with owner (owner-repo)
335
- Useful for forking repos with same name from different owners
336
- [default: true]
337
- --continue-only-on-feedback Only continue if feedback detected
338
- [default: false]
339
- --watch, -w Monitor for feedback and auto-restart [default: false]
340
- --watch-interval Feedback check interval (seconds) [default: 60]
341
- --min-disk-space Minimum disk space in MB [default: 500]
342
- --log-dir, -l Directory for log files [default: cwd]
343
- --think Thinking level (low, medium, high, max) [optional]
344
- --sentry Enable Sentry error tracking (use --no-sentry to disable)
345
- [default: true]
346
- --auto-cleanup Delete temp directory on completion
347
- [default: true for private repos, false for public repos]
348
- --version Show version number
349
- --help, -h Show help
350
304
  ```
351
305
 
306
+ **Most frequently used options:**
307
+
308
+ | Option | Alias | Description | Default |
309
+ | --------- | ----- | --------------------------------------- | ------- |
310
+ | `--model` | `-m` | AI model to use (sonnet, opus, haiku) | sonnet |
311
+ | `--think` | | Thinking level (low, medium, high, max) | - |
312
+
313
+ **Other useful options:**
314
+
315
+ | Option | Alias | Description | Default |
316
+ | --------------- | ----- | ------------------------------------------------ | ------- |
317
+ | `--tool` | | AI tool (claude, opencode, codex, agent) | claude |
318
+ | `--verbose` | `-v` | Enable verbose logging | false |
319
+ | `--attach-logs` | | Attach logs to PR (⚠️ may expose sensitive data) | false |
320
+ | `--help` | `-h` | Show all available options | - |
321
+
322
+ > **📖 Full options list**: See [docs/CONFIGURATION.md](./docs/CONFIGURATION.md#solve-options) for all available options including forking, auto-continue, watch mode, and experimental features.
323
+
352
324
  ## 🔧 hive Options
353
325
 
354
326
  ```bash
355
327
  hive <github-url> [options]
356
-
357
- --monitor-tag, -t Label to monitor [default: "help wanted"]
358
- --all-issues, -a Monitor all issues (ignore labels) [default: false]
359
- --skip-issues-with-prs, -s Skip issues with existing PRs [default: false]
360
- --concurrency, -c Parallel workers [default: 2]
361
- --pull-requests-per-issue, -p Number of PRs per issue [default: 1]
362
- --model, -m Model (opus, sonnet for claude; grok-code-fast-1, gpt4o for opencode; gpt5, gpt5-codex, o3 for codex; grok, sonnet, haiku for agent)
363
- [default: sonnet for claude, grok-code-fast-1 for opencode, gpt-5 for codex, grok-code-fast-1 for agent]
364
- --tool AI tool (claude, opencode, codex, agent) [default: claude]
365
- --interval, -i Poll interval (seconds) [default: 300]
366
- --max-issues Limit processed issues [default: 0 (unlimited)]
367
- --once Single run (don't monitor) [default: false]
368
- --dry-run List issues without processing [default: false]
369
- --skip-tool-check Skip tool connection check (use --no-tool-check to disable)
370
- [default: false]
371
- --verbose, -v Enable verbose logging [default: false]
372
- --min-disk-space Minimum disk space in MB [default: 500]
373
- --auto-cleanup Clean /tmp/* /var/tmp/* on success [default: false]
374
- --fork, -f Fork repos if no write access [default: false]
375
- --auto-fork Automatically fork public repos without write access
376
- [default: true]
377
- --attach-logs Attach logs to PRs (⚠️ sensitive) [default: false]
378
- --project-number, -pn GitHub Project number to monitor
379
- --project-owner, -po GitHub Project owner (org or user)
380
- --project-status, -ps Project status column to monitor [default: "Ready"]
381
- --project-mode, -pm Enable project-based monitoring [default: false]
382
- --youtrack-mode Enable YouTrack mode instead of GitHub [default: false]
383
- --youtrack-stage Override YouTrack stage to monitor
384
- --youtrack-project Override YouTrack project code
385
- --target-branch, -tb Target branch for pull requests [default: repo default]
386
- --log-dir, -l Directory for log files [default: cwd]
387
- --auto-continue Pass --auto-continue to solve for each issue
388
- [default: true]
389
- --think Thinking level (low, medium, high, max) [optional]
390
- --sentry Enable Sentry error tracking (use --no-sentry to disable)
391
- [default: true]
392
- --watch, -w Monitor for feedback and auto-restart [default: false]
393
- --issue-order, -o Order issues by date (asc, desc) [default: asc]
394
- --version Show version number
395
- --help, -h Show help
396
328
  ```
397
329
 
330
+ **Most frequently used options:**
331
+
332
+ | Option | Alias | Description | Default |
333
+ | -------------- | ----- | --------------------------------------- | ------- |
334
+ | `--model` | `-m` | AI model to use (sonnet, opus, haiku) | sonnet |
335
+ | `--think` | | Thinking level (low, medium, high, max) | - |
336
+ | `--all-issues` | `-a` | Monitor all issues (ignore labels) | false |
337
+ | `--once` | | Single run (don't monitor continuously) | false |
338
+
339
+ **Other useful options:**
340
+
341
+ | Option | Alias | Description | Default |
342
+ | ------------------------ | ----- | ------------------------------------------------- | ------- |
343
+ | `--tool` | | AI tool (claude, opencode, agent) | claude |
344
+ | `--concurrency` | `-c` | Number of parallel workers | 2 |
345
+ | `--skip-issues-with-prs` | `-s` | Skip issues with existing PRs | false |
346
+ | `--verbose` | `-v` | Enable verbose logging | false |
347
+ | `--attach-logs` | | Attach logs to PRs (⚠️ may expose sensitive data) | false |
348
+ | `--help` | `-h` | Show all available options | - |
349
+
350
+ > **📖 Full options list**: See [docs/CONFIGURATION.md](./docs/CONFIGURATION.md#hive-options) for all available options including project monitoring, YouTrack integration, and experimental features.
351
+
398
352
  ## 🤖 Telegram Bot
399
353
 
400
354
  The Hive Mind includes a Telegram bot interface (SwarmMindBot) for remote command execution.
@@ -641,12 +595,14 @@ grep -E '\(cd /tmp/gh-issue-solver-[0-9]+ && claude --resume [0-9a-f-]{36}\)' hi
641
595
 
642
596
  ## 🔧 Configuration
643
597
 
644
- Authentication is handled through:
598
+ **Authentication:**
645
599
 
646
600
  - `gh auth login` - GitHub CLI authentication
647
601
  - `claude-profiles` - Claude authentication profile migration to server
648
602
 
649
- No environment variable configuration is currently supported.
603
+ **Environment Variables & Advanced Options:**
604
+
605
+ For comprehensive configuration including environment variables, timeouts, retry limits, Telegram bot settings, YouTrack integration, and all CLI options, see [docs/CONFIGURATION.md](./docs/CONFIGURATION.md).
650
606
 
651
607
  ## 🐛 Reporting Issues
652
608
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@link-assistant/hive-mind",
3
- "version": "0.51.21",
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",
@@ -266,6 +266,11 @@ export const createYargsConfig = yargsInstance => {
266
266
  description: 'Create comprehensive case study documentation for the issue including logs, analysis, timeline, root cause investigation, and proposed solutions. Organizes findings into ./docs/case-studies/issue-{id}/ directory. Only supported for --tool claude.',
267
267
  default: false,
268
268
  })
269
+ .option('prompt-playwright-mcp', {
270
+ type: 'boolean',
271
+ description: 'Enable Playwright MCP browser automation hints in system prompt (enabled by default, only takes effect if Playwright MCP is installed). Use --no-prompt-playwright-mcp to disable. Only supported for --tool claude.',
272
+ default: true,
273
+ })
269
274
  .parserConfiguration({
270
275
  'boolean-negation': true,
271
276
  'strip-dashed': false,
package/src/hive.mjs CHANGED
@@ -750,6 +750,7 @@ if (isDirectExecution) {
750
750
  const promptExploreSubAgentFlag = argv.promptExploreSubAgent ? ' --prompt-explore-sub-agent' : '';
751
751
  const promptIssueReportingFlag = argv.promptIssueReporting ? ' --prompt-issue-reporting' : '';
752
752
  const promptCaseStudiesFlag = argv.promptCaseStudies ? ' --prompt-case-studies' : '';
753
+ const promptPlaywrightMcpFlag = argv.promptPlaywrightMcp === true ? ' --prompt-playwright-mcp' : argv.promptPlaywrightMcp === false ? ' --no-prompt-playwright-mcp' : '';
753
754
  // Use spawn to get real-time streaming output while avoiding command-stream's automatic quote addition
754
755
  const { spawn } = await import('child_process');
755
756
 
@@ -800,9 +801,9 @@ if (isDirectExecution) {
800
801
  if (argv.promptExploreSubAgent) args.push('--prompt-explore-sub-agent');
801
802
  if (argv.promptIssueReporting) args.push('--prompt-issue-reporting');
802
803
  if (argv.promptCaseStudies) args.push('--prompt-case-studies');
803
-
804
+ if (argv.promptPlaywrightMcp !== undefined) args.push(argv.promptPlaywrightMcp ? '--prompt-playwright-mcp' : '--no-prompt-playwright-mcp');
804
805
  // Log the actual command being executed so users can investigate/reproduce
805
- const command = `${solveCommand} "${issueUrl}" --model ${argv.model}${toolFlag}${forkFlag}${autoForkFlag}${verboseFlag}${attachLogsFlag}${targetBranchFlag}${logDirFlag}${dryRunFlag}${skipToolConnectionCheckFlag}${autoContinueFlag}${thinkFlag}${promptPlanSubAgentFlag}${noSentryFlag}${watchFlag}${prefixForkNameWithOwnerNameFlag}${interactiveModeFlag}${promptExploreSubAgentFlag}${promptIssueReportingFlag}${promptCaseStudiesFlag}`;
806
+ const command = `${solveCommand} "${issueUrl}" --model ${argv.model}${toolFlag}${forkFlag}${autoForkFlag}${verboseFlag}${attachLogsFlag}${targetBranchFlag}${logDirFlag}${dryRunFlag}${skipToolConnectionCheckFlag}${autoContinueFlag}${thinkFlag}${promptPlanSubAgentFlag}${noSentryFlag}${watchFlag}${prefixForkNameWithOwnerNameFlag}${interactiveModeFlag}${promptExploreSubAgentFlag}${promptIssueReportingFlag}${promptCaseStudiesFlag}${promptPlaywrightMcpFlag}`;
806
807
  await log(` 📋 Command: ${command}`);
807
808
 
808
809
  let exitCode = 0;
@@ -281,6 +281,11 @@ export const createYargsConfig = yargsInstance => {
281
281
  description: 'Create comprehensive case study documentation for the issue including logs, analysis, timeline, root cause investigation, and proposed solutions. Organizes findings into ./docs/case-studies/issue-{id}/ directory. Only supported for --tool claude.',
282
282
  default: false,
283
283
  })
284
+ .option('prompt-playwright-mcp', {
285
+ type: 'boolean',
286
+ description: 'Enable Playwright MCP browser automation hints in system prompt (enabled by default, only takes effect if Playwright MCP is installed). Use --no-prompt-playwright-mcp to disable. Only supported for --tool claude.',
287
+ default: true,
288
+ })
284
289
  .parserConfiguration({
285
290
  'boolean-negation': true,
286
291
  })
package/src/solve.mjs CHANGED
@@ -828,14 +828,18 @@ try {
828
828
  // Default to Claude
829
829
  // Check for Playwright MCP availability if using Claude tool
830
830
  if (argv.tool === 'claude' || !argv.tool) {
831
- const { checkPlaywrightMcpAvailability } = claudeLib;
832
- const playwrightMcpAvailable = await checkPlaywrightMcpAvailability();
833
- if (playwrightMcpAvailable) {
834
- await log('🎭 Playwright MCP detected - enabling browser automation hints', { verbose: true });
835
- argv.promptPlaywrightMcp = true;
831
+ // If flag is true (default), check if Playwright MCP is actually available
832
+ if (argv.promptPlaywrightMcp) {
833
+ const { checkPlaywrightMcpAvailability } = claudeLib;
834
+ const playwrightMcpAvailable = await checkPlaywrightMcpAvailability();
835
+ if (playwrightMcpAvailable) {
836
+ await log('🎭 Playwright MCP detected - enabling browser automation hints', { verbose: true });
837
+ } else {
838
+ await log('ℹ️ Playwright MCP not detected - browser automation hints will be disabled', { verbose: true });
839
+ argv.promptPlaywrightMcp = false;
840
+ }
836
841
  } else {
837
- await log('ℹ️ Playwright MCP not detected - browser automation hints will be disabled', { verbose: true });
838
- argv.promptPlaywrightMcp = false;
842
+ await log('ℹ️ Playwright MCP explicitly disabled via --no-prompt-playwright-mcp', { verbose: true });
839
843
  }
840
844
  }
841
845
  const claudeResult = await executeClaude({
@@ -400,15 +400,19 @@ export const watchForFeedback = async params => {
400
400
 
401
401
  // Check for Playwright MCP availability if using Claude tool
402
402
  if (argv.tool === 'claude' || !argv.tool) {
403
- const playwrightMcpAvailable = await checkPlaywrightMcpAvailability();
404
- if (playwrightMcpAvailable) {
405
- await log('🎭 Playwright MCP detected - enabling browser automation hints', { verbose: true });
406
- argv.promptPlaywrightMcp = true;
403
+ // If flag is true (default), check if Playwright MCP is actually available
404
+ if (argv.promptPlaywrightMcp) {
405
+ const playwrightMcpAvailable = await checkPlaywrightMcpAvailability();
406
+ if (playwrightMcpAvailable) {
407
+ await log('🎭 Playwright MCP detected - enabling browser automation hints', { verbose: true });
408
+ } else {
409
+ await log('ℹ️ Playwright MCP not detected - browser automation hints will be disabled', {
410
+ verbose: true,
411
+ });
412
+ argv.promptPlaywrightMcp = false;
413
+ }
407
414
  } else {
408
- await log('ℹ️ Playwright MCP not detected - browser automation hints will be disabled', {
409
- verbose: true,
410
- });
411
- argv.promptPlaywrightMcp = false;
415
+ await log('ℹ️ Playwright MCP explicitly disabled via --no-prompt-playwright-mcp', { verbose: true });
412
416
  }
413
417
  }
414
418
 
@@ -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