@@ -11,7 +11,7 @@ type RunSandboxDoctor = typeof import("./doctor")["runSandboxDoctor"];
1111const requireDist = createRequire ( import . meta. url ) ;
1212const doctorModulePath = "./doctor.js" ;
1313
14- function createDoctorHarness ( ) : {
14+ function createDoctorHarness ( overrides : { provider ?: string ; gatewayChainOk ?: boolean } = { } ) : {
1515 buildToolScopeChecksSpy : MockInstance ;
1616 captureOpenShellSpy : MockInstance ;
1717 captureHostCommandSpy : MockInstance ;
@@ -29,6 +29,8 @@ function createDoctorHarness(): {
2929 resolveOpenShellSpy : MockInstance ;
3030 runSandboxDoctor : RunSandboxDoctor ;
3131} {
32+ const provider = overrides . provider ?? "ollama-local" ;
33+ const gatewayChainOk = overrides . gatewayChainOk ?? false ;
3234 delete require . cache [ requireDist . resolve ( doctorModulePath ) ] ;
3335
3436 const logSpy = vi . spyOn ( console , "log" ) . mockImplementation ( ( ) => undefined ) ;
@@ -56,7 +58,7 @@ function createDoctorHarness(): {
5658 name : "alpha" ,
5759 agent : "openclaw" ,
5860 model : "registry-model" ,
59- provider : "ollama-local" ,
61+ provider,
6062 openshellDriver : "docker" ,
6163 gatewayName : "nemoclaw-19080" ,
6264 gatewayPort : 19080 ,
@@ -95,7 +97,7 @@ function createDoctorHarness(): {
9597 return { status : 0 , output : "alpha Ready" } ;
9698 }
9799 if ( argv [ 0 ] === "inference" && argv [ 1 ] === "get" ) {
98- return { status : 0 , output : " Provider: ollama-local \nModel: live-model\n" } ;
100+ return { status : 0 , output : ` Provider: ${ provider } \nModel: live-model\n` } ;
99101 }
100102 return { status : 0 , output : "" } ;
101103 } ) ;
@@ -118,9 +120,12 @@ function createDoctorHarness(): {
118120 const probeSandboxInferenceGatewayHealthSpy = vi
119121 . spyOn ( processRecovery , "probeSandboxInferenceGatewayHealth" )
120122 . mockResolvedValue ( {
121- ok : false ,
122- endpoint : "http://127.0.0.1:19000/v1/chat/completions" ,
123- detail : "gateway refused connection" ,
123+ ok : gatewayChainOk ,
124+ endpoint : "https://inference.local/v1/models" ,
125+ httpStatus : gatewayChainOk ? 200 : 0 ,
126+ detail : gatewayChainOk
127+ ? "Inference gateway responded HTTP 200 on https://inference.local/v1/models (full chain reachable)."
128+ : "Inference gateway unreachable on https://inference.local/v1/models from inside the sandbox." ,
124129 } ) ;
125130 const loadAgentSpy = vi . spyOn ( agentDefs , "loadAgent" ) . mockReturnValue ( {
126131 name : "openclaw" ,
@@ -251,6 +256,59 @@ describe("runSandboxDoctor flow", () => {
251256 } ,
252257 ) ;
253258
259+ it (
260+ "probes the inference.local route for cloud providers, not just local ones (#6192)" ,
261+ testTimeoutOptions ( 30_000 ) ,
262+ async ( ) => {
263+ // Regression: doctor appended the `inference.local` gateway-chain subprobe
264+ // only for ollama-local/vllm-local. A cloud sandbox whose upstream endpoint
265+ // was reachable but whose in-sandbox inference.local route was broken
266+ // reported "healthy" (exit 0), contradicting `connect`.
267+ const harness = createDoctorHarness ( { provider : "nvidia-prod" , gatewayChainOk : false } ) ;
268+
269+ const report = await harness . runSandboxDoctor ( "alpha" , [ "--json" ] , { quietJson : true } ) ;
270+
271+ // Upstream probe stays green (negative control — we did not break it)...
272+ expect ( report ?. checks ) . toEqual (
273+ expect . arrayContaining ( [
274+ expect . objectContaining ( { group : "Inference" , label : "Provider health" , status : "ok" } ) ,
275+ ] ) ,
276+ ) ;
277+ // ...but the real inference.local route is now probed and reported broken,
278+ // flipping the overall verdict to fail.
279+ expect ( report ?. checks ) . toEqual (
280+ expect . arrayContaining ( [
281+ expect . objectContaining ( {
282+ group : "Inference" ,
283+ label : "Provider health (gateway)" ,
284+ status : "fail" ,
285+ } ) ,
286+ ] ) ,
287+ ) ;
288+ expect ( report ?. status ) . toBe ( "fail" ) ;
289+ } ,
290+ ) ;
291+
292+ it (
293+ "keeps cloud-provider doctor green when inference.local is reachable (#6192)" ,
294+ testTimeoutOptions ( 30_000 ) ,
295+ async ( ) => {
296+ const harness = createDoctorHarness ( { provider : "nvidia-prod" , gatewayChainOk : true } ) ;
297+
298+ const report = await harness . runSandboxDoctor ( "alpha" , [ "--json" ] , { quietJson : true } ) ;
299+
300+ expect ( report ?. checks ) . toEqual (
301+ expect . arrayContaining ( [
302+ expect . objectContaining ( {
303+ group : "Inference" ,
304+ label : "Provider health (gateway)" ,
305+ status : "ok" ,
306+ } ) ,
307+ ] ) ,
308+ ) ;
309+ } ,
310+ ) ;
311+
254312 it ( "rejects mutating --fix when JSON output was requested" , async ( ) => {
255313 const harness = createDoctorHarness ( ) ;
256314
0 commit comments