mirror of
https://github.com/Syngnat/GoNavi.git
synced 2026-08-25 02:00:09 +08:00
🐛 fix(ai): 隐藏 Claude CLI 后台控制台窗口
- 统一认证检查、非流式与流式请求的 Claude CLI 命令创建 - Windows 启用 HideWindow 与 CREATE_NO_WINDOW,并保留已有启动标志 - 增加跨平台进程配置与 Windows 回归测试
This commit is contained in:
@@ -137,7 +137,7 @@ func CheckClaudeCLILocalAuth(ctx context.Context) error {
|
|||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
args := append(buildClaudeCLILocalAuthIsolationArgs(), "auth", "status", "--json")
|
args := append(buildClaudeCLILocalAuthIsolationArgs(), "auth", "status", "--json")
|
||||||
cmd := claudeCommandContext(ctx, command.Path, args...)
|
cmd := newClaudeCLICommand(ctx, command.Path, args...)
|
||||||
env, err := buildClaudeCLIEnv(ai.ProviderConfig{AuthMode: "local-cli"}, cmd.Environ(), runtime.GOOS, claudeLookPath, fileExists)
|
env, err := buildClaudeCLIEnv(ai.ProviderConfig{AuthMode: "local-cli"}, cmd.Environ(), runtime.GOOS, claudeLookPath, fileExists)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -224,7 +224,7 @@ func (p *ClaudeCLIProvider) Chat(ctx context.Context, req ai.ChatRequest) (*ai.C
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
cmd := claudeCommandContext(ctx, command.Path, args...)
|
cmd := newClaudeCLICommand(ctx, command.Path, args...)
|
||||||
if err := p.setEnv(cmd); err != nil {
|
if err := p.setEnv(cmd); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -301,7 +301,7 @@ func (p *ClaudeCLIProvider) ChatStream(ctx context.Context, req ai.ChatRequest,
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
cmd := claudeCommandContext(ctx, command.Path, args...)
|
cmd := newClaudeCLICommand(ctx, command.Path, args...)
|
||||||
if err := p.setEnv(cmd); err != nil {
|
if err := p.setEnv(cmd); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -469,6 +469,12 @@ func isClaudeCLITimeout(ctx context.Context, err error) bool {
|
|||||||
return errors.Is(ctx.Err(), context.DeadlineExceeded) || errors.Is(err, context.DeadlineExceeded)
|
return errors.Is(ctx.Err(), context.DeadlineExceeded) || errors.Is(err, context.DeadlineExceeded)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func newClaudeCLICommand(ctx context.Context, name string, args ...string) *exec.Cmd {
|
||||||
|
cmd := claudeCommandContext(ctx, name, args...)
|
||||||
|
configureClaudeCLICommand(cmd)
|
||||||
|
return cmd
|
||||||
|
}
|
||||||
|
|
||||||
func claudeCLIEndpointForLog(config ai.ProviderConfig) string {
|
func claudeCLIEndpointForLog(config ai.ProviderConfig) string {
|
||||||
baseURL := strings.TrimRight(strings.TrimSpace(config.BaseURL), "/")
|
baseURL := strings.TrimRight(strings.TrimSpace(config.BaseURL), "/")
|
||||||
if baseURL != "" {
|
if baseURL != "" {
|
||||||
|
|||||||
7
internal/ai/provider/claude_cli_process_other.go
Normal file
7
internal/ai/provider/claude_cli_process_other.go
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
//go:build !windows
|
||||||
|
|
||||||
|
package provider
|
||||||
|
|
||||||
|
import "os/exec"
|
||||||
|
|
||||||
|
func configureClaudeCLICommand(_ *exec.Cmd) {}
|
||||||
21
internal/ai/provider/claude_cli_process_windows.go
Normal file
21
internal/ai/provider/claude_cli_process_windows.go
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
//go:build windows
|
||||||
|
|
||||||
|
package provider
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os/exec"
|
||||||
|
"syscall"
|
||||||
|
)
|
||||||
|
|
||||||
|
const claudeCLIWindowsCreateNoWindow uint32 = 0x08000000
|
||||||
|
|
||||||
|
func configureClaudeCLICommand(cmd *exec.Cmd) {
|
||||||
|
if cmd == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if cmd.SysProcAttr == nil {
|
||||||
|
cmd.SysProcAttr = &syscall.SysProcAttr{}
|
||||||
|
}
|
||||||
|
cmd.SysProcAttr.HideWindow = true
|
||||||
|
cmd.SysProcAttr.CreationFlags |= claudeCLIWindowsCreateNoWindow
|
||||||
|
}
|
||||||
31
internal/ai/provider/claude_cli_process_windows_test.go
Normal file
31
internal/ai/provider/claude_cli_process_windows_test.go
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
//go:build windows
|
||||||
|
|
||||||
|
package provider
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os/exec"
|
||||||
|
"syscall"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestConfigureClaudeCLICommandHidesWindowsConsole(t *testing.T) {
|
||||||
|
const existingCreationFlag uint32 = 0x00000004
|
||||||
|
cmd := &exec.Cmd{
|
||||||
|
SysProcAttr: &syscall.SysProcAttr{CreationFlags: existingCreationFlag},
|
||||||
|
}
|
||||||
|
|
||||||
|
configureClaudeCLICommand(cmd)
|
||||||
|
|
||||||
|
if cmd.SysProcAttr == nil {
|
||||||
|
t.Fatal("expected Windows process attributes to be configured")
|
||||||
|
}
|
||||||
|
if !cmd.SysProcAttr.HideWindow {
|
||||||
|
t.Fatal("expected Claude CLI window to be hidden")
|
||||||
|
}
|
||||||
|
if cmd.SysProcAttr.CreationFlags&claudeCLIWindowsCreateNoWindow == 0 {
|
||||||
|
t.Fatalf("expected CREATE_NO_WINDOW, got creation flags %#x", cmd.SysProcAttr.CreationFlags)
|
||||||
|
}
|
||||||
|
if cmd.SysProcAttr.CreationFlags&existingCreationFlag == 0 {
|
||||||
|
t.Fatalf("expected existing creation flags to be preserved, got %#x", cmd.SysProcAttr.CreationFlags)
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user