kiro-spec-engine 1.45.6 → 1.45.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 +5 -0
- package/lib/orchestrator/agent-spawner.js +94 -5
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [1.45.7] - 2026-02-13
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
- **Windows CMD 8191 character limit**: `AgentSpawner.spawn()` now writes bootstrap prompt to temp file and spawns via PowerShell on Windows, bypassing cmd.exe's 8191 character command line limit (fixes `The command line is too long` error when bootstrap prompt exceeds 8K characters)
|
|
14
|
+
|
|
10
15
|
## [1.45.6] - 2026-02-13
|
|
11
16
|
|
|
12
17
|
### Fixed
|
|
@@ -83,12 +83,41 @@ class AgentSpawner extends EventEmitter {
|
|
|
83
83
|
const { command, prependArgs } = this._resolveCodexCommand(config);
|
|
84
84
|
|
|
85
85
|
// Spawn the child process (Req 1.1, 1.2)
|
|
86
|
-
|
|
86
|
+
//
|
|
87
|
+
// On Windows we must use a shell to execute .cmd/.ps1 wrappers, but
|
|
88
|
+
// cmd.exe has an 8191-character command-line limit which the bootstrap
|
|
89
|
+
// prompt easily exceeds. To avoid this we write the prompt to a temp
|
|
90
|
+
// file and pass the file path to codex via a shell read expression.
|
|
91
|
+
//
|
|
92
|
+
// Strategy per platform:
|
|
93
|
+
// Windows → write prompt to temp file, spawn via cmd.exe with
|
|
94
|
+
// `type <file>` piped through a FOR /F or via PowerShell.
|
|
95
|
+
// Simplest: use stdin pipe (stdio[0] = 'pipe') so the
|
|
96
|
+
// prompt never appears on the command line at all.
|
|
97
|
+
// Others → pass prompt directly as argument (no length issue).
|
|
98
|
+
const isWindows = process.platform === 'win32';
|
|
99
|
+
const needsShell = isWindows || command === 'npx';
|
|
100
|
+
|
|
101
|
+
// On Windows, remove the prompt from args and pipe it via stdin instead,
|
|
102
|
+
// completely bypassing the cmd.exe 8191-char command-line limit.
|
|
103
|
+
let useStdinPrompt = false;
|
|
104
|
+
let stdinPrompt = null;
|
|
87
105
|
const finalArgs = [...prependArgs, ...args];
|
|
88
106
|
|
|
107
|
+
if (isWindows) {
|
|
108
|
+
// Remove the prompt (last element of args portion) from command line
|
|
109
|
+
// and deliver it via stdin to avoid cmd.exe length limit.
|
|
110
|
+
stdinPrompt = finalArgs.pop(); // remove prompt
|
|
111
|
+
// If the prompt was quoted by the escaping below, unwrap it
|
|
112
|
+
if (stdinPrompt.startsWith('"') && stdinPrompt.endsWith('"')) {
|
|
113
|
+
stdinPrompt = stdinPrompt.slice(1, -1).replace(/\\"/g, '"');
|
|
114
|
+
}
|
|
115
|
+
useStdinPrompt = true;
|
|
116
|
+
}
|
|
117
|
+
|
|
89
118
|
// When shell: true, Node.js concatenates args into a single string without
|
|
90
|
-
// escaping. Arguments containing spaces
|
|
91
|
-
//
|
|
119
|
+
// escaping. Arguments containing spaces must be quoted so the shell does
|
|
120
|
+
// not split them into separate tokens.
|
|
92
121
|
if (needsShell) {
|
|
93
122
|
for (let i = 0; i < finalArgs.length; i++) {
|
|
94
123
|
if (/\s/.test(finalArgs[i])) {
|
|
@@ -98,12 +127,45 @@ class AgentSpawner extends EventEmitter {
|
|
|
98
127
|
}
|
|
99
128
|
|
|
100
129
|
const env = { ...process.env, [apiKeyEnvVar]: apiKey };
|
|
101
|
-
|
|
130
|
+
|
|
131
|
+
// When using stdin for the prompt, write it to a temp file and pass
|
|
132
|
+
// the file path as the last argument using a short placeholder.
|
|
133
|
+
// Codex exec reads the prompt from argv, so we use a temp-file approach:
|
|
134
|
+
// write prompt → pass file path via shell read.
|
|
135
|
+
let promptTmpFile = null;
|
|
136
|
+
if (useStdinPrompt) {
|
|
137
|
+
promptTmpFile = path.join(os.tmpdir(), `kse-prompt-${agentId}-${Date.now()}.txt`);
|
|
138
|
+
fs.writeFileSync(promptTmpFile, stdinPrompt, 'utf-8');
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// Build the final spawn arguments
|
|
142
|
+
let spawnCommand = command;
|
|
143
|
+
let spawnArgs = finalArgs;
|
|
144
|
+
let spawnShell = needsShell;
|
|
145
|
+
|
|
146
|
+
if (promptTmpFile) {
|
|
147
|
+
// On Windows, use PowerShell to read the temp file as the last argument.
|
|
148
|
+
// PowerShell does not have the 8191-char limit of cmd.exe.
|
|
149
|
+
// We construct: powershell -NoProfile -Command "& <command> <args> (Get-Content -Raw '<tmpfile>')"
|
|
150
|
+
const cmdParts = [command, ...finalArgs].map(a => {
|
|
151
|
+
if (a.startsWith('"') && a.endsWith('"')) return a;
|
|
152
|
+
return /\s/.test(a) ? `"${a}"` : a;
|
|
153
|
+
});
|
|
154
|
+
const psPromptExpr = `(Get-Content -Raw '${promptTmpFile.replace(/'/g, "''")}')`;
|
|
155
|
+
cmdParts.push(psPromptExpr);
|
|
156
|
+
|
|
157
|
+
const psCommand = `& ${cmdParts.join(' ')}`;
|
|
158
|
+
spawnCommand = 'powershell.exe';
|
|
159
|
+
spawnArgs = ['-NoProfile', '-Command', psCommand];
|
|
160
|
+
spawnShell = false; // spawning powershell.exe directly
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
const child = spawn(spawnCommand, spawnArgs, {
|
|
102
164
|
cwd: this._workspaceRoot,
|
|
103
165
|
env,
|
|
104
166
|
stdio: ['ignore', 'pipe', 'pipe'],
|
|
105
167
|
windowsHide: true,
|
|
106
|
-
shell:
|
|
168
|
+
shell: spawnShell,
|
|
107
169
|
});
|
|
108
170
|
|
|
109
171
|
const now = new Date().toISOString();
|
|
@@ -120,6 +182,7 @@ class AgentSpawner extends EventEmitter {
|
|
|
120
182
|
retryCount: 0,
|
|
121
183
|
stderr: '',
|
|
122
184
|
events: [],
|
|
185
|
+
_promptTmpFile: promptTmpFile,
|
|
123
186
|
};
|
|
124
187
|
|
|
125
188
|
this._agents.set(agentId, agent);
|
|
@@ -231,6 +294,9 @@ class AgentSpawner extends EventEmitter {
|
|
|
231
294
|
*/
|
|
232
295
|
_setupCloseHandler(agent) {
|
|
233
296
|
agent.process.on('close', async (code) => {
|
|
297
|
+
// Clean up prompt temp file if used
|
|
298
|
+
this._cleanupPromptTmpFile(agent);
|
|
299
|
+
|
|
234
300
|
// Clear timeout timer if still pending
|
|
235
301
|
if (agent._timeoutTimer) {
|
|
236
302
|
clearTimeout(agent._timeoutTimer);
|
|
@@ -274,6 +340,9 @@ class AgentSpawner extends EventEmitter {
|
|
|
274
340
|
|
|
275
341
|
// Handle spawn errors (e.g. command not found)
|
|
276
342
|
agent.process.on('error', async (err) => {
|
|
343
|
+
// Clean up prompt temp file if used
|
|
344
|
+
this._cleanupPromptTmpFile(agent);
|
|
345
|
+
|
|
277
346
|
if (agent._timeoutTimer) {
|
|
278
347
|
clearTimeout(agent._timeoutTimer);
|
|
279
348
|
agent._timeoutTimer = null;
|
|
@@ -311,6 +380,9 @@ class AgentSpawner extends EventEmitter {
|
|
|
311
380
|
agent._timeoutTimer = setTimeout(async () => {
|
|
312
381
|
if (agent.status !== 'running') return;
|
|
313
382
|
|
|
383
|
+
// Clean up prompt temp file if used
|
|
384
|
+
this._cleanupPromptTmpFile(agent);
|
|
385
|
+
|
|
314
386
|
agent.status = 'timeout';
|
|
315
387
|
agent.completedAt = new Date().toISOString();
|
|
316
388
|
|
|
@@ -399,6 +471,23 @@ class AgentSpawner extends EventEmitter {
|
|
|
399
471
|
}
|
|
400
472
|
}
|
|
401
473
|
|
|
474
|
+
/**
|
|
475
|
+
* Remove the temporary prompt file created for Windows spawns.
|
|
476
|
+
* Silently ignores errors (file may already be gone).
|
|
477
|
+
* @param {object} agent
|
|
478
|
+
* @private
|
|
479
|
+
*/
|
|
480
|
+
_cleanupPromptTmpFile(agent) {
|
|
481
|
+
if (agent._promptTmpFile) {
|
|
482
|
+
try {
|
|
483
|
+
fs.unlinkSync(agent._promptTmpFile);
|
|
484
|
+
} catch (_err) {
|
|
485
|
+
// Ignore — file may already be deleted
|
|
486
|
+
}
|
|
487
|
+
agent._promptTmpFile = null;
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
|
|
402
491
|
/**
|
|
403
492
|
* Read API key from Codex CLI's native auth file (~/.codex/auth.json).
|
|
404
493
|
* Returns the key string or null if not found.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "kiro-spec-engine",
|
|
3
|
-
"version": "1.45.
|
|
3
|
+
"version": "1.45.7",
|
|
4
4
|
"description": "kiro-spec-engine (kse) - A CLI tool and npm package for spec-driven development with AI coding assistants. NOT the Kiro IDE desktop application.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"bin": {
|