Skip to content

Commit a1ad60b

Browse files
Pn1koclaude
authored andcommitted
Address code review feedback on profile selection
- Drop dead connectedByInstance map in renderProfilesList; only directory lookup is consulted and the "unresolved host" footer already covers connected hosts whose instanceId did not resolve. - Drop the misleading `--timeout` flag on `obu profiles --connected`; the probe was always hard-capped at 800ms regardless of the flag. - Cap LevelDB scan reads at 32 MB so a pathological file can't OOM the host. chrome.storage.local logs are well under 1 MB in practice. - Clean up unused `picked` return from pickSocketForProfile in dialBrowserSocketForProfile. - Skill: split single-profile guidance into "installed and connected" vs "installed but Chrome closed" so agents prompt the user to open Chrome instead of silently retrying a doomed connection. - Plan TC-2: update the JSON field list to match the actual `obu profiles --json` and `--connected --json` outputs. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent c391a9c commit a1ad60b

3 files changed

Lines changed: 31 additions & 26 deletions

File tree

cmd/open-browser-use/main.go

Lines changed: 14 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,10 @@ const chromeWebStoreUpdateURL = "https://clients2.google.com/service/update2/crx
3535
const chromeWebStoreExtensionURL = "https://chromewebstore.google.com/detail/open-browser-use/" + defaultChromeExtensionID + "?utm_source=open-computer-use"
3636
const betaExtensionPublicKey = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnBLT95WWVnHYH0pOBRH/eP+BWtlKVmLE/RHkERUTI2+PGDSQrbWVabmTw4CZ3yhjko04dijSX2Az8cnp65xh23Dh5mP5TCtiP9LexRFJokd8EsyeFdtKamMYr0hF1ZUc1/8ZpLnetAU65ZMB9VzHQBqpJWeUwuIvecgfRtGklDgJMjnvcq5J6pttZrzWrI/2B0BNufwsTQfEt7qLtDFPHXmUdtZfQbc2EfYFvkXLDAXicYviiocedrsAGIKUxpyQegobhUFL+tNLOuXKBpZlLFQn3xgm5CyGZwN6bueiV/S7reigVTKAMQ8BX0eacT22e8r0UzjsjkugeHOIonIvtQIDAQAB"
3737

38+
// LevelDB log/ldb files for chrome.storage.local are typically under 1 MB; cap
39+
// the scan at 32 MB so a pathological file can't OOM the host.
40+
const maxLevelDBScanBytes = 32 << 20
41+
3842
func main() {
3943
if err := run(os.Args[1:]); err != nil {
4044
fmt.Fprintln(os.Stderr, err)
@@ -747,6 +751,10 @@ func resolveProfileForInstanceID(extensionID string, instanceID string) (directo
747751
if !strings.HasSuffix(name, ".log") && !strings.HasSuffix(name, ".ldb") {
748752
continue
749753
}
754+
info, err := entry.Info()
755+
if err != nil || info.Size() > maxLevelDBScanBytes {
756+
continue
757+
}
750758
payload, err := os.ReadFile(filepath.Join(storageDir, name))
751759
if err != nil {
752760
continue
@@ -1350,7 +1358,6 @@ func newProfilesCommand() *cobra.Command {
13501358
var asJSON bool
13511359
var connected bool
13521360
var socketDir string
1353-
var timeout time.Duration
13541361
cmd := &cobra.Command{
13551362
Use: "profiles",
13561363
Short: "List Chrome profiles that have the Open Browser Use extension installed",
@@ -1362,29 +1369,25 @@ func newProfilesCommand() *cobra.Command {
13621369
}
13631370
var connections []connectedProfileInfo
13641371
if connected {
1365-
connections = probeConnectedProfiles(socketDir, timeout)
1372+
connections = probeConnectedProfiles(socketDir)
13661373
}
13671374
return renderProfilesList(cmd.OutOrStdout(), profiles, connections, connected, asJSON)
13681375
},
13691376
}
13701377
cmd.Flags().BoolVar(&asJSON, "json", false, "emit JSON instead of a human-readable table")
13711378
cmd.Flags().BoolVar(&connected, "connected", false, "also probe running hosts and mark which profile is currently connected")
13721379
cmd.Flags().StringVar(&socketDir, "socket-dir", host.DefaultSocketDir, "directory containing host sockets (used with --connected)")
1373-
cmd.Flags().DurationVar(&timeout, "timeout", 2*time.Second, "per-socket probe timeout (used with --connected)")
13741380
return cmd
13751381
}
13761382

1377-
func probeConnectedProfiles(socketDir string, timeout time.Duration) []connectedProfileInfo {
1383+
const connectedProbeTimeout = 800 * time.Millisecond
1384+
1385+
func probeConnectedProfiles(socketDir string) []connectedProfileInfo {
13781386
candidates, err := listSocketCandidates(socketDir)
13791387
if err != nil || len(candidates) == 0 {
13801388
return nil
13811389
}
1382-
probeTimeout := timeout
1383-
if probeTimeout <= 0 {
1384-
probeTimeout = 800 * time.Millisecond
1385-
} else if probeTimeout > 800*time.Millisecond {
1386-
probeTimeout = 800 * time.Millisecond
1387-
}
1390+
probeTimeout := connectedProbeTimeout
13881391
var out []connectedProfileInfo
13891392
for _, candidate := range candidates {
13901393
conn, err := net.DialTimeout("unix", candidate.path, probeTimeout)
@@ -1403,14 +1406,10 @@ func probeConnectedProfiles(socketDir string, timeout time.Duration) []connected
14031406

14041407
func renderProfilesList(writer io.Writer, profiles []installedChromeProfile, connected []connectedProfileInfo, showConnected bool, asJSON bool) error {
14051408
connectedByDir := map[string]connectedProfileInfo{}
1406-
connectedByInstance := map[string]connectedProfileInfo{}
14071409
for _, info := range connected {
14081410
if info.Directory != "" {
14091411
connectedByDir[info.Directory] = info
14101412
}
1411-
if info.InstanceID != "" {
1412-
connectedByInstance[info.InstanceID] = info
1413-
}
14141413
}
14151414

14161415
if asJSON {
@@ -2127,11 +2126,10 @@ func dialBrowserSocketForProfile(socketPath string, socketDir string, profile st
21272126
}
21282127
return conn, nil
21292128
}
2130-
conn, picked, _, err := pickSocketForProfile(socketDir, profile, timeout)
2129+
conn, _, _, err := pickSocketForProfile(socketDir, profile, timeout)
21312130
if err != nil {
21322131
return nil, err
21332132
}
2134-
_ = picked
21352133
return conn, nil
21362134
}
21372135

docs/exec-plans/active/2026-05-12-chrome-profile-selection.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,8 @@
107107

108108
2. **TC-2 多 profile:列表正确**
109109
- 同时启动 `Default``Profile 1` 两个 Chrome 窗口。
110-
- 运行 `obu profiles --json` → 期望返回 2 条:每条包含 `directory``displayName``extensionVersion``socket``active`(其中之一为 `true`)。
110+
- 运行 `obu profiles --json` → 期望返回 2 条:每条包含 `directory``displayName``extensionId``version``source`
111+
- 运行 `obu profiles --connected --json` → 同上,额外多出 `connected: true``socketPath``instanceId`
111112
- 展示名应该和 Chrome 头像菜单里看到的一致。
112113

113114
3. **TC-3 显式指定 profile**

skills/open-browser-use/SKILL.md

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -52,23 +52,29 @@ picking whatever Chrome window happens to be active.
5252
(whether that profile's host is currently reachable). JSON output is
5353
available via `--json`.
5454

55-
2. If exactly one profile is installed, proceed without asking.
55+
2. If exactly one profile is installed and its `CONNECTED` column is `yes`,
56+
proceed without asking.
5657

57-
3. If more than one profile is installed, ask the user which to use unless the
58-
user already specified one in the original task ("use my work profile",
59-
"do this on cookiy.com"). When asking, list both directory name and display
60-
name so the user can recognize them.
58+
3. If a profile is installed but `CONNECTED` is `-`, the user's Chrome is not
59+
open on that profile. Ask the user to open Chrome on that profile (naming it
60+
by display name so it is unambiguous) before retrying — do not run browser
61+
commands yet, the connection will just fail.
6162

62-
4. After the user has chosen, pass `--profile <selector>` to every CLI / MCP
63+
4. If more than one profile is installed and connected, ask the user which to
64+
use unless the user already specified one in the original task ("use my work
65+
profile", "do this on cookiy.com"). When asking, list both directory name
66+
and display name so the user can recognize them.
67+
68+
5. After the user has chosen, pass `--profile <selector>` to every CLI / MCP
6369
command for the rest of the task. The selector accepts either the directory
6470
name (`Default`, `Profile 1`) or the display name (`Eva`, `cookiy.com`),
6571
case-insensitive. Do not switch profiles mid-task.
6672

67-
5. If `--profile` does not match any running host, the CLI prints which
73+
6. If `--profile` does not match any running host, the CLI prints which
6874
profiles are currently connected. Ask the user to open Chrome on the chosen
6975
profile, then retry; do not silently fall back to a different profile.
7076

71-
6. For MCP, lock the profile at server start:
77+
7. For MCP, lock the profile at server start:
7278

7379
```toml
7480
[mcp_servers.open_browser_use]
@@ -79,7 +85,7 @@ picking whatever Chrome window happens to be active.
7985
Do not pass profile as a per-tool-call argument — the MCP server applies the
8086
start-time selector to every call.
8187

82-
7. Do not remember the user's profile choice across unrelated tasks. A future
88+
8. Do not remember the user's profile choice across unrelated tasks. A future
8389
task may belong to a different profile; ask again rather than assuming.
8490

8591
## Common CLI Actions

0 commit comments

Comments
 (0)