Files
tutti/packages/agent/daemon/runtimecmd/executable_windows.go
T
agent-radar 2ed3415fb7
Publish Claude Code Binaries / Stage and publish binaries (push) Canceled after 0s
Publish Tutti App Runtime / Build darwin-arm64 (push) Canceled after 0s
Publish Tutti App Runtime / Build darwin-amd64 (push) Canceled after 0s
Publish Tutti App Runtime / Build linux-amd64 (push) Canceled after 0s
Publish Tutti App Runtime / Build windows-amd64 (push) Canceled after 0s
Sync Tutti Agent Skills / sync (push) Canceled after 0s
Windows Agent Adapters / Test Windows agent adapters (push) Canceled after 0s
Windows Daemon Adapters / Test Windows daemon adapters (push) Canceled after 0s
Publish Tutti App Runtime / Publish runtime catalog (push) Canceled after 0s
源码快照 @ 2026-09-01 (source-only, 剔除非源码素材)
2026-09-01 20:17:27 +08:00

65 lines
1.6 KiB
Go

//go:build windows
package runtimecmd
import (
"os"
"path/filepath"
"strings"
)
const defaultWindowsPathExt = ".COM;.EXE;.BAT;.CMD;.PS1"
func executableNameCandidates(command string, env []string) []string {
if filepath.Ext(command) != "" {
return []string{command}
}
pathExt := strings.TrimSpace(envValue(env, "PATHEXT"))
if pathExt == "" {
pathExt = defaultWindowsPathExt
}
// Prefer Windows PATHEXT launchers before an extensionless file. npm writes
// both a POSIX `opencode` shim and a Windows `opencode.cmd` shim into the
// same prefix; choosing the POSIX shim makes ACP probes hang or fail on
// Windows. Keep the extensionless candidate as a final fallback for managed
// PE launchers such as the Tutti agent binary.
result := make([]string, 0, 6)
seen := map[string]struct{}{}
extensions := strings.Split(pathExt, ";")
hasPowerShell := false
for _, extension := range extensions {
if strings.EqualFold(strings.TrimSpace(extension), ".PS1") {
hasPowerShell = true
break
}
}
if !hasPowerShell {
extensions = append(extensions, ".PS1")
}
for _, extension := range extensions {
extension = strings.TrimSpace(extension)
if extension == "" {
continue
}
if !strings.HasPrefix(extension, ".") {
extension = "." + extension
}
candidate := command + extension
key := strings.ToLower(candidate)
if _, ok := seen[key]; ok {
continue
}
seen[key] = struct{}{}
result = append(result, candidate)
}
if _, ok := seen[strings.ToLower(command)]; !ok {
result = append(result, command)
}
return result
}
func isExecutableFile(path string) bool {
stat, err := os.Stat(path)
return err == nil && !stat.IsDir()
}