

























@@ -9,6 +9,12 @@ import {
99import { maybeRepairBundledPluginRuntimeDeps } from "./doctor-bundled-plugin-runtime-deps.js";
1010import type { DoctorPrompter } from "./doctor-prompter.js";
111112+type InstalledRuntimeDeps = Array<{
13+installRoot: string;
14+missingSpecs: string[];
15+installSpecs: string[];
16+}>;
17+1218function writeJson(filePath: string, value: unknown) {
1319fs.mkdirSync(path.dirname(filePath), { recursive: true });
1420fs.writeFileSync(filePath, `${JSON.stringify(value, null, 2)}\n`, "utf8");
@@ -25,6 +31,31 @@ function writeBundledChannelPlugin(root: string, id: string, dependencies: Recor
2531});
2632}
273334+function createInstalledRuntimeDeps(): InstalledRuntimeDeps {
35+return [];
36+}
37+38+function createNonInteractivePrompter(
39+options: { updateInProgress?: boolean } = {},
40+): DoctorPrompter {
41+return {
42+shouldRepair: false,
43+shouldForce: false,
44+repairMode: {
45+shouldRepair: false,
46+shouldForce: false,
47+nonInteractive: true,
48+canPrompt: false,
49+updateInProgress: options.updateInProgress ?? false,
50+},
51+confirm: async () => false,
52+confirmAutoFix: async () => false,
53+confirmAggressiveAutoFix: async () => false,
54+confirmRuntimeRepair: async () => false,
55+select: async (_params: unknown, fallback: unknown) => fallback,
56+} as DoctorPrompter;
57+}
58+2859describe("doctor bundled plugin runtime deps", () => {
2960it("skips source checkouts", () => {
3061const root = fs.mkdtempSync(path.join(os.tmpdir(), "openclaw-doctor-bundled-"));
@@ -175,31 +206,11 @@ describe("doctor bundled plugin runtime deps", () => {
175206const root = fs.mkdtempSync(path.join(os.tmpdir(), "openclaw-doctor-bundled-"));
176207writeJson(path.join(root, "package.json"), { name: "openclaw" });
177208writeBundledChannelPlugin(root, "telegram", { grammy: "1.37.0" });
178-const installed: Array<{
179-installRoot: string;
180-missingSpecs: string[];
181-installSpecs: string[];
182-}> = [];
183-const prompter = {
184-shouldRepair: false,
185-shouldForce: false,
186-repairMode: {
187-shouldRepair: false,
188-shouldForce: false,
189-nonInteractive: true,
190-canPrompt: false,
191-updateInProgress: false,
192-},
193-confirm: async () => false,
194-confirmAutoFix: async () => false,
195-confirmAggressiveAutoFix: async () => false,
196-confirmRuntimeRepair: async () => false,
197-select: async (_params: unknown, fallback: unknown) => fallback,
198-} as DoctorPrompter;
209+const installed = createInstalledRuntimeDeps();
199210200211await maybeRepairBundledPluginRuntimeDeps({
201212runtime: { error: () => {} } as never,
202- prompter,
213+prompter: createNonInteractivePrompter(),
203214packageRoot: root,
204215config: {
205216plugins: { enabled: true },
@@ -223,31 +234,11 @@ describe("doctor bundled plugin runtime deps", () => {
223234const root = fs.mkdtempSync(path.join(os.tmpdir(), "openclaw-doctor-bundled-"));
224235writeJson(path.join(root, "package.json"), { name: "openclaw" });
225236writeBundledChannelPlugin(root, "feishu", { "@larksuiteoapi/node-sdk": "^1.61.0" });
226-const installed: Array<{
227-installRoot: string;
228-missingSpecs: string[];
229-installSpecs: string[];
230-}> = [];
231-const prompter = {
232-shouldRepair: false,
233-shouldForce: false,
234-repairMode: {
235-shouldRepair: false,
236-shouldForce: false,
237-nonInteractive: true,
238-canPrompt: false,
239-updateInProgress: true,
240-},
241-confirm: async () => false,
242-confirmAutoFix: async () => false,
243-confirmAggressiveAutoFix: async () => false,
244-confirmRuntimeRepair: async () => false,
245-select: async (_params: unknown, fallback: unknown) => fallback,
246-} as DoctorPrompter;
237+const installed = createInstalledRuntimeDeps();
247238248239await maybeRepairBundledPluginRuntimeDeps({
249240runtime: { error: () => {} } as never,
250- prompter,
241+prompter: createNonInteractivePrompter({ updateInProgress: true }),
251242packageRoot: root,
252243includeConfiguredChannels: true,
253244config: {
@@ -274,31 +265,11 @@ describe("doctor bundled plugin runtime deps", () => {
274265writeJson(path.join(root, "package.json"), { name: "openclaw", version: "2026.4.22" });
275266writeBundledChannelPlugin(root, "slack", { "@slack/web-api": "7.15.1" });
276267const env = { OPENCLAW_PLUGIN_STAGE_DIR: stageDir };
277-const installed: Array<{
278-installRoot: string;
279-missingSpecs: string[];
280-installSpecs: string[];
281-}> = [];
282-const prompter = {
283-shouldRepair: false,
284-shouldForce: false,
285-repairMode: {
286-shouldRepair: false,
287-shouldForce: false,
288-nonInteractive: true,
289-canPrompt: false,
290-updateInProgress: false,
291-},
292-confirm: async () => false,
293-confirmAutoFix: async () => false,
294-confirmAggressiveAutoFix: async () => false,
295-confirmRuntimeRepair: async () => false,
296-select: async (_params: unknown, fallback: unknown) => fallback,
297-} as DoctorPrompter;
268+const installed = createInstalledRuntimeDeps();
298269299270await maybeRepairBundledPluginRuntimeDeps({
300271runtime: { error: () => {} } as never,
301- prompter,
272+prompter: createNonInteractivePrompter(),
302273 env,
303274packageRoot: root,
304275config: {
@@ -330,31 +301,11 @@ describe("doctor bundled plugin runtime deps", () => {
330301name: "@slack/web-api",
331302version: "7.15.1",
332303});
333-const installed: Array<{
334-installRoot: string;
335-missingSpecs: string[];
336-installSpecs: string[];
337-}> = [];
338-const prompter = {
339-shouldRepair: false,
340-shouldForce: false,
341-repairMode: {
342-shouldRepair: false,
343-shouldForce: false,
344-nonInteractive: true,
345-canPrompt: false,
346-updateInProgress: false,
347-},
348-confirm: async () => false,
349-confirmAutoFix: async () => false,
350-confirmAggressiveAutoFix: async () => false,
351-confirmRuntimeRepair: async () => false,
352-select: async (_params: unknown, fallback: unknown) => fallback,
353-} as DoctorPrompter;
304+const installed = createInstalledRuntimeDeps();
354305355306await maybeRepairBundledPluginRuntimeDeps({
356307runtime: { error: () => {} } as never,
357- prompter,
308+prompter: createNonInteractivePrompter(),
358309packageRoot: root,
359310includeConfiguredChannels: true,
360311config: {
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。