diff --git a/src/infra/clawhub.test.ts b/src/infra/clawhub.test.ts index e2edfc2d9b7..5b2e88e102e 100644 --- a/src/infra/clawhub.test.ts +++ b/src/infra/clawhub.test.ts @@ -1,7 +1,7 @@ import fs from "node:fs/promises"; import os from "node:os"; import path from "node:path"; -import { afterEach, describe, expect, it } from "vitest"; +import { afterEach, describe, expect, it, vi } from "vitest"; import { parseClawHubPluginSpec, resolveClawHubAuthToken, @@ -12,13 +12,21 @@ import { } from "./clawhub.js"; describe("clawhub helpers", () => { + const originalHome = process.env.HOME; + afterEach(() => { delete process.env.OPENCLAW_CLAWHUB_TOKEN; delete process.env.CLAWHUB_TOKEN; delete process.env.CLAWHUB_AUTH_TOKEN; delete process.env.OPENCLAW_CLAWHUB_CONFIG_PATH; delete process.env.CLAWHUB_CONFIG_PATH; + delete process.env.CLAWDHUB_CONFIG_PATH; delete process.env.XDG_CONFIG_HOME; + if (originalHome == null) { + delete process.env.HOME; + } else { + process.env.HOME = originalHome; + } }); it("parses explicit ClawHub package specs", () => { @@ -81,17 +89,46 @@ describe("clawhub helpers", () => { it("resolves ClawHub auth token from config.json", async () => { const configRoot = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-clawhub-config-")); - process.env.XDG_CONFIG_HOME = configRoot; - await fs.mkdir(path.join(configRoot, "clawhub"), { recursive: true }); - await fs.writeFile( - path.join(configRoot, "clawhub", "config.json"), - JSON.stringify({ auth: { token: "cfg-token-123" } }), - "utf8", - ); + const configPath = path.join(configRoot, "clawhub", "config.json"); + process.env.OPENCLAW_CLAWHUB_CONFIG_PATH = configPath; + await fs.mkdir(path.dirname(configPath), { recursive: true }); + await fs.writeFile(configPath, JSON.stringify({ auth: { token: "cfg-token-123" } }), "utf8"); await expect(resolveClawHubAuthToken()).resolves.toBe("cfg-token-123"); }); + it("resolves ClawHub auth token from the legacy config path override", async () => { + const configRoot = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-clawdhub-config-")); + const configPath = path.join(configRoot, "config.json"); + process.env.CLAWDHUB_CONFIG_PATH = configPath; + await fs.writeFile(configPath, JSON.stringify({ token: "legacy-token-123" }), "utf8"); + + await expect(resolveClawHubAuthToken()).resolves.toBe("legacy-token-123"); + }); + + it.runIf(process.platform === "darwin")( + "resolves ClawHub auth token from the macOS Application Support path", + async () => { + const fakeHome = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-clawhub-home-")); + const configPath = path.join( + fakeHome, + "Library", + "Application Support", + "clawhub", + "config.json", + ); + const homedirSpy = vi.spyOn(os, "homedir").mockReturnValue(fakeHome); + try { + await fs.mkdir(path.dirname(configPath), { recursive: true }); + await fs.writeFile(configPath, JSON.stringify({ token: "macos-token-123" }), "utf8"); + + await expect(resolveClawHubAuthToken()).resolves.toBe("macos-token-123"); + } finally { + homedirSpy.mockRestore(); + } + }, + ); + it("injects resolved auth token into ClawHub requests", async () => { process.env.OPENCLAW_CLAWHUB_TOKEN = "env-token-123"; const fetchImpl = async (input: string | URL | Request, init?: RequestInit) => { diff --git a/src/infra/clawhub.ts b/src/infra/clawhub.ts index a5172828650..7a466afe221 100644 --- a/src/infra/clawhub.ts +++ b/src/infra/clawhub.ts @@ -236,10 +236,15 @@ function extractTokenFromClawHubConfig(value: unknown): string | undefined { function resolveClawHubConfigPath(): string { const explicit = - process.env.OPENCLAW_CLAWHUB_CONFIG_PATH?.trim() || process.env.CLAWHUB_CONFIG_PATH?.trim(); + process.env.OPENCLAW_CLAWHUB_CONFIG_PATH?.trim() || + process.env.CLAWHUB_CONFIG_PATH?.trim() || + process.env.CLAWDHUB_CONFIG_PATH?.trim(); if (explicit) { return explicit; } + if (process.platform === "darwin") { + return path.join(os.homedir(), "Library", "Application Support", "clawhub", "config.json"); + } const xdgConfigHome = process.env.XDG_CONFIG_HOME?.trim(); const configHome = xdgConfigHome && xdgConfigHome.length > 0 ? xdgConfigHome : path.join(os.homedir(), ".config");