mirror of
https://github.com/multica-ai/multica.git
synced 2026-06-17 11:48:42 +02:00
* fix(daemon): use CREATE_NEW_CONSOLE to stop grandchild console popups on Windows (#1521) CREATE_NO_WINDOW strips the console entirely. When the agent CLI then spawns a console-subsystem grandchild (bash, cmd, netstat, findstr, timeout) without itself passing CREATE_NO_WINDOW, Windows allocates a brand-new visible console window per invocation — trading one popup per agent run for N popups per tool call. Switch to CREATE_NEW_CONSOLE + HideWindow=true so the agent gets a hidden console that grandchildren inherit. Stdio pipes still work via STARTF_USESTDHANDLES; no changes needed at the 17 hideAgentWindow call sites. Add a Windows-only regression test asserting CREATE_NEW_CONSOLE is set and CREATE_NO_WINDOW is not, per the #1474 Windows-test follow-up. Root-cause diagnosis by @matrenitski (verified against the shipped multica.exe and the Claude Code CLI it spawns) in issue #1521. * test(agent): use CREATE_NEW_CONSOLE-compatible flag in preservation test CREATE_NEW_PROCESS_GROUP is silently ignored by Windows when combined with CREATE_NEW_CONSOLE, so asserting it 'survives' was only bitwise-true, not semantically meaningful. Switch the example to CREATE_UNICODE_ENVIRONMENT (documented compatible) and also assert a non-flag field (NoInheritHandles) survives to exercise full struct preservation.
33 lines
1.2 KiB
Go
33 lines
1.2 KiB
Go
//go:build windows
|
|
|
|
package agent
|
|
|
|
import (
|
|
"os/exec"
|
|
"syscall"
|
|
)
|
|
|
|
// createNewConsole allocates a fresh console for the child process. Combined
|
|
// with HideWindow=true (STARTF_USESHOWWINDOW + SW_HIDE) the console window
|
|
// stays off-screen, and — critically — any grandchildren the agent spawns
|
|
// (tool subprocesses like bash, cmd, netstat, findstr) inherit this hidden
|
|
// console instead of each allocating their own visible one.
|
|
//
|
|
// Using CREATE_NO_WINDOW here instead would strip the console entirely,
|
|
// which forces Windows to allocate a new visible console per grandchild
|
|
// when the grandchild is a console-subsystem program that doesn't itself
|
|
// pass CREATE_NO_WINDOW — the exact popup storm reported in #1521.
|
|
const createNewConsole = 0x00000010
|
|
|
|
// hideAgentWindow configures cmd to suppress the console window on Windows
|
|
// while still giving descendant processes a hidden console to inherit.
|
|
// Stdio pipes set via cmd.StdoutPipe/StdinPipe keep working because
|
|
// STARTF_USESTDHANDLES takes precedence over the new console's stdio.
|
|
func hideAgentWindow(cmd *exec.Cmd) {
|
|
if cmd.SysProcAttr == nil {
|
|
cmd.SysProcAttr = &syscall.SysProcAttr{}
|
|
}
|
|
cmd.SysProcAttr.HideWindow = true
|
|
cmd.SysProcAttr.CreationFlags |= createNewConsole
|
|
}
|