@link-assistant/hive-mind 1.2.6 → 1.2.8

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,25 @@
1
1
  # @link-assistant/hive-mind
2
2
 
3
+ ## 1.2.8
4
+
5
+ ### Patch Changes
6
+
7
+ - Add case study for issue #1114 analyzing AI solver performance in hyoo-ru/mam_mol repository
8
+
9
+ fix: Propagate --verbose flag to agent tool for debugging DecimalError issues
10
+ - Added --verbose flag propagation to agent tool execution in agent.lib.mjs
11
+ - Created case study documentation for DecimalError root cause analysis
12
+
13
+ ## 1.2.7
14
+
15
+ ### Patch Changes
16
+
17
+ - 12831a1: fix: Allow issues_list and pulls_list URLs for /hive command (Issue #1102)
18
+ - Accept issues_list URLs (e.g., `https://github.com/owner/repo/issues`) for /hive command
19
+ - Clean non-printable characters from URLs to prevent Markdown parsing errors
20
+ - Escape special characters in error messages
21
+ - Normalize issues_list URLs to base repo URLs before processing
22
+
3
23
  ## 1.2.6
4
24
 
5
25
  ### Patch Changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@link-assistant/hive-mind",
3
- "version": "1.2.6",
3
+ "version": "1.2.8",
4
4
  "description": "AI-powered issue solver and hive mind for collaborative problem solving",
5
5
  "main": "src/hive.mjs",
6
6
  "type": "module",
package/src/agent.lib.mjs CHANGED
@@ -364,6 +364,11 @@ export const executeAgentCommand = async params => {
364
364
  // Build agent command arguments
365
365
  let agentArgs = `--model ${mappedModel}`;
366
366
 
367
+ // Propagate verbose flag to agent for detailed debugging output
368
+ if (argv.verbose) {
369
+ agentArgs += ' --verbose';
370
+ }
371
+
367
372
  // Agent supports stdin in both plain text and JSON format
368
373
  // We'll combine system and user prompts into a single message
369
374
  const combinedPrompt = systemPrompt ? `${systemPrompt}\n\n${prompt}` : prompt;
@@ -382,10 +387,11 @@ export const executeAgentCommand = async params => {
382
387
 
383
388
  try {
384
389
  // Pipe the prompt file to agent via stdin
390
+ // Use agentArgs which includes --model and optionally --verbose
385
391
  execCommand = $({
386
392
  cwd: tempDir,
387
393
  mirror: false,
388
- })`cat ${promptFile} | ${agentPath} --model ${mappedModel}`;
394
+ })`cat ${promptFile} | ${agentPath} ${agentArgs}`;
389
395
 
390
396
  await log(`${formatAligned('šŸ“‹', 'Command details:', '')}`);
391
397
  await log(formatAligned('šŸ“‚', 'Working directory:', tempDir, 2));
@@ -595,66 +595,28 @@ function mergeArgsWithOverrides(userArgs, overrides) {
595
595
  return [...filteredArgs, ...overrides];
596
596
  }
597
597
 
598
- /**
599
- * Validate GitHub URL for Telegram bot commands
600
- *
601
- * @param {string[]} args - Command arguments (first arg should be URL)
602
- * @param {Object} options - Validation options
603
- * @param {string[]} options.allowedTypes - Allowed URL types (e.g., ['issue', 'pull'] or ['repository', 'organization', 'user'])
604
- * @param {string} options.commandName - Command name for error messages (e.g., 'solve' or 'hive')
605
- * @param {string} options.exampleUrl - Example URL for error messages
606
- * @returns {{ valid: boolean, error?: string }}
607
- */
598
+ /** Validate GitHub URL for Telegram bot commands. Returns { valid, error?, parsed?, normalizedUrl? } */
608
599
  function validateGitHubUrl(args, options = {}) {
609
- // Default options for /solve command (backward compatibility)
610
600
  const { allowedTypes = ['issue', 'pull'], commandName = 'solve' } = options;
611
-
612
- if (args.length === 0) {
613
- return {
614
- valid: false,
615
- error: `Missing GitHub URL. Usage: /${commandName} <github-url> [options]`,
616
- };
617
- }
618
-
619
- const url = args[0];
620
- if (!url.includes('github.com')) {
621
- return {
622
- valid: false,
623
- error: 'First argument must be a GitHub URL',
624
- };
625
- }
626
-
627
- // Parse the URL to validate structure
601
+ if (args.length === 0) return { valid: false, error: `Missing GitHub URL. Usage: /${commandName} <github-url> [options]` };
602
+ // Issue #1102: Clean non-printable chars (Zero-Width Space, BOM, etc.) from URLs
603
+ const url = cleanNonPrintableChars(args[0]);
604
+ if (!url.includes('github.com')) return { valid: false, error: 'First argument must be a GitHub URL' };
628
605
  const parsed = parseGitHubUrl(url);
629
- if (!parsed.valid) {
630
- return {
631
- valid: false,
632
- error: parsed.error || 'Invalid GitHub URL',
633
- suggestion: parsed.suggestion,
634
- };
635
- }
636
-
637
- // Check if the URL type is allowed for this command
606
+ if (!parsed.valid) return { valid: false, error: parsed.error || 'Invalid GitHub URL', suggestion: parsed.suggestion };
638
607
  if (!allowedTypes.includes(parsed.type)) {
639
608
  const allowedTypesStr = allowedTypes.map(t => (t === 'pull' ? 'pull request' : t)).join(', ');
640
609
  const baseUrl = `https://github.com/${parsed.owner}/${parsed.repo}`;
641
-
642
- // Provide specific, helpful error messages based on the URL type
610
+ const escapedUrl = escapeMarkdown(url),
611
+ escapedBaseUrl = escapeMarkdown(baseUrl); // Issue #1102: escape for Markdown
643
612
  let error;
644
- if (parsed.type === 'issues_list') {
645
- error = `URL points to the issues list page, but you need a specific issue\n\nšŸ’” How to fix:\n1. Open the repository: ${url}\n2. Click on a specific issue\n3. Copy the URL (it should end with /issues/NUMBER)\n\nExample: \`${baseUrl}/issues/1\``;
646
- } else if (parsed.type === 'pulls_list') {
647
- error = `URL points to the pull requests list page, but you need a specific pull request\n\nšŸ’” How to fix:\n1. Open the repository: ${url}\n2. Click on a specific pull request\n3. Copy the URL (it should end with /pull/NUMBER)\n\nExample: \`${baseUrl}/pull/1\``;
648
- } else if (parsed.type === 'repo') {
649
- error = `URL points to a repository, but you need a specific ${allowedTypesStr}\n\nšŸ’” How to fix:\n1. Go to: ${url}/issues\n2. Click on an issue to solve\n3. Use the full URL with the issue number\n\nExample: \`${baseUrl}/issues/1\``;
650
- } else {
651
- error = `URL must be a GitHub ${allowedTypesStr} (not ${parsed.type.replace('_', ' ')})`;
652
- }
653
-
613
+ if (parsed.type === 'issues_list') error = `URL points to the issues list page, but you need a specific issue\n\nšŸ’” How to fix:\n1. Open the repository: ${escapedUrl}\n2. Click on a specific issue\n3. Copy the URL (it should end with /issues/NUMBER)\n\nExample: \`${escapedBaseUrl}/issues/1\``;
614
+ else if (parsed.type === 'pulls_list') error = `URL points to the pull requests list page, but you need a specific pull request\n\nšŸ’” How to fix:\n1. Open the repository: ${escapedUrl}\n2. Click on a specific pull request\n3. Copy the URL (it should end with /pull/NUMBER)\n\nExample: \`${escapedBaseUrl}/pull/1\``;
615
+ else if (parsed.type === 'repo') error = `URL points to a repository, but you need a specific ${allowedTypesStr}\n\nšŸ’” How to fix:\n1. Go to: ${escapedUrl}/issues\n2. Click on an issue to solve\n3. Use the full URL with the issue number\n\nExample: \`${escapedBaseUrl}/issues/1\``;
616
+ else error = `URL must be a GitHub ${allowedTypesStr} (not ${parsed.type.replace('_', ' ')})`;
654
617
  return { valid: false, error };
655
618
  }
656
-
657
- return { valid: true };
619
+ return { valid: true, parsed, normalizedUrl: url };
658
620
  }
659
621
 
660
622
  /**
@@ -1174,23 +1136,25 @@ bot.command(/^hive$/i, async ctx => {
1174
1136
 
1175
1137
  const userArgs = parseCommandArgs(ctx.message.text);
1176
1138
 
1177
- const validation = validateGitHubUrl(userArgs, {
1178
- allowedTypes: ['repo', 'organization', 'user'],
1179
- commandName: 'hive',
1180
- exampleUrl: 'https://github.com/owner/repo',
1181
- });
1139
+ // Issue #1102: Allow issues_list/pulls_list URLs and normalize to repo URLs
1140
+ const validation = validateGitHubUrl(userArgs, { allowedTypes: ['repo', 'organization', 'user', 'issues_list', 'pulls_list'], commandName: 'hive' });
1182
1141
  if (!validation.valid) {
1183
1142
  let errorMsg = `āŒ ${validation.error}`;
1184
- if (validation.suggestion) {
1185
- errorMsg += `\n\nšŸ’” Did you mean: \`${validation.suggestion}\``;
1186
- }
1143
+ if (validation.suggestion) errorMsg += `\n\nšŸ’” Did you mean: \`${escapeMarkdown(validation.suggestion)}\``;
1187
1144
  errorMsg += '\n\nExample: `/hive https://github.com/owner/repo`';
1188
1145
  await ctx.reply(errorMsg, { parse_mode: 'Markdown', reply_to_message_id: ctx.message.message_id });
1189
1146
  return;
1190
1147
  }
1148
+ // Normalize issues_list/pulls_list to base repo URL, or use cleaned URL
1149
+ let normalizedArgs = [...userArgs];
1150
+ const p = validation.parsed;
1151
+ if (p && (p.type === 'issues_list' || p.type === 'pulls_list')) {
1152
+ normalizedArgs[0] = `https://github.com/${p.owner}/${p.repo}`;
1153
+ if (VERBOSE) console.log(`[VERBOSE] /hive: Normalized ${p.type} URL to repo URL: ${normalizedArgs[0]}`);
1154
+ } else if (validation.normalizedUrl && validation.normalizedUrl !== userArgs[0]) normalizedArgs[0] = validation.normalizedUrl;
1191
1155
 
1192
1156
  // Merge user args with overrides
1193
- const args = mergeArgsWithOverrides(userArgs, hiveOverrides);
1157
+ const args = mergeArgsWithOverrides(normalizedArgs, hiveOverrides);
1194
1158
 
1195
1159
  // Determine tool from args (default: claude)
1196
1160
  let hiveTool = 'claude';