Skip to content

Commit 212bb53

Browse files
committed
fix: keep legacy health check behavior
1 parent ce1a2fe commit 212bb53

5 files changed

Lines changed: 162 additions & 35 deletions

File tree

tests/unit/agents-modal-guards.test.mjs

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -253,8 +253,8 @@ test('runHealthCheck skips Claude speed tests when the primary health check alre
253253
await methods.runHealthCheck.call(context);
254254

255255
assert.strictEqual(context.healthCheckLoading, false);
256-
assert.strictEqual(claudeSpeedTestCalls, 0);
257-
assert.strictEqual(context.healthCheckResult, null);
256+
assert.strictEqual(claudeSpeedTestCalls, 1);
257+
assert.strictEqual(context.healthCheckResult.ok, false);
258258
});
259259

260260
test('runHealthCheck preserves backend remote health result while appending speed test summaries', async () => {
@@ -269,14 +269,6 @@ test('runHealthCheck preserves backend remote health result while appending spee
269269
statusCode: 200,
270270
ok: true,
271271
message: 'ok'
272-
},
273-
report: {
274-
schema: 1,
275-
generatedAt: new Date().toISOString(),
276-
ok: true,
277-
summary: { total: 0, error: 0, warn: 0, info: 0 },
278-
issues: [],
279-
sources: {}
280272
}
281273
}),
282274
getProviderConfigModeMeta() {
@@ -308,7 +300,10 @@ test('runHealthCheck preserves backend remote health result while appending spee
308300
assert.strictEqual(context.healthCheckLoading, false);
309301
assert.strictEqual(context.healthCheckResult.remote.type, 'remote-health-check');
310302
assert.strictEqual(context.healthCheckResult.remote.statusCode, 200);
311-
assert.deepStrictEqual(context.healthCheckResult.remote.speedTests, undefined);
303+
assert.deepStrictEqual(context.healthCheckResult.remote.speedTests, {
304+
alpha: { ok: true, durationMs: 10, status: 200 },
305+
beta: { ok: true, durationMs: 20, status: 200 }
306+
});
312307
});
313308

314309
test('applyCodexConfigDirect keeps the successful apply result when only the refresh fails', async () => {

web-ui/app.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -536,7 +536,7 @@ document.addEventListener('DOMContentLoaded', () => {
536536
if (!this.__doctorLoadedOnce) {
537537
this.__doctorLoadedOnce = true;
538538
if (typeof this.runHealthCheck === 'function') {
539-
void this.runHealthCheck({ silent: true });
539+
void this.runHealthCheck({ doctor: true, silent: true });
540540
}
541541
}
542542
}

web-ui/modules/app.methods.codex-config.mjs

Lines changed: 153 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -280,33 +280,165 @@ export function createCodexConfigMethods(options = {}) {
280280
try {
281281
const silent = !!(options && options.silent);
282282
const forceRefresh = !!(options && options.forceRefresh);
283-
const res = await api('doctor', {
284-
lang: this.lang,
285-
remote: true,
286-
range: this.sessionsUsageTimeRange,
287-
targetApp: this.skillsTargetApp,
288-
includeUsage: true,
289-
includeTasks: true,
290-
includeSkills: true,
291-
includeInstall: true,
292-
forceRefresh
293-
});
283+
const useDoctor = !!(options && options.doctor);
284+
if (useDoctor) {
285+
const res = await api('doctor', {
286+
lang: this.lang,
287+
remote: true,
288+
range: this.sessionsUsageTimeRange,
289+
targetApp: this.skillsTargetApp,
290+
includeUsage: true,
291+
includeTasks: true,
292+
includeSkills: true,
293+
includeInstall: true,
294+
forceRefresh
295+
});
296+
if (hasResponseError(res)) {
297+
this.healthCheckResult = null;
298+
if (!silent) {
299+
this.showMessage(getResponseMessage(res, '检查失败'), 'error');
300+
}
301+
return;
302+
}
303+
if (res && typeof res === 'object') {
304+
this.healthCheckResult = res;
305+
const report = res.report && typeof res.report === 'object' ? res.report : null;
306+
const summary = report && report.summary && typeof report.summary === 'object' ? report.summary : null;
307+
const total = summary && Number.isFinite(Number(summary.total))
308+
? Math.max(0, Math.floor(Number(summary.total)))
309+
: (Array.isArray(res.issues) ? res.issues.length : 0);
310+
const errors = summary && Number.isFinite(Number(summary.error)) ? Math.max(0, Math.floor(Number(summary.error))) : 0;
311+
const warns = summary && Number.isFinite(Number(summary.warn)) ? Math.max(0, Math.floor(Number(summary.warn))) : 0;
312+
this.healthCheckBatchTotal = total;
313+
this.healthCheckBatchDone = total;
314+
this.healthCheckBatchFailed = errors + warns;
315+
if (!silent && res.ok) {
316+
this.showMessage('检查通过', 'success');
317+
}
318+
return;
319+
}
320+
this.healthCheckResult = null;
321+
if (!silent) {
322+
this.showMessage('检查失败', 'error');
323+
}
324+
return;
325+
}
326+
327+
if (this.configMode === 'claude') {
328+
const entries = Object.entries(this.claudeConfigs || {});
329+
this.healthCheckBatchTotal = entries.length;
330+
331+
const speedTasks = entries.map(([name, config]) => this.runClaudeSpeedTest(name, config)
332+
.then((result) => {
333+
if (!result || result.ok !== true) {
334+
this.healthCheckBatchFailed += 1;
335+
}
336+
return { name, result };
337+
})
338+
.catch((err) => {
339+
this.healthCheckBatchFailed += 1;
340+
return {
341+
name,
342+
result: { ok: false, error: err && err.message ? err.message : 'Speed test failed' }
343+
};
344+
})
345+
.finally(() => {
346+
this.healthCheckBatchDone += 1;
347+
})
348+
);
349+
350+
const pairs = await Promise.all(speedTasks);
351+
const results = {};
352+
const issues = [];
353+
for (const pair of pairs) {
354+
results[pair.name] = pair.result || null;
355+
if (typeof this.buildSpeedTestIssue === 'function') {
356+
const issue = this.buildSpeedTestIssue(pair.name, pair.result);
357+
if (issue) issues.push(issue);
358+
}
359+
}
360+
const ok = issues.length === 0 && this.healthCheckBatchFailed === 0;
361+
this.healthCheckResult = {
362+
ok,
363+
issues,
364+
remote: {
365+
type: 'speed-test',
366+
speedTests: results
367+
}
368+
};
369+
if (ok && !silent) {
370+
this.showMessage('检查通过', 'success');
371+
}
372+
return;
373+
}
374+
375+
const shouldRunSpeedTests = this.configMode === 'codex';
376+
const speedTimeoutMs = shouldRunSpeedTests ? 3500 : 0;
377+
const providers = shouldRunSpeedTests
378+
? (this.providersList || [])
379+
.map((provider) => typeof provider === 'string'
380+
? provider.trim()
381+
: String((provider && provider.name) || '').trim())
382+
.filter(Boolean)
383+
: [];
384+
const currentProvider = String(this.currentProvider || '').trim();
385+
const orderedProviders = currentProvider && providers.includes(currentProvider)
386+
? [currentProvider, ...providers.filter((name) => name !== currentProvider)]
387+
: providers;
388+
this.healthCheckBatchTotal = orderedProviders.length;
389+
390+
const speedTasks = orderedProviders.map((provider) => this.runSpeedTest(provider, { silent: true, timeoutMs: speedTimeoutMs })
391+
.then((result) => {
392+
if (!result || result.ok !== true) {
393+
this.healthCheckBatchFailed += 1;
394+
}
395+
return { name: provider, result };
396+
})
397+
.catch((err) => {
398+
this.healthCheckBatchFailed += 1;
399+
return {
400+
name: provider,
401+
result: { ok: false, error: err && err.message ? err.message : 'Speed test failed' }
402+
};
403+
})
404+
.finally(() => {
405+
this.healthCheckBatchDone += 1;
406+
})
407+
);
408+
409+
const configTask = api('config-health-check', { remote: this.configMode === 'codex' });
410+
const [res, pairs] = await Promise.all([
411+
configTask,
412+
Promise.all(speedTasks)
413+
]);
294414
if (hasResponseError(res)) {
295415
this.healthCheckResult = null;
296416
if (!silent) {
297417
this.showMessage(getResponseMessage(res, '检查失败'), 'error');
298418
}
299419
} else if (res && typeof res === 'object') {
300-
this.healthCheckResult = res;
301-
const report = res.report && typeof res.report === 'object' ? res.report : null;
302-
const summary = report && report.summary && typeof report.summary === 'object' ? report.summary : null;
303-
const total = summary && Number.isFinite(Number(summary.total)) ? Math.max(0, Math.floor(Number(summary.total))) : (Array.isArray(res.issues) ? res.issues.length : 0);
304-
const errors = summary && Number.isFinite(Number(summary.error)) ? Math.max(0, Math.floor(Number(summary.error))) : 0;
305-
const warns = summary && Number.isFinite(Number(summary.warn)) ? Math.max(0, Math.floor(Number(summary.warn))) : 0;
306-
this.healthCheckBatchTotal = total;
307-
this.healthCheckBatchDone = total;
308-
this.healthCheckBatchFailed = errors + warns;
309-
if (!silent && res.ok) {
420+
const issues = Array.isArray(res.issues) ? [...res.issues] : [];
421+
let remote = res.remote || null;
422+
if (shouldRunSpeedTests) {
423+
const results = {};
424+
for (const pair of pairs) {
425+
results[pair.name] = pair.result || null;
426+
const issue = this.buildSpeedTestIssue(pair.name, pair.result);
427+
if (issue) issues.push(issue);
428+
}
429+
remote = remote && typeof remote === 'object'
430+
? { ...remote, speedTests: results }
431+
: { type: 'speed-test', speedTests: results };
432+
}
433+
434+
const ok = issues.length === 0;
435+
this.healthCheckResult = {
436+
...res,
437+
ok,
438+
issues,
439+
remote
440+
};
441+
if (ok && !silent) {
310442
this.showMessage('检查通过', 'success');
311443
}
312444
} else {

web-ui/modules/app.methods.navigation.mjs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ export function createNavigationMethods(options = {}) {
2424
let ok = true;
2525
try {
2626
if (typeof vm.runHealthCheck === 'function') {
27-
await vm.runHealthCheck({ silent: true, forceRefresh });
27+
await vm.runHealthCheck({ doctor: true, silent: true, forceRefresh });
2828
}
2929
vm.__doctorLoadedOnce = true;
3030
return true;

web-ui/partials/index/panel-dashboard.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@
145145
v-else-if="action.type === 'run-check'"
146146
type="button"
147147
class="btn-tool btn-tool-compact"
148-
@click="runHealthCheck({ forceRefresh: true })"
148+
@click="runHealthCheck({ doctor: true, forceRefresh: true })"
149149
:disabled="healthCheckLoading">
150150
{{ t('dashboard.doctor.runChecks') }}
151151
</button>

0 commit comments

Comments
 (0)