


























@@ -1,3 +1,6 @@
1+import fs from "node:fs";
2+import os from "node:os";
3+import path from "node:path";
14import { afterEach, describe, expect, it, vi } from "vitest";
25import {
36ensureCodexComputerUse,
@@ -7,8 +10,13 @@ import {
710} from "./computer-use.js";
811912describe("Codex Computer Use setup", () => {
13+const cleanupPaths: string[] = [];
14+1015afterEach(() => {
1116vi.useRealTimers();
17+for (const cleanupPath of cleanupPaths.splice(0)) {
18+fs.rmSync(cleanupPath, { recursive: true, force: true });
19+}
1220});
13211422it("stays disabled until configured", async () => {
@@ -253,6 +261,69 @@ describe("Codex Computer Use setup", () => {
253261});
254262});
255263264+it("auto-registers the bundled Codex app marketplace during auto-install", async () => {
265+const bundledMarketplacePath = fs.mkdtempSync(
266+path.join(os.tmpdir(), "openclaw-codex-bundled-marketplace-"),
267+);
268+cleanupPaths.push(bundledMarketplacePath);
269+const request = createBundledMarketplaceComputerUseRequest(bundledMarketplacePath);
270+271+await expect(
272+ensureCodexComputerUse({
273+pluginConfig: {
274+computerUse: {
275+enabled: true,
276+autoInstall: true,
277+},
278+},
279+ request,
280+defaultBundledMarketplacePath: bundledMarketplacePath,
281+}),
282+).resolves.toEqual(
283+expect.objectContaining({
284+ready: true,
285+reason: "ready",
286+marketplaceName: "openai-bundled",
287+message: "Computer Use is ready.",
288+}),
289+);
290+expect(request).toHaveBeenCalledWith("marketplace/add", {
291+source: bundledMarketplacePath,
292+});
293+expect(request).toHaveBeenCalledWith("plugin/install", {
294+marketplacePath: `${bundledMarketplacePath}/.agents/plugins/marketplace.json`,
295+pluginName: "computer-use",
296+});
297+});
298+299+it("allows auto-install from a configured local marketplace path", async () => {
300+const request = createComputerUseRequest({ installed: false });
301+302+await expect(
303+ensureCodexComputerUse({
304+pluginConfig: {
305+computerUse: {
306+enabled: true,
307+autoInstall: true,
308+marketplacePath: "/marketplaces/desktop-tools/.agents/plugins/marketplace.json",
309+},
310+},
311+ request,
312+}),
313+).resolves.toEqual(
314+expect.objectContaining({
315+ready: true,
316+reason: "ready",
317+message: "Computer Use is ready.",
318+}),
319+);
320+expect(request).not.toHaveBeenCalledWith("marketplace/add", expect.anything());
321+expect(request).toHaveBeenCalledWith("plugin/install", {
322+marketplacePath: "/marketplaces/desktop-tools/.agents/plugins/marketplace.json",
323+pluginName: "computer-use",
324+});
325+});
326+256327it("requires an explicit install command for configured marketplace sources", async () => {
257328const request = createComputerUseRequest({ installed: false });
258329@@ -607,6 +678,87 @@ function createMultiMarketplaceComputerUseRequest(): CodexComputerUseRequest {
607678}) as CodexComputerUseRequest;
608679}
609680681+function createBundledMarketplaceComputerUseRequest(
682+bundledMarketplacePath: string,
683+): CodexComputerUseRequest {
684+let registered = false;
685+let installed = false;
686+return vi.fn(async (method: string, requestParams?: unknown) => {
687+if (method === "experimentalFeature/enablement/set") {
688+return { enablement: { plugins: true } };
689+}
690+if (method === "marketplace/add") {
691+expect(requestParams).toEqual({
692+source: bundledMarketplacePath,
693+});
694+registered = true;
695+return {
696+marketplaceName: "openai-bundled",
697+installedRoot: bundledMarketplacePath,
698+alreadyAdded: false,
699+};
700+}
701+if (method === "plugin/list") {
702+return {
703+marketplaces: registered
704+ ? [
705+{
706+name: "openai-bundled",
707+path: `${bundledMarketplacePath}/.agents/plugins/marketplace.json`,
708+interface: null,
709+plugins: [pluginSummary(installed, "openai-bundled")],
710+},
711+]
712+ : [],
713+marketplaceLoadErrors: [],
714+featuredPluginIds: [],
715+};
716+}
717+if (method === "plugin/read") {
718+return {
719+plugin: {
720+marketplaceName: "openai-bundled",
721+marketplacePath: `${bundledMarketplacePath}/.agents/plugins/marketplace.json`,
722+summary: pluginSummary(installed, "openai-bundled"),
723+description: "Control desktop apps.",
724+skills: [],
725+apps: [],
726+mcpServers: ["computer-use"],
727+},
728+};
729+}
730+if (method === "plugin/install") {
731+installed = true;
732+return { authPolicy: "ON_INSTALL", appsNeedingAuth: [] };
733+}
734+if (method === "config/mcpServer/reload") {
735+return undefined;
736+}
737+if (method === "mcpServerStatus/list") {
738+return {
739+data: installed
740+ ? [
741+{
742+name: "computer-use",
743+tools: {
744+list_apps: {
745+name: "list_apps",
746+inputSchema: { type: "object" },
747+},
748+},
749+resources: [],
750+resourceTemplates: [],
751+authStatus: "unsupported",
752+},
753+]
754+ : [],
755+nextCursor: null,
756+};
757+}
758+throw new Error(`unexpected request ${method}`);
759+}) as CodexComputerUseRequest;
760+}
761+610762function marketplaceEntry(marketplaceName: string, installed: boolean) {
611763return {
612764name: marketplaceName,
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。