@link-assistant/hive-mind 1.2.6 ā 1.2.7
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 +10 -0
- package/package.json +1 -1
- package/src/telegram-bot.mjs +24 -60
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
# @link-assistant/hive-mind
|
|
2
2
|
|
|
3
|
+
## 1.2.7
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 12831a1: fix: Allow issues_list and pulls_list URLs for /hive command (Issue #1102)
|
|
8
|
+
- Accept issues_list URLs (e.g., `https://github.com/owner/repo/issues`) for /hive command
|
|
9
|
+
- Clean non-printable characters from URLs to prevent Markdown parsing errors
|
|
10
|
+
- Escape special characters in error messages
|
|
11
|
+
- Normalize issues_list URLs to base repo URLs before processing
|
|
12
|
+
|
|
3
13
|
## 1.2.6
|
|
4
14
|
|
|
5
15
|
### Patch Changes
|
package/package.json
CHANGED
package/src/telegram-bot.mjs
CHANGED
|
@@ -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
|
-
|
|
613
|
-
|
|
614
|
-
|
|
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
|
-
|
|
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
|
-
|
|
646
|
-
|
|
647
|
-
|
|
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
|
-
|
|
1178
|
-
|
|
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(
|
|
1157
|
+
const args = mergeArgsWithOverrides(normalizedArgs, hiveOverrides);
|
|
1194
1158
|
|
|
1195
1159
|
// Determine tool from args (default: claude)
|
|
1196
1160
|
let hiveTool = 'claude';
|