mirror of
https://github.com/openclaw/openclaw.git
synced 2026-03-22 07:20:59 +00:00
Tests: restore deterministic plugins CLI coverage (#49955)
* Tests: restore deterministic plugins CLI coverage * CLI: preserve plugins exit control-flow narrowing * Tests: fix plugins CLI mock typing for tsgo * Tests: fix provider usage mock typing in key normalization
This commit is contained in:
424
src/cli/plugins-cli.test.ts
Normal file
424
src/cli/plugins-cli.test.ts
Normal file
@@ -0,0 +1,424 @@
|
||||
import { Command } from "commander";
|
||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import type { OpenClawConfig } from "../config/config.js";
|
||||
import { createCliRuntimeCapture } from "./test-runtime-capture.js";
|
||||
|
||||
const loadConfig = vi.fn<() => OpenClawConfig>(() => ({}) as OpenClawConfig);
|
||||
const writeConfigFile = vi.fn<(config: OpenClawConfig) => Promise<void>>(async () => undefined);
|
||||
const resolveStateDir = vi.fn(() => "/tmp/openclaw-state");
|
||||
const installPluginFromMarketplace = vi.fn();
|
||||
const listMarketplacePlugins = vi.fn();
|
||||
const resolveMarketplaceInstallShortcut = vi.fn();
|
||||
const enablePluginInConfig = vi.fn();
|
||||
const recordPluginInstall = vi.fn();
|
||||
const clearPluginManifestRegistryCache = vi.fn();
|
||||
const buildPluginStatusReport = vi.fn();
|
||||
const applyExclusiveSlotSelection = vi.fn();
|
||||
const uninstallPlugin = vi.fn();
|
||||
const updateNpmInstalledPlugins = vi.fn();
|
||||
const promptYesNo = vi.fn();
|
||||
const installPluginFromNpmSpec = vi.fn();
|
||||
const installPluginFromPath = vi.fn();
|
||||
|
||||
const { defaultRuntime, runtimeLogs, runtimeErrors, resetRuntimeCapture } =
|
||||
createCliRuntimeCapture();
|
||||
|
||||
vi.mock("../runtime.js", () => ({
|
||||
defaultRuntime,
|
||||
}));
|
||||
|
||||
vi.mock("../config/config.js", async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import("../config/config.js")>();
|
||||
return {
|
||||
...actual,
|
||||
loadConfig: () => loadConfig(),
|
||||
writeConfigFile: (config: OpenClawConfig) => writeConfigFile(config),
|
||||
};
|
||||
});
|
||||
|
||||
vi.mock("../config/paths.js", async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import("../config/paths.js")>();
|
||||
return {
|
||||
...actual,
|
||||
resolveStateDir: () => resolveStateDir(),
|
||||
};
|
||||
});
|
||||
|
||||
vi.mock("../plugins/marketplace.js", () => ({
|
||||
installPluginFromMarketplace: (...args: unknown[]) => installPluginFromMarketplace(...args),
|
||||
listMarketplacePlugins: (...args: unknown[]) => listMarketplacePlugins(...args),
|
||||
resolveMarketplaceInstallShortcut: (...args: unknown[]) =>
|
||||
resolveMarketplaceInstallShortcut(...args),
|
||||
}));
|
||||
|
||||
vi.mock("../plugins/enable.js", () => ({
|
||||
enablePluginInConfig: (...args: unknown[]) => enablePluginInConfig(...args),
|
||||
}));
|
||||
|
||||
vi.mock("../plugins/installs.js", () => ({
|
||||
recordPluginInstall: (...args: unknown[]) => recordPluginInstall(...args),
|
||||
}));
|
||||
|
||||
vi.mock("../plugins/manifest-registry.js", () => ({
|
||||
clearPluginManifestRegistryCache: () => clearPluginManifestRegistryCache(),
|
||||
}));
|
||||
|
||||
vi.mock("../plugins/status.js", async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import("../plugins/status.js")>();
|
||||
return {
|
||||
...actual,
|
||||
buildPluginStatusReport: (...args: unknown[]) => buildPluginStatusReport(...args),
|
||||
};
|
||||
});
|
||||
|
||||
vi.mock("../plugins/slots.js", () => ({
|
||||
applyExclusiveSlotSelection: (...args: unknown[]) => applyExclusiveSlotSelection(...args),
|
||||
}));
|
||||
|
||||
vi.mock("../plugins/uninstall.js", async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import("../plugins/uninstall.js")>();
|
||||
return {
|
||||
...actual,
|
||||
uninstallPlugin: (...args: unknown[]) => uninstallPlugin(...args),
|
||||
};
|
||||
});
|
||||
|
||||
vi.mock("../plugins/update.js", () => ({
|
||||
updateNpmInstalledPlugins: (...args: unknown[]) => updateNpmInstalledPlugins(...args),
|
||||
}));
|
||||
|
||||
vi.mock("./prompt.js", () => ({
|
||||
promptYesNo: (...args: unknown[]) => promptYesNo(...args),
|
||||
}));
|
||||
|
||||
vi.mock("../plugins/install.js", () => ({
|
||||
installPluginFromNpmSpec: (...args: unknown[]) => installPluginFromNpmSpec(...args),
|
||||
installPluginFromPath: (...args: unknown[]) => installPluginFromPath(...args),
|
||||
}));
|
||||
|
||||
const { registerPluginsCli } = await import("./plugins-cli.js");
|
||||
|
||||
describe("plugins cli", () => {
|
||||
const createProgram = () => {
|
||||
const program = new Command();
|
||||
program.exitOverride();
|
||||
registerPluginsCli(program);
|
||||
return program;
|
||||
};
|
||||
|
||||
const runCommand = (argv: string[]) => createProgram().parseAsync(argv, { from: "user" });
|
||||
|
||||
beforeEach(() => {
|
||||
resetRuntimeCapture();
|
||||
loadConfig.mockReset();
|
||||
writeConfigFile.mockReset();
|
||||
resolveStateDir.mockReset();
|
||||
installPluginFromMarketplace.mockReset();
|
||||
listMarketplacePlugins.mockReset();
|
||||
resolveMarketplaceInstallShortcut.mockReset();
|
||||
enablePluginInConfig.mockReset();
|
||||
recordPluginInstall.mockReset();
|
||||
clearPluginManifestRegistryCache.mockReset();
|
||||
buildPluginStatusReport.mockReset();
|
||||
applyExclusiveSlotSelection.mockReset();
|
||||
uninstallPlugin.mockReset();
|
||||
updateNpmInstalledPlugins.mockReset();
|
||||
promptYesNo.mockReset();
|
||||
installPluginFromNpmSpec.mockReset();
|
||||
installPluginFromPath.mockReset();
|
||||
|
||||
loadConfig.mockReturnValue({} as OpenClawConfig);
|
||||
writeConfigFile.mockResolvedValue(undefined);
|
||||
resolveStateDir.mockReturnValue("/tmp/openclaw-state");
|
||||
resolveMarketplaceInstallShortcut.mockResolvedValue(null);
|
||||
installPluginFromMarketplace.mockResolvedValue({
|
||||
ok: false,
|
||||
error: "marketplace install failed",
|
||||
});
|
||||
enablePluginInConfig.mockImplementation((cfg: OpenClawConfig) => ({ config: cfg }));
|
||||
recordPluginInstall.mockImplementation((cfg: OpenClawConfig) => cfg);
|
||||
buildPluginStatusReport.mockReturnValue({
|
||||
plugins: [],
|
||||
diagnostics: [],
|
||||
});
|
||||
applyExclusiveSlotSelection.mockImplementation(({ config }: { config: OpenClawConfig }) => ({
|
||||
config,
|
||||
warnings: [],
|
||||
}));
|
||||
uninstallPlugin.mockResolvedValue({
|
||||
ok: true,
|
||||
config: {} as OpenClawConfig,
|
||||
warnings: [],
|
||||
actions: {
|
||||
entry: false,
|
||||
install: false,
|
||||
allowlist: false,
|
||||
loadPath: false,
|
||||
memorySlot: false,
|
||||
directory: false,
|
||||
},
|
||||
});
|
||||
updateNpmInstalledPlugins.mockResolvedValue({
|
||||
outcomes: [],
|
||||
changed: false,
|
||||
config: {} as OpenClawConfig,
|
||||
});
|
||||
promptYesNo.mockResolvedValue(true);
|
||||
installPluginFromPath.mockResolvedValue({ ok: false, error: "path install disabled in test" });
|
||||
installPluginFromNpmSpec.mockResolvedValue({
|
||||
ok: false,
|
||||
error: "npm install disabled in test",
|
||||
});
|
||||
});
|
||||
|
||||
it("exits when --marketplace is combined with --link", async () => {
|
||||
await expect(
|
||||
runCommand(["plugins", "install", "alpha", "--marketplace", "local/repo", "--link"]),
|
||||
).rejects.toThrow("__exit__:1");
|
||||
|
||||
expect(runtimeErrors.at(-1)).toContain("`--link` is not supported with `--marketplace`.");
|
||||
expect(installPluginFromMarketplace).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("exits when marketplace install fails", async () => {
|
||||
await expect(
|
||||
runCommand(["plugins", "install", "alpha", "--marketplace", "local/repo"]),
|
||||
).rejects.toThrow("__exit__:1");
|
||||
|
||||
expect(installPluginFromMarketplace).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
marketplace: "local/repo",
|
||||
plugin: "alpha",
|
||||
}),
|
||||
);
|
||||
expect(writeConfigFile).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("installs marketplace plugins and persists config", async () => {
|
||||
const cfg = {
|
||||
plugins: {
|
||||
entries: {},
|
||||
},
|
||||
} as OpenClawConfig;
|
||||
const enabledCfg = {
|
||||
plugins: {
|
||||
entries: {
|
||||
alpha: {
|
||||
enabled: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
} as OpenClawConfig;
|
||||
const installedCfg = {
|
||||
...enabledCfg,
|
||||
plugins: {
|
||||
...enabledCfg.plugins,
|
||||
installs: {
|
||||
alpha: {
|
||||
source: "marketplace",
|
||||
installPath: "/tmp/openclaw-state/extensions/alpha",
|
||||
},
|
||||
},
|
||||
},
|
||||
} as OpenClawConfig;
|
||||
|
||||
loadConfig.mockReturnValue(cfg);
|
||||
installPluginFromMarketplace.mockResolvedValue({
|
||||
ok: true,
|
||||
pluginId: "alpha",
|
||||
targetDir: "/tmp/openclaw-state/extensions/alpha",
|
||||
version: "1.2.3",
|
||||
marketplaceName: "Claude",
|
||||
marketplaceSource: "local/repo",
|
||||
marketplacePlugin: "alpha",
|
||||
});
|
||||
enablePluginInConfig.mockReturnValue({ config: enabledCfg });
|
||||
recordPluginInstall.mockReturnValue(installedCfg);
|
||||
buildPluginStatusReport.mockReturnValue({
|
||||
plugins: [{ id: "alpha", kind: "provider" }],
|
||||
diagnostics: [],
|
||||
});
|
||||
applyExclusiveSlotSelection.mockReturnValue({
|
||||
config: installedCfg,
|
||||
warnings: ["slot adjusted"],
|
||||
});
|
||||
|
||||
await runCommand(["plugins", "install", "alpha", "--marketplace", "local/repo"]);
|
||||
|
||||
expect(clearPluginManifestRegistryCache).toHaveBeenCalledTimes(1);
|
||||
expect(writeConfigFile).toHaveBeenCalledWith(installedCfg);
|
||||
expect(runtimeLogs.some((line) => line.includes("slot adjusted"))).toBe(true);
|
||||
expect(runtimeLogs.some((line) => line.includes("Installed plugin: alpha"))).toBe(true);
|
||||
});
|
||||
|
||||
it("shows uninstall dry-run preview without mutating config", async () => {
|
||||
loadConfig.mockReturnValue({
|
||||
plugins: {
|
||||
entries: {
|
||||
alpha: {
|
||||
enabled: true,
|
||||
},
|
||||
},
|
||||
installs: {
|
||||
alpha: {
|
||||
source: "path",
|
||||
sourcePath: "/tmp/openclaw-state/extensions/alpha",
|
||||
installPath: "/tmp/openclaw-state/extensions/alpha",
|
||||
},
|
||||
},
|
||||
},
|
||||
} as OpenClawConfig);
|
||||
buildPluginStatusReport.mockReturnValue({
|
||||
plugins: [{ id: "alpha", name: "alpha" }],
|
||||
diagnostics: [],
|
||||
});
|
||||
|
||||
await runCommand(["plugins", "uninstall", "alpha", "--dry-run"]);
|
||||
|
||||
expect(uninstallPlugin).not.toHaveBeenCalled();
|
||||
expect(writeConfigFile).not.toHaveBeenCalled();
|
||||
expect(runtimeLogs.some((line) => line.includes("Dry run, no changes made."))).toBe(true);
|
||||
});
|
||||
|
||||
it("uninstalls with --force and --keep-files without prompting", async () => {
|
||||
const baseConfig = {
|
||||
plugins: {
|
||||
entries: {
|
||||
alpha: { enabled: true },
|
||||
},
|
||||
installs: {
|
||||
alpha: {
|
||||
source: "path",
|
||||
sourcePath: "/tmp/openclaw-state/extensions/alpha",
|
||||
installPath: "/tmp/openclaw-state/extensions/alpha",
|
||||
},
|
||||
},
|
||||
},
|
||||
} as OpenClawConfig;
|
||||
const nextConfig = {
|
||||
plugins: {
|
||||
entries: {},
|
||||
installs: {},
|
||||
},
|
||||
} as OpenClawConfig;
|
||||
|
||||
loadConfig.mockReturnValue(baseConfig);
|
||||
buildPluginStatusReport.mockReturnValue({
|
||||
plugins: [{ id: "alpha", name: "alpha" }],
|
||||
diagnostics: [],
|
||||
});
|
||||
uninstallPlugin.mockResolvedValue({
|
||||
ok: true,
|
||||
config: nextConfig,
|
||||
warnings: [],
|
||||
actions: {
|
||||
entry: true,
|
||||
install: true,
|
||||
allowlist: false,
|
||||
loadPath: false,
|
||||
memorySlot: false,
|
||||
directory: false,
|
||||
},
|
||||
});
|
||||
|
||||
await runCommand(["plugins", "uninstall", "alpha", "--force", "--keep-files"]);
|
||||
|
||||
expect(promptYesNo).not.toHaveBeenCalled();
|
||||
expect(uninstallPlugin).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
pluginId: "alpha",
|
||||
deleteFiles: false,
|
||||
}),
|
||||
);
|
||||
expect(writeConfigFile).toHaveBeenCalledWith(nextConfig);
|
||||
});
|
||||
|
||||
it("exits when uninstall target is not managed by plugin install records", async () => {
|
||||
loadConfig.mockReturnValue({
|
||||
plugins: {
|
||||
entries: {},
|
||||
installs: {},
|
||||
},
|
||||
} as OpenClawConfig);
|
||||
buildPluginStatusReport.mockReturnValue({
|
||||
plugins: [{ id: "alpha", name: "alpha" }],
|
||||
diagnostics: [],
|
||||
});
|
||||
|
||||
await expect(runCommand(["plugins", "uninstall", "alpha", "--force"])).rejects.toThrow(
|
||||
"__exit__:1",
|
||||
);
|
||||
|
||||
expect(runtimeErrors.at(-1)).toContain("is not managed by plugins config/install records");
|
||||
expect(uninstallPlugin).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("exits when update is called without id and without --all", async () => {
|
||||
loadConfig.mockReturnValue({
|
||||
plugins: {
|
||||
installs: {},
|
||||
},
|
||||
} as OpenClawConfig);
|
||||
|
||||
await expect(runCommand(["plugins", "update"])).rejects.toThrow("__exit__:1");
|
||||
|
||||
expect(runtimeErrors.at(-1)).toContain("Provide a plugin id or use --all.");
|
||||
expect(updateNpmInstalledPlugins).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("reports no tracked plugins when update --all has empty install records", async () => {
|
||||
loadConfig.mockReturnValue({
|
||||
plugins: {
|
||||
installs: {},
|
||||
},
|
||||
} as OpenClawConfig);
|
||||
|
||||
await runCommand(["plugins", "update", "--all"]);
|
||||
|
||||
expect(updateNpmInstalledPlugins).not.toHaveBeenCalled();
|
||||
expect(runtimeLogs.at(-1)).toBe("No tracked plugins to update.");
|
||||
});
|
||||
|
||||
it("writes updated config when updater reports changes", async () => {
|
||||
const cfg = {
|
||||
plugins: {
|
||||
installs: {
|
||||
alpha: {
|
||||
source: "npm",
|
||||
spec: "@openclaw/alpha@1.0.0",
|
||||
},
|
||||
},
|
||||
},
|
||||
} as OpenClawConfig;
|
||||
const nextConfig = {
|
||||
plugins: {
|
||||
installs: {
|
||||
alpha: {
|
||||
source: "npm",
|
||||
spec: "@openclaw/alpha@1.1.0",
|
||||
},
|
||||
},
|
||||
},
|
||||
} as OpenClawConfig;
|
||||
loadConfig.mockReturnValue(cfg);
|
||||
updateNpmInstalledPlugins.mockResolvedValue({
|
||||
outcomes: [{ status: "ok", message: "Updated alpha -> 1.1.0" }],
|
||||
changed: true,
|
||||
config: nextConfig,
|
||||
});
|
||||
|
||||
await runCommand(["plugins", "update", "alpha"]);
|
||||
|
||||
expect(updateNpmInstalledPlugins).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
config: cfg,
|
||||
pluginIds: ["alpha"],
|
||||
dryRun: false,
|
||||
}),
|
||||
);
|
||||
expect(writeConfigFile).toHaveBeenCalledWith(nextConfig);
|
||||
expect(runtimeLogs.some((line) => line.includes("Restart the gateway to load plugins."))).toBe(
|
||||
true,
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -288,7 +288,7 @@ async function runPluginInstallCommand(params: {
|
||||
: null;
|
||||
if (shorthand?.ok === false) {
|
||||
defaultRuntime.error(shorthand.error);
|
||||
process.exit(1);
|
||||
return defaultRuntime.exit(1);
|
||||
}
|
||||
|
||||
const raw = shorthand?.ok ? shorthand.plugin : params.raw;
|
||||
@@ -301,11 +301,11 @@ async function runPluginInstallCommand(params: {
|
||||
if (opts.marketplace) {
|
||||
if (opts.link) {
|
||||
defaultRuntime.error("`--link` is not supported with `--marketplace`.");
|
||||
process.exit(1);
|
||||
return defaultRuntime.exit(1);
|
||||
}
|
||||
if (opts.pin) {
|
||||
defaultRuntime.error("`--pin` is not supported with `--marketplace`.");
|
||||
process.exit(1);
|
||||
return defaultRuntime.exit(1);
|
||||
}
|
||||
|
||||
const cfg = loadConfig();
|
||||
@@ -316,7 +316,7 @@ async function runPluginInstallCommand(params: {
|
||||
});
|
||||
if (!result.ok) {
|
||||
defaultRuntime.error(result.error);
|
||||
process.exit(1);
|
||||
return defaultRuntime.exit(1);
|
||||
}
|
||||
|
||||
clearPluginManifestRegistryCache();
|
||||
@@ -343,7 +343,7 @@ async function runPluginInstallCommand(params: {
|
||||
const fileSpec = resolveFileNpmSpecToLocalPath(raw);
|
||||
if (fileSpec && !fileSpec.ok) {
|
||||
defaultRuntime.error(fileSpec.error);
|
||||
process.exit(1);
|
||||
return defaultRuntime.exit(1);
|
||||
}
|
||||
const normalized = fileSpec && fileSpec.ok ? fileSpec.path : raw;
|
||||
const resolved = resolveUserPath(normalized);
|
||||
@@ -356,7 +356,7 @@ async function runPluginInstallCommand(params: {
|
||||
const probe = await installPluginFromPath({ path: resolved, dryRun: true });
|
||||
if (!probe.ok) {
|
||||
defaultRuntime.error(probe.error);
|
||||
process.exit(1);
|
||||
return defaultRuntime.exit(1);
|
||||
}
|
||||
|
||||
let next: OpenClawConfig = enablePluginInConfig(
|
||||
@@ -394,7 +394,7 @@ async function runPluginInstallCommand(params: {
|
||||
});
|
||||
if (!result.ok) {
|
||||
defaultRuntime.error(result.error);
|
||||
process.exit(1);
|
||||
return defaultRuntime.exit(1);
|
||||
}
|
||||
// Plugin CLI registrars may have warmed the manifest registry cache before install;
|
||||
// force a rescan so config validation sees the freshly installed plugin.
|
||||
@@ -420,7 +420,7 @@ async function runPluginInstallCommand(params: {
|
||||
|
||||
if (opts.link) {
|
||||
defaultRuntime.error("`--link` requires a local path.");
|
||||
process.exit(1);
|
||||
return defaultRuntime.exit(1);
|
||||
}
|
||||
|
||||
if (
|
||||
@@ -436,7 +436,7 @@ async function runPluginInstallCommand(params: {
|
||||
])
|
||||
) {
|
||||
defaultRuntime.error(`Path not found: ${resolved}`);
|
||||
process.exit(1);
|
||||
return defaultRuntime.exit(1);
|
||||
}
|
||||
|
||||
const bundledPreNpmPlan = resolveBundledInstallPlanBeforeNpm({
|
||||
@@ -465,7 +465,7 @@ async function runPluginInstallCommand(params: {
|
||||
});
|
||||
if (!bundledFallbackPlan) {
|
||||
defaultRuntime.error(result.error);
|
||||
process.exit(1);
|
||||
return defaultRuntime.exit(1);
|
||||
}
|
||||
|
||||
await installBundledPluginSource({
|
||||
@@ -623,7 +623,7 @@ export function registerPluginsCli(program: Command) {
|
||||
if (opts.all) {
|
||||
if (id) {
|
||||
defaultRuntime.error("Pass either a plugin id or --all, not both.");
|
||||
process.exit(1);
|
||||
return defaultRuntime.exit(1);
|
||||
}
|
||||
const inspectAll = buildAllPluginInspectReports({
|
||||
config: cfg,
|
||||
@@ -689,7 +689,7 @@ export function registerPluginsCli(program: Command) {
|
||||
|
||||
if (!id) {
|
||||
defaultRuntime.error("Provide a plugin id or use --all.");
|
||||
process.exit(1);
|
||||
return defaultRuntime.exit(1);
|
||||
}
|
||||
|
||||
const inspect = buildPluginInspectReport({
|
||||
@@ -699,7 +699,7 @@ export function registerPluginsCli(program: Command) {
|
||||
});
|
||||
if (!inspect) {
|
||||
defaultRuntime.error(`Plugin not found: ${id}`);
|
||||
process.exit(1);
|
||||
return defaultRuntime.exit(1);
|
||||
}
|
||||
const install = cfg.plugins?.installs?.[inspect.plugin.id];
|
||||
|
||||
@@ -905,7 +905,7 @@ export function registerPluginsCli(program: Command) {
|
||||
} else {
|
||||
defaultRuntime.error(`Plugin not found: ${id}`);
|
||||
}
|
||||
process.exit(1);
|
||||
return defaultRuntime.exit(1);
|
||||
}
|
||||
|
||||
const install = cfg.plugins?.installs?.[pluginId];
|
||||
@@ -972,7 +972,7 @@ export function registerPluginsCli(program: Command) {
|
||||
|
||||
if (!result.ok) {
|
||||
defaultRuntime.error(result.error);
|
||||
process.exit(1);
|
||||
return defaultRuntime.exit(1);
|
||||
}
|
||||
for (const warning of result.warnings) {
|
||||
defaultRuntime.log(theme.warn(warning));
|
||||
@@ -1040,7 +1040,7 @@ export function registerPluginsCli(program: Command) {
|
||||
return;
|
||||
}
|
||||
defaultRuntime.error("Provide a plugin id or use --all.");
|
||||
process.exit(1);
|
||||
return defaultRuntime.exit(1);
|
||||
}
|
||||
|
||||
const result = await updateNpmInstalledPlugins({
|
||||
@@ -1148,7 +1148,7 @@ export function registerPluginsCli(program: Command) {
|
||||
});
|
||||
if (!result.ok) {
|
||||
defaultRuntime.error(result.error);
|
||||
process.exit(1);
|
||||
return defaultRuntime.exit(1);
|
||||
}
|
||||
|
||||
if (opts.json) {
|
||||
|
||||
@@ -7,8 +7,7 @@ import { NON_ENV_SECRETREF_MARKER } from "../agents/model-auth-markers.js";
|
||||
const resolveProviderUsageAuthWithPluginMock = vi.fn(async (..._args: unknown[]) => null);
|
||||
|
||||
vi.mock("../plugins/provider-runtime.js", () => ({
|
||||
resolveProviderUsageAuthWithPlugin: (...args: unknown[]) =>
|
||||
resolveProviderUsageAuthWithPluginMock(...args),
|
||||
resolveProviderUsageAuthWithPlugin: resolveProviderUsageAuthWithPluginMock,
|
||||
}));
|
||||
|
||||
let resolveProviderAuths: typeof import("./provider-usage.auth.js").resolveProviderAuths;
|
||||
|
||||
Reference in New Issue
Block a user