@link-assistant/hive-mind 2.1.7 → 2.1.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,11 @@
1
1
  # @link-assistant/hive-mind
2
2
 
3
+ ## 2.1.8
4
+
5
+ ### Patch Changes
6
+
7
+ - 11dab3c: Handle Telegram and CLI commands where a GitHub issue or pull request URL is immediately followed by a long option marker.
8
+
3
9
  ## 2.1.7
4
10
 
5
11
  ### Patch Changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@link-assistant/hive-mind",
3
- "version": "2.1.7",
3
+ "version": "2.1.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",
@@ -0,0 +1,23 @@
1
+ const TYPOGRAPHIC_LONG_OPTION_DASHES = /[\u2013\u2014]/g;
2
+
3
+ const GITHUB_ISSUE_OR_PR_WITH_JOINED_OPTION = new RegExp(['^(', '(?:https?://)?', '(?:www\\.)?', '(?:github\\.com/)?', '[A-Za-z0-9_.-]+/[A-Za-z0-9_.-]+/(?:issues|pull)/\\d+', ')', '(--[A-Za-z][A-Za-z0-9-]*(?:=.*)?)', '$'].join(''));
4
+
5
+ export const normalizeTypographicOptionDashes = value => {
6
+ if (typeof value !== 'string') return value;
7
+ return value.replace(TYPOGRAPHIC_LONG_OPTION_DASHES, '--');
8
+ };
9
+
10
+ export const splitJoinedGitHubLongOptionArg = value => {
11
+ const normalized = normalizeTypographicOptionDashes(value);
12
+ if (typeof normalized !== 'string') return [normalized];
13
+
14
+ const match = normalized.match(GITHUB_ISSUE_OR_PR_WITH_JOINED_OPTION);
15
+ if (!match) return [normalized];
16
+
17
+ return [match[1], match[2]];
18
+ };
19
+
20
+ export const normalizeCliArgs = args => {
21
+ if (!Array.isArray(args)) return [];
22
+ return args.flatMap(splitJoinedGitHubLongOptionArg);
23
+ };
@@ -1,8 +1,10 @@
1
1
  import { getenv, makeConfig, yargs as linoYargs } from 'lino-arguments';
2
2
 
3
+ import { normalizeCliArgs } from './argument-normalization.lib.mjs';
3
4
  import { enhanceUnknownArgumentError } from './option-suggestions.lib.mjs';
4
5
 
5
6
  export { getenv };
7
+ export { normalizeCliArgs, normalizeTypographicOptionDashes, splitJoinedGitHubLongOptionArg } from './argument-normalization.lib.mjs';
6
8
 
7
9
  export const hideBin = argv => argv.slice(2);
8
10
 
@@ -53,7 +55,7 @@ export function addCliCompatibilityAliases(parsed, { positionalAliases = [] } =
53
55
  }
54
56
 
55
57
  export function parseCliArgumentsWithLino({ argv = process.argv, commandName = 'cli', createYargsConfig, positionalAliases = [], lenv = { enabled: true }, env = { enabled: false }, getenv: getenvOptions = { enabled: true } } = {}) {
56
- const fullArgv = ensureFullArgv(argv, commandName);
58
+ const fullArgv = normalizeCliArgs(ensureFullArgv(argv, commandName));
57
59
  let configuredParser = null;
58
60
  let parsed;
59
61
 
package/src/hive.mjs CHANGED
@@ -18,9 +18,9 @@ if (earlyArgs.includes('--version')) {
18
18
  if (earlyArgs.includes('--help') || earlyArgs.includes('-h')) {
19
19
  try {
20
20
  // Load minimal modules needed for help
21
- const { getLinoYargsFactory, hideBin } = await import('./cli-arguments.lib.mjs');
21
+ const { getLinoYargsFactory, hideBin, normalizeCliArgs } = await import('./cli-arguments.lib.mjs');
22
22
  const yargs = getLinoYargsFactory();
23
- const rawArgs = hideBin(process.argv);
23
+ const rawArgs = normalizeCliArgs(hideBin(process.argv));
24
24
  // Reuse createYargsConfig from shared module to avoid duplication
25
25
  const { createYargsConfig } = await import('./hive.config.lib.mjs');
26
26
  const helpYargs = createYargsConfig(yargs(rawArgs)).version(false);
@@ -62,7 +62,7 @@ if (isRunningDirectly) {
62
62
  30000, // 30 second timeout
63
63
  'loading command-stream'
64
64
  );
65
- const { parseCliArgumentsWithLino, hideBin } = await import('./cli-arguments.lib.mjs');
65
+ const { parseCliArgumentsWithLino, hideBin, normalizeCliArgs } = await import('./cli-arguments.lib.mjs');
66
66
  const path = (await withTimeout(use('path'), 30000, 'loading path')).default;
67
67
  const fs = (await withTimeout(use('fs'), 30000, 'loading fs')).promises;
68
68
  // Import shared library functions
@@ -225,7 +225,7 @@ if (isRunningDirectly) {
225
225
  }
226
226
 
227
227
  // Configure command line arguments - GitHub URL as positional argument
228
- const rawArgs = hideBin(process.argv);
228
+ const rawArgs = normalizeCliArgs(hideBin(process.argv));
229
229
  // Use .parse() instead of .argv to ensure .strict() mode works correctly
230
230
  // When you use .argv, strict mode doesn't trigger properly
231
231
  // See: https://github.com/yargs/yargs/issues - .strict() only works with .parse()
@@ -248,7 +248,7 @@ if (isRunningDirectly) {
248
248
 
249
249
  try {
250
250
  argv = parseCliArgumentsWithLino({
251
- argv: process.argv,
251
+ argv: ['node', 'hive', ...rawArgs],
252
252
  commandName: 'hive',
253
253
  createYargsConfig,
254
254
  positionalAliases: ['github-url'],
@@ -11,7 +11,7 @@ import { enhanceErrorMessage, detectMalformedFlags } from './option-suggestions.
11
11
  import { defaultModels, buildModelOptionDescription, resolveDefaultFallbackModel, resolveRuntimeDefaultModel } from './models/index.mjs';
12
12
  import { validateBranchName } from './solve.branch.lib.mjs';
13
13
  import { resolveEscalationConfig, isEscalateEnabled, DEFAULT_ESCALATE_RANGE } from './solve.escalate.lib.mjs';
14
- import { getLinoYargsFactory, hideBin, parseCliArgumentsWithLino } from './cli-arguments.lib.mjs';
14
+ import { getLinoYargsFactory, hideBin, normalizeCliArgs, parseCliArgumentsWithLino } from './cli-arguments.lib.mjs';
15
15
 
16
16
  // Re-export for use by telegram-bot.mjs (avoids extra import lines there)
17
17
  export { detectMalformedFlags };
@@ -737,7 +737,7 @@ export const createYargsConfig = yargsInstance => {
737
737
 
738
738
  // Parse command line arguments - now needs yargs and hideBin passed in
739
739
  export const parseArguments = async (yargs = getLinoYargsFactory(), hideBinFn = hideBin) => {
740
- const rawArgs = hideBinFn(process.argv);
740
+ const rawArgs = normalizeCliArgs(hideBinFn(process.argv));
741
741
 
742
742
  // Issue #1092: Detect malformed flag patterns BEFORE yargs parsing
743
743
  // This catches cases like "-- model" which yargs silently treats as positional arguments
@@ -776,7 +776,7 @@ export const parseArguments = async (yargs = getLinoYargsFactory(), hideBinFn =
776
776
  try {
777
777
  yargsInstance = createYargsConfig(yargs());
778
778
  argv = parseCliArgumentsWithLino({
779
- argv: process.argv,
779
+ argv: ['node', 'solve', ...rawArgs],
780
780
  commandName: 'solve',
781
781
  createYargsConfig,
782
782
  positionalAliases: ['issue-url'],
@@ -8,6 +8,7 @@
8
8
  * @see https://github.com/link-assistant/hive-mind/issues/1618
9
9
  */
10
10
 
11
+ import { normalizeCliArgs } from './argument-normalization.lib.mjs';
11
12
  import { enhanceUnknownArgumentError } from './option-suggestions.lib.mjs';
12
13
 
13
14
  export const TOOL_SOLVE_COMMAND_ALIASES = Object.freeze({
@@ -29,16 +30,13 @@ export function parseCommandArgs(text) {
29
30
  return [];
30
31
  }
31
32
 
32
- // Replace em-dash with double-dash to fix Telegram auto-replacement.
33
- const normalizedArgsText = argsText.replace(/—/g, '--');
34
-
35
33
  const args = [];
36
34
  let currentArg = '';
37
35
  let inQuotes = false;
38
36
  let quoteChar = null;
39
37
 
40
- for (let i = 0; i < normalizedArgsText.length; i++) {
41
- const char = normalizedArgsText[i];
38
+ for (let i = 0; i < argsText.length; i++) {
39
+ const char = argsText[i];
42
40
 
43
41
  if ((char === '"' || char === "'") && !inQuotes) {
44
42
  inQuotes = true;
@@ -60,7 +58,7 @@ export function parseCommandArgs(text) {
60
58
  args.push(currentArg);
61
59
  }
62
60
 
63
- return args;
61
+ return normalizeCliArgs(args);
64
62
  }
65
63
 
66
64
  function toCamelCaseOptionName(name) {