Files
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

119 lines
3.3 KiB
Go

package browser
import (
"errors"
"fmt"
"os"
"path/filepath"
"runtime"
"strconv"
"strings"
)
const autoConnectSetupHint = "Open Chrome and enable remote debugging at chrome://inspect/#remote-debugging, then try again."
func browserMCPSubprocessEnv() []string {
return []string{
"NO_PROXY=127.0.0.1,localhost,::1",
"no_proxy=127.0.0.1,localhost,::1",
}
}
func resolveAutoConnectMCPConnectionArgs() []string {
if endpoint, ok := stableChromeDevToolsWebSocketEndpoint(); ok {
return []string{"--wsEndpoint", endpoint, "--no-usage-statistics"}
}
return []string{"--autoConnect", "--channel", "stable", "--no-usage-statistics"}
}
func validateAutoConnectChromeReady() error {
if _, err := readStableChromeDevToolsActivePort(); err != nil {
return fmt.Errorf("could not connect to Chrome for reuse mode: %w. %s", err, autoConnectSetupHint)
}
return nil
}
func stableChromeDevToolsWebSocketEndpoint() (endpoint string, ok bool) {
activePort, err := readStableChromeDevToolsActivePort()
if err != nil {
return "", false
}
return fmt.Sprintf("ws://127.0.0.1:%d%s", activePort.port, activePort.path), true
}
func readStableChromeDevToolsActivePort() (devToolsActivePort, error) {
portPath := stableChromeDevToolsActivePortPath()
if portPath == "" {
return devToolsActivePort{}, errors.New("stable Chrome profile path is unavailable on this platform")
}
content, err := os.ReadFile(portPath)
if err != nil {
if os.IsNotExist(err) {
return devToolsActivePort{}, fmt.Errorf("DevToolsActivePort not found at %s", portPath)
}
return devToolsActivePort{}, fmt.Errorf("read DevToolsActivePort: %w", err)
}
activePort, ok := parseDevToolsActivePort(string(content))
if !ok {
return devToolsActivePort{}, fmt.Errorf("invalid DevToolsActivePort at %s", portPath)
}
return activePort, nil
}
func stableChromeDevToolsActivePortPath() string {
home, err := os.UserHomeDir()
if err != nil {
return ""
}
return stableChromeDevToolsActivePortPathFor(runtime.GOOS, home, os.Getenv("LOCALAPPDATA"))
}
func stableChromeDevToolsActivePortPathFor(goos string, home string, localAppData string) string {
switch goos {
case "darwin":
if strings.TrimSpace(home) == "" {
return ""
}
return filepath.Join(home, "Library", "Application Support", "Google", "Chrome", "DevToolsActivePort")
case "linux":
if strings.TrimSpace(home) == "" {
return ""
}
return filepath.Join(home, ".config", "google-chrome", "DevToolsActivePort")
case "windows":
if strings.TrimSpace(localAppData) == "" {
return ""
}
return filepath.Join(localAppData, "Google", "Chrome", "User Data", "DevToolsActivePort")
default:
return ""
}
}
func parseDevToolsActivePort(content string) (devToolsActivePort, bool) {
lines := make([]string, 0, 2)
for _, line := range strings.Split(content, "\n") {
trimmed := strings.TrimSpace(line)
if trimmed != "" {
lines = append(lines, trimmed)
}
}
if len(lines) < 2 {
return devToolsActivePort{}, false
}
port, err := strconv.Atoi(lines[0])
if err != nil || port <= 0 || port > 65535 {
return devToolsActivePort{}, false
}
path := lines[1]
if !strings.HasPrefix(path, "/") {
return devToolsActivePort{}, false
}
return devToolsActivePort{port: port, path: path}, true
}
type devToolsActivePort struct {
port int
path string
}