惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

爱范儿
爱范儿
博客园_首页
U
Unit 42
Apple Machine Learning Research
Apple Machine Learning Research
云风的 BLOG
云风的 BLOG
MongoDB | Blog
MongoDB | Blog
美团技术团队
H
Help Net Security
G
Google Developers Blog
B
Blog RSS Feed
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
aimingoo的专栏
aimingoo的专栏
Google DeepMind News
Google DeepMind News
J
Java Code Geeks
M
MIT News - Artificial intelligence
腾讯CDC
IT之家
IT之家
Vercel News
Vercel News
C
Check Point Blog
博客园 - 三生石上(FineUI控件)
Last Week in AI
Last Week in AI
I
InfoQ
博客园 - 司徒正美
A
About on SuperTechFans

Recent Commits to openclaw:main

test: merge chat side-result checks · openclaw/openclaw@ddd2c2a test: merge cron history checks · openclaw/openclaw@f7eb746 test: merge responsive navigation shell checks · openclaw/openclaw@c2e4b47 docs(changelog): add codex oauth fixes · openclaw/openclaw@628e6cd test: merge navigation routing cases · openclaw/openclaw@5d8cecb Tests: mock channel registry bundled fallback · openclaw/openclaw@2b08233 Secrets: avoid broad web search discovery for single plugin config · openclaw/openclaw@a464f59 test: merge config view browser checks · openclaw/openclaw@20cf511 fix(status): align oauth health with runtime · openclaw/openclaw@eed7116 feat: add macOS screen snapshots for monitor preview (#67954) thanks … · openclaw/openclaw@f377db1 fix: report shared auth scopes in hello-ok (#67810) thanks @BunsDev · openclaw/openclaw@0b6c39b Auto-reply: avoid eager bundled route fallback · openclaw/openclaw@3ea1bf4 Tests: narrow session binding contract setup · openclaw/openclaw@54e4e16 fix(macOS): enable undo/redo in webchat composer text input (#34962) · openclaw/openclaw@00951dc Tests: speed up channel setup promotion · openclaw/openclaw@82b529a Docs: refresh agent instructions · openclaw/openclaw@5775fe2 fix(auth): serialize OAuth refresh across agents to fix #26322 (#67876) · openclaw/openclaw@8e79080 test: allow ollama public surface boundary test · openclaw/openclaw@7d4f1a6 Docs: add test performance guardrails · openclaw/openclaw@89706d3 Tests: restore context-engine usage proof · openclaw/openclaw@e4c4f95 Tests: slim context engine runtime coverage · openclaw/openclaw@74c198f ci: retry failed custom checkouts · openclaw/openclaw@0ee5baf test: trim duplicate provider auth onboarding cases · openclaw/openclaw@1ffc02e matrix: fix sessions_spawn --thread subagent session spawning (#67643) · openclaw/openclaw@1ce2596 test: reduce auth choice fixture churn · openclaw/openclaw@857b9cd test: mock health status config boundaries · openclaw/openclaw@9d5ab4a test: mock onboard config io boundary · openclaw/openclaw@299694d test: mock legacy state plugin boundaries · openclaw/openclaw@2713089 test: mock channel install boundaries · openclaw/openclaw@b945248 test: mock doctor preview channel boundaries · openclaw/openclaw@b1a3ad4
fix(doctor): honor external service repair policy · openc...
shakkernerd · 2026-04-26 · via Recent Commits to openclaw:main

@@ -28,6 +28,12 @@ import {

2828

} from "./daemon-runtime.js";

2929

import { buildGatewayRuntimeHints, formatGatewayRuntimeSummary } from "./doctor-format.js";

3030

import type { DoctorOptions, DoctorPrompter } from "./doctor-prompter.js";

31+

import {

32+

confirmDoctorServiceRepair,

33+

EXTERNAL_SERVICE_REPAIR_NOTE,

34+

isServiceRepairExternallyManaged,

35+

resolveServiceRepairPolicy,

36+

} from "./doctor-service-repair-policy.js";

3137

import { resolveGatewayInstallToken } from "./gateway-install-token.js";

3238

import { formatHealthCheckFailure } from "./health-format.js";

3339

import { healthCommand } from "./health.js";

@@ -37,6 +43,7 @@ async function maybeRepairLaunchAgentBootstrap(params: {

3743

title: string;

3844

runtime: RuntimeEnv;

3945

prompter: DoctorPrompter;

46+

serviceRepairExternal: boolean;

4047

}): Promise<boolean> {

4148

if (process.platform !== "darwin") {

4249

return false;

@@ -58,8 +65,12 @@ async function maybeRepairLaunchAgentBootstrap(params: {

5865

}

59666067

note("LaunchAgent is listed but not loaded in launchd.", `${params.title} LaunchAgent`);

68+

if (params.serviceRepairExternal) {

69+

note(EXTERNAL_SERVICE_REPAIR_NOTE, `${params.title} LaunchAgent`);

70+

return false;

71+

}

617262-

const shouldFix = await params.prompter.confirmRuntimeRepair({

73+

const shouldFix = await confirmDoctorServiceRepair(params.prompter, {

6374

message: `Repair ${params.title} LaunchAgent bootstrap now?`,

6475

initialValue: true,

6576

});

@@ -98,6 +109,8 @@ export async function maybeRepairGatewayDaemon(params: {

98109

return;

99110

}

100111112+

const serviceRepairPolicy = resolveServiceRepairPolicy();

113+

const serviceRepairExternal = isServiceRepairExternallyManaged(serviceRepairPolicy);

101114

const service = resolveGatewayService();

102115

// systemd can throw in containers/WSL; treat as "not loaded" and fall back to hints.

103116

let loaded = false;

@@ -117,6 +130,7 @@ export async function maybeRepairGatewayDaemon(params: {

117130

title: "Gateway",

118131

runtime: params.runtime,

119132

prompter: params.prompter,

133+

serviceRepairExternal,

120134

});

121135

await maybeRepairLaunchAgentBootstrap({

122136

env: {

@@ -126,6 +140,7 @@ export async function maybeRepairGatewayDaemon(params: {

126140

title: "Node",

127141

runtime: params.runtime,

128142

prompter: params.prompter,

143+

serviceRepairExternal,

129144

});

130145

if (gatewayRepaired) {

131146

loaded = await service.isLoaded({ env: process.env });

@@ -162,10 +177,18 @@ export async function maybeRepairGatewayDaemon(params: {

162177

}

163178

note("Gateway service not installed.", "Gateway");

164179

if (params.cfg.gateway?.mode !== "remote") {

165-

const install = await params.prompter.confirmRuntimeRepair({

166-

message: "Install gateway service now?",

167-

initialValue: true,

168-

});

180+

if (serviceRepairExternal) {

181+

note(EXTERNAL_SERVICE_REPAIR_NOTE, "Gateway");

182+

return;

183+

}

184+

const install = await confirmDoctorServiceRepair(

185+

params.prompter,

186+

{

187+

message: "Install gateway service now?",

188+

initialValue: true,

189+

},

190+

serviceRepairPolicy,

191+

);

169192

if (install) {

170193

const daemonRuntime = await params.prompter.select<GatewayDaemonRuntime>(

171194

{

@@ -233,10 +256,18 @@ export async function maybeRepairGatewayDaemon(params: {

233256

}

234257235258

if (serviceRuntime?.status !== "running") {

236-

const start = await params.prompter.confirmRuntimeRepair({

237-

message: "Start gateway service now?",

238-

initialValue: true,

239-

});

259+

if (serviceRepairExternal) {

260+

note(EXTERNAL_SERVICE_REPAIR_NOTE, "Gateway");

261+

return;

262+

}

263+

const start = await confirmDoctorServiceRepair(

264+

params.prompter,

265+

{

266+

message: "Start gateway service now?",

267+

initialValue: true,

268+

},

269+

serviceRepairPolicy,

270+

);

240271

if (start) {

241272

const restartResult = await service.restart({

242273

env: process.env,

@@ -260,10 +291,18 @@ export async function maybeRepairGatewayDaemon(params: {

260291

}

261292262293

if (serviceRuntime?.status === "running") {

263-

const restart = await params.prompter.confirmRuntimeRepair({

264-

message: "Restart gateway service now?",

265-

initialValue: true,

266-

});

294+

if (serviceRepairExternal) {

295+

note(EXTERNAL_SERVICE_REPAIR_NOTE, "Gateway");

296+

return;

297+

}

298+

const restart = await confirmDoctorServiceRepair(

299+

params.prompter,

300+

{

301+

message: "Restart gateway service now?",

302+

initialValue: true,

303+

},

304+

serviceRepairPolicy,

305+

);

267306

if (restart) {

268307

const restartResult = await service.restart({

269308

env: process.env,