




















@@ -1,4 +1,4 @@
1-import { describe, expect, it, vi } from "vitest";
1+import { afterEach, describe, expect, it, vi } from "vitest";
22import type { OpenClawConfig } from "../config/config.js";
33import type { RuntimeEnv } from "../runtime.js";
44import type { WizardPrompter } from "../wizard/prompts.js";
@@ -7,6 +7,8 @@ const mocks = vi.hoisted(() => ({
77buildWorkspaceSkillStatus: vi.fn(),
88installSkill: vi.fn(),
99detectBinary: vi.fn(),
10+isContainerEnvironment: vi.fn(),
11+resolveBrewExecutable: vi.fn(),
1012resolveNodeManagerOptions: vi.fn(() => [
1113{ value: "npm", label: "npm" },
1214{ value: "pnpm", label: "pnpm" },
@@ -21,6 +23,12 @@ vi.mock("../agents/skills-status.js", () => ({
2123vi.mock("../agents/skills-install.js", () => ({
2224installSkill: mocks.installSkill,
2325}));
26+vi.mock("../infra/container-environment.js", () => ({
27+isContainerEnvironment: mocks.isContainerEnvironment,
28+}));
29+vi.mock("../infra/brew.js", () => ({
30+resolveBrewExecutable: mocks.resolveBrewExecutable,
31+}));
2432vi.mock("./onboard-helpers.js", () => ({
2533detectBinary: mocks.detectBinary,
2634resolveNodeManagerOptions: mocks.resolveNodeManagerOptions,
@@ -78,6 +86,7 @@ function createBundledSkill(params: {
78867987function mockMissingBrewStatus(skills: Array<ReturnType<typeof createBundledSkill>>): void {
8088mocks.detectBinary.mockResolvedValue(false);
89+mocks.resolveBrewExecutable.mockReturnValue(undefined);
8190mocks.installSkill.mockResolvedValue({
8291ok: true,
8392message: "Installed",
@@ -134,6 +143,66 @@ const runtime: RuntimeEnv = {
134143};
135144136145describe("setupSkills", () => {
146+afterEach(() => {
147+mocks.isContainerEnvironment.mockReset();
148+mocks.resolveBrewExecutable.mockReset();
149+});
150+151+it("hides brew-only installs in Linux containers when brew is missing", async () => {
152+const originalPlatformDescriptor = Object.getOwnPropertyDescriptor(process, "platform")!;
153+Object.defineProperty(process, "platform", { value: "linux", configurable: true });
154+try {
155+mockMissingBrewStatus([
156+createBundledSkill({
157+name: "video-frames",
158+description: "ffmpeg",
159+bins: ["ffmpeg"],
160+installLabel: "Install ffmpeg (brew)",
161+}),
162+]);
163+mocks.isContainerEnvironment.mockReturnValue(true);
164+165+const { prompter, notes } = createPrompter({});
166+await setupSkills({} as OpenClawConfig, "/tmp/ws", runtime, prompter);
167+168+expect(prompter.multiselect).not.toHaveBeenCalled();
169+expect(mocks.installSkill).not.toHaveBeenCalled();
170+expect(notes.find((n) => n.title === "Container skill installs")).toBeDefined();
171+expect(notes.find((n) => n.title === "Homebrew recommended")).toBeUndefined();
172+} finally {
173+Object.defineProperty(process, "platform", originalPlatformDescriptor);
174+}
175+});
176+177+it("keeps brew-only installs visible when Linuxbrew is resolved off PATH", async () => {
178+const originalPlatformDescriptor = Object.getOwnPropertyDescriptor(process, "platform")!;
179+Object.defineProperty(process, "platform", { value: "linux", configurable: true });
180+try {
181+mockMissingBrewStatus([
182+createBundledSkill({
183+name: "video-frames",
184+description: "ffmpeg",
185+bins: ["ffmpeg"],
186+installLabel: "Install ffmpeg (brew)",
187+}),
188+]);
189+mocks.isContainerEnvironment.mockReturnValue(true);
190+mocks.resolveBrewExecutable.mockReturnValue("/home/linuxbrew/.linuxbrew/bin/brew");
191+192+const { prompter, notes } = createPrompter({ multiselect: ["video-frames"] });
193+await setupSkills({} as OpenClawConfig, "/tmp/ws", runtime, prompter);
194+195+expect(prompter.multiselect).toHaveBeenCalled();
196+expect(mocks.installSkill).toHaveBeenCalledWith(
197+expect.objectContaining({ skillName: "video-frames", installId: "brew" }),
198+);
199+expect(notes.find((n) => n.title === "Container skill installs")).toBeUndefined();
200+expect(notes.find((n) => n.title === "Homebrew recommended")).toBeUndefined();
201+} finally {
202+Object.defineProperty(process, "platform", originalPlatformDescriptor);
203+}
204+});
205+137206it("does not recommend Homebrew when user skips installing brew-backed deps", async () => {
138207if (process.platform === "win32") {
139208return;
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。