chore: merge upstream v12.1.6 + keep local fixes

- Upstream v12.1.6: fix drop orphan flag when filtering empty-string spawn args (#2049)
  → Adopted upstream's cleaner look-behind approach for ProcessRegistry.ts
- Keep: reset completed session on mac sleep/resume (create.ts, not in upstream)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
JOUNGWOOK KWON
2026-04-17 09:04:40 +09:00
10 changed files with 284 additions and 262 deletions
+11 -16
View File
@@ -412,28 +412,23 @@ export function createPidCapturingSpawn(sessionDbId: number) {
const useCmdWrapper = process.platform === 'win32' && spawnOptions.command.endsWith('.cmd');
const env = sanitizeEnv(spawnOptions.env ?? process.env);
// Filter empty string args: Bun's spawn() silently drops empty strings from argv,
// causing subsequent flags to be consumed as values for the preceding flag.
// The Agent SDK may produce empty-string args (e.g., settingSources defaults to []
// which joins to ""). Node preserves these, but Bun drops them, breaking CLI parsing.
//
// FIX: Simply filtering empty strings has the same effect as Bun dropping them —
// it leaves the preceding flag (e.g. --setting-sources) without a value, causing
// the next flag (e.g. --permission-mode) to be consumed as that value.
// Instead, we must remove the entire flag+empty-value pair.
// Filter empty string args AND their preceding flag (Issue #2049).
// The Agent SDK emits ["--setting-sources", ""] when settingSources defaults to [].
// Simply dropping "" leaves an orphan --setting-sources that consumes the next
// flag (e.g. --permission-mode) as its value, crashing Claude Code 2.1.109+ with
// "Invalid setting source: --permission-mode". Drop the flag too so the SDK
// default (no setting sources) is preserved by omission.
const args: string[] = [];
for (let i = 0; i < spawnOptions.args.length; i++) {
const arg = spawnOptions.args[i];
if (arg === '') continue; // skip standalone empty strings
// If this is a --flag followed by an empty string, skip both (remove the pair entirely)
if (arg.startsWith('--') && i + 1 < spawnOptions.args.length && spawnOptions.args[i + 1] === '') {
i++; // skip the empty value too
for (const arg of spawnOptions.args) {
if (arg === '') {
if (args.length > 0 && args[args.length - 1].startsWith('--')) {
args.pop();
}
continue;
}
args.push(arg);
}
const child = useCmdWrapper
? spawn('cmd.exe', ['/d', '/c', spawnOptions.command, ...args], {
cwd: spawnOptions.cwd,