@link-assistant/hive-mind 1.46.5 → 1.46.6

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
+ ## 1.46.6
4
+
5
+ ### Patch Changes
6
+
7
+ - 6ab718a: Fix --interactive-mode completely broken (#1532): replace promisify(execFile) with spawn-based execFileAsync that correctly pipes stdin to child processes. The Node.js promisify(execFile) silently ignores the `input` option, causing `gh api --input -` to hang forever waiting for stdin data that never arrives, which blocks the entire stream processing loop.
8
+
3
9
  ## 1.46.5
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": "1.46.5",
3
+ "version": "1.46.6",
4
4
  "description": "AI-powered issue solver and hive mind for collaborative problem solving",
5
5
  "main": "src/hive.mjs",
6
6
  "type": "module",
@@ -52,12 +52,67 @@ const CONFIG = {
52
52
  // See: https://github.com/link-assistant/hive-mind/issues/1324
53
53
  import { sanitizeUnicode } from './unicode-sanitization.lib.mjs';
54
54
 
55
- // Use child_process for stdin-based API calls to avoid shell quoting issues
56
- // with large/complex comment bodies containing backticks, quotes, etc.
55
+ // Use child_process.spawn for stdin-based API calls to avoid shell quoting
56
+ // issues with large/complex comment bodies containing backticks, quotes, etc.
57
+ // IMPORTANT: We use spawn (not execFile) because promisify(execFile) silently
58
+ // ignores the `input` option — only the sync variants (execFileSync, execSync,
59
+ // spawnSync) support `input`. Using execFile with `input` causes `gh api --input -`
60
+ // to hang forever waiting for stdin, which blocks the stream processing loop and
61
+ // prevents interactive mode from working at all.
57
62
  // See: https://github.com/link-assistant/hive-mind/issues/1458
58
- import { execFile } from 'node:child_process';
59
- import { promisify } from 'node:util';
60
- const execFileAsync = promisify(execFile);
63
+ // See: https://github.com/link-assistant/hive-mind/issues/1532
64
+ import { spawn } from 'node:child_process';
65
+
66
+ /**
67
+ * Spawn a child process with stdin piping support.
68
+ * Unlike promisify(execFile), this correctly writes `input` to the child's
69
+ * stdin before closing it, so commands like `gh api --input -` work.
70
+ *
71
+ * @param {string} command - The command to run
72
+ * @param {string[]} args - Command arguments
73
+ * @param {Object} [options] - Options
74
+ * @param {string} [options.input] - Data to write to stdin
75
+ * @param {number} [options.maxBuffer=1048576] - Max stdout/stderr buffer size
76
+ * @returns {Promise<{stdout: string, stderr: string}>}
77
+ */
78
+ const execFileAsync = (command, args, options = {}) => {
79
+ return new Promise((resolve, reject) => {
80
+ const { input, maxBuffer = 1024 * 1024, ...spawnOpts } = options;
81
+ const child = spawn(command, args, { ...spawnOpts, stdio: ['pipe', 'pipe', 'pipe'] });
82
+ let stdout = '';
83
+ let stderr = '';
84
+ let stdoutLen = 0;
85
+ let stderrLen = 0;
86
+ child.stdout.on('data', chunk => {
87
+ const str = chunk.toString();
88
+ stdoutLen += str.length;
89
+ if (stdoutLen <= maxBuffer) stdout += str;
90
+ });
91
+ child.stderr.on('data', chunk => {
92
+ const str = chunk.toString();
93
+ stderrLen += str.length;
94
+ if (stderrLen <= maxBuffer) stderr += str;
95
+ });
96
+ child.on('error', reject);
97
+ child.on('close', code => {
98
+ if (code !== 0) {
99
+ const err = new Error(`Command failed: ${command} ${args.join(' ')}\n${stderr}`);
100
+ err.code = code;
101
+ err.stdout = stdout;
102
+ err.stderr = stderr;
103
+ reject(err);
104
+ } else {
105
+ resolve({ stdout, stderr });
106
+ }
107
+ });
108
+ if (input != null) {
109
+ child.stdin.write(input);
110
+ child.stdin.end();
111
+ } else {
112
+ child.stdin.end();
113
+ }
114
+ });
115
+ };
61
116
 
62
117
  /**
63
118
  * Truncate content in the middle, keeping start and end
@@ -1302,6 +1357,7 @@ export const utils = {
1302
1357
  formatCost,
1303
1358
  escapeMarkdown,
1304
1359
  getToolIcon,
1360
+ execFileAsync,
1305
1361
  CONFIG,
1306
1362
  };
1307
1363