@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 +6 -0
- package/package.json +1 -1
- package/src/interactive-mode.lib.mjs +61 -5
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
|
@@ -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
|
|
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
|
-
|
|
59
|
-
import {
|
|
60
|
-
|
|
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
|
|