Skip to content

Commit aef1604

Browse files
committed
fix(infra): allow macos browser open over ssh env
1 parent a00c583 commit aef1604

3 files changed

Lines changed: 30 additions & 1 deletion

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ Docs: https://docs.openclaw.ai
3838
- Gateway/restart: eager-load the lifecycle runtime before in-place upgrade signal handling so package replacement does not deadlock restart imports. (#84890) Thanks @myps6415.
3939
- CLI/update: start managed Gateway update handoff helpers from a stable existing directory and tolerate deleted cwd/package roots during macOS LaunchAgent handoff. Fixes #83808. (#83875) Thanks @jason-allen-oneal.
4040
- Cron: honor `cron.retry.retryOn: ["network"]` for common network error codes such as `EAI_AGAIN`, `EHOSTUNREACH`, and `ENETUNREACH`.
41+
- Dashboard/CLI: allow macOS browser launching through `open` even when SSH environment variables are present, while preserving Linux SSH no-display protection. Fixes #67088. Thanks @theglove44.
4142
- Agents/OpenAI: preserve structured provider error code, type, and redacted body metadata on boundary-aware transport failures.
4243
- Doctor/Codex: point native Codex asset warnings at the canonical `openclaw migrate plan codex` preview command. Fixes #84948. Thanks @markoa.
4344
- CLI/models: make `capability model auth logout --agent` remove auth profiles from the selected non-default agent store. Fixes #85092. Thanks @islandpreneur007.

src/infra/browser-open.test.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,19 @@
11
import path from "node:path";
22
import { afterEach, describe, expect, it, vi } from "vitest";
3+
4+
const detectBinaryMock = vi.hoisted(() => vi.fn(async () => false));
5+
6+
vi.mock("./detect-binary.js", () => ({
7+
detectBinary: detectBinaryMock,
8+
}));
9+
310
import { resolveBrowserOpenCommand } from "./browser-open.js";
411
import { resetWindowsInstallRootsForTests } from "./windows-install-roots.js";
512

613
afterEach(() => {
714
vi.restoreAllMocks();
815
vi.unstubAllEnvs();
16+
detectBinaryMock.mockReset().mockResolvedValue(false);
917
resetWindowsInstallRootsForTests();
1018
});
1119

@@ -44,4 +52,24 @@ describe("resolveBrowserOpenCommand", () => {
4452
expect(resolved.argv).toEqual([rundll32, "url.dll,FileProtocolHandler"]);
4553
expect(resolved.command).toBe(rundll32);
4654
});
55+
56+
it("resolves macOS open even when SSH environment variables are present", async () => {
57+
vi.spyOn(process, "platform", "get").mockReturnValue("darwin");
58+
vi.stubEnv("SSH_CONNECTION", "192.0.2.1 12345 192.0.2.2 22");
59+
detectBinaryMock.mockResolvedValueOnce(true);
60+
61+
const resolved = await resolveBrowserOpenCommand();
62+
63+
expect(detectBinaryMock).toHaveBeenCalledWith("open");
64+
expect(resolved).toEqual({ argv: ["open"], command: "open" });
65+
});
66+
67+
it("still refuses browser launch over Linux SSH without a display", async () => {
68+
vi.spyOn(process, "platform", "get").mockReturnValue("linux");
69+
vi.stubEnv("SSH_CONNECTION", "192.0.2.1 12345 192.0.2.2 22");
70+
71+
const resolved = await resolveBrowserOpenCommand();
72+
73+
expect(resolved).toEqual({ argv: null, reason: "ssh-no-display" });
74+
});
4775
});

src/infra/browser-open.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ export async function resolveBrowserOpenCommand(): Promise<BrowserOpenCommand> {
4848
Boolean(process.env.SSH_TTY) ||
4949
Boolean(process.env.SSH_CONNECTION);
5050

51-
if (isSsh && !hasDisplay && platform !== "win32") {
51+
if (isSsh && !hasDisplay && platform !== "win32" && platform !== "darwin") {
5252
return { argv: null, reason: "ssh-no-display" };
5353
}
5454

0 commit comments

Comments
 (0)