



















@@ -998,6 +998,102 @@ describe("maybeRepairGatewayServiceConfig", () => {
998998}
999999});
10001000});
1001+1002+it("does not duplicate Gateway service config panels for a source-checkout entrypoint with audit findings", async () => {
1003+await withEnvAsync({}, async () => {
1004+const root = await fs.mkdtemp(
1005+path.join(os.tmpdir(), "openclaw-doctor-service-config-dedup-"),
1006+);
1007+try {
1008+await fs.mkdir(path.join(root, ".git"), { recursive: true });
1009+await fs.mkdir(path.join(root, "src"), { recursive: true });
1010+await fs.mkdir(path.join(root, "extensions"), { recursive: true });
1011+await fs.mkdir(path.join(root, "dist"), { recursive: true });
1012+await fs.writeFile(
1013+path.join(root, "package.json"),
1014+JSON.stringify({ name: "openclaw", version: "0.0.0-test" }),
1015+"utf8",
1016+);
1017+const sourceCheckoutEntrypoint = path.join(root, "dist", "index.js");
1018+await fs.writeFile(sourceCheckoutEntrypoint, "export {};\n", "utf8");
1019+const installEntrypoint = "/usr/local/lib/node_modules/openclaw/dist/index.js";
1020+setupGatewayEntrypointRepairScenario({
1021+currentEntrypoint: sourceCheckoutEntrypoint,
1022+ installEntrypoint,
1023+installWorkingDirectory: "/tmp",
1024+});
1025+1026+await runRepair({ gateway: {} });
1027+1028+const gatewayServiceConfigNotes = mocks.note.mock.calls.filter(
1029+([, title]) => title === "Gateway service config",
1030+);
1031+expect(gatewayServiceConfigNotes).toHaveLength(1);
1032+const consolidated = gatewayServiceConfigNotes[0]?.[0] ?? "";
1033+expect(consolidated).toContain(
1034+"Gateway service entrypoint does not match the current install.",
1035+);
1036+expect(consolidated).not.toContain("resolves to a source checkout");
1037+const forceMatches = consolidated.match(/openclaw gateway install --force/g) ?? [];
1038+expect(forceMatches).toHaveLength(0);
1039+} finally {
1040+await fs.rm(root, { recursive: true, force: true });
1041+}
1042+});
1043+});
1044+1045+it("keeps the gateway install force hint when a source-checkout warning is suppressed and repair is declined", async () => {
1046+await withEnvAsync({}, async () => {
1047+const root = await fs.mkdtemp(
1048+path.join(os.tmpdir(), "openclaw-doctor-service-config-force-hint-"),
1049+);
1050+try {
1051+await fs.mkdir(path.join(root, ".git"), { recursive: true });
1052+await fs.mkdir(path.join(root, "src"), { recursive: true });
1053+await fs.mkdir(path.join(root, "extensions"), { recursive: true });
1054+await fs.mkdir(path.join(root, "dist"), { recursive: true });
1055+await fs.writeFile(
1056+path.join(root, "package.json"),
1057+JSON.stringify({ name: "openclaw", version: "0.0.0-test" }),
1058+"utf8",
1059+);
1060+const sourceCheckoutEntrypoint = path.join(root, "dist", "index.js");
1061+await fs.writeFile(sourceCheckoutEntrypoint, "export {};\n", "utf8");
1062+const installEntrypoint = "/usr/local/lib/node_modules/openclaw/dist/index.js";
1063+setupGatewayEntrypointRepairScenario({
1064+currentEntrypoint: sourceCheckoutEntrypoint,
1065+ installEntrypoint,
1066+installWorkingDirectory: "/tmp",
1067+});
1068+1069+const declinePrompts = {
1070+ ...makeDoctorPrompts(),
1071+confirmAutoFix: vi.fn().mockResolvedValue(false),
1072+confirmAggressiveAutoFix: vi.fn().mockResolvedValue(false),
1073+confirmRuntimeRepair: vi.fn().mockResolvedValue(false),
1074+};
1075+await maybeRepairGatewayServiceConfig(
1076+{ gateway: {} },
1077+"local",
1078+makeDoctorIo(),
1079+declinePrompts,
1080+);
1081+1082+const gatewayServiceConfigNotes = mocks.note.mock.calls.filter(
1083+([, title]) => title === "Gateway service config",
1084+);
1085+expect(gatewayServiceConfigNotes).toHaveLength(2);
1086+const auditNote = gatewayServiceConfigNotes[0]?.[0] ?? "";
1087+expect(auditNote).toContain(
1088+"Gateway service entrypoint does not match the current install.",
1089+);
1090+expect(auditNote).not.toContain("resolves to a source checkout");
1091+expect(gatewayServiceConfigNotes[1]?.[0]).toContain("openclaw gateway install --force");
1092+} finally {
1093+await fs.rm(root, { recursive: true, force: true });
1094+}
1095+});
1096+});
10011097});
1002109810031099describe("maybeScanExtraGatewayServices", () => {
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。