fix: cron panel crash on missing schedule + doctor parser false positive (#347)
- Filter out cron jobs with missing/empty schedule before processing, preventing TypeError on .toLowerCase() (#342) - Add defensive .localeCompare() guard in sort comparator - Exclude positive/instructional lines ("No ... warnings detected", "Run: ...") from doctor issue extraction (#331) - Strip negated warning phrases before keyword detection so "No channel security warnings detected" doesn't trigger warning level - Add 2 tests for the doctor parser fix
This commit is contained in:
parent
8eef4139ec
commit
466a1621d4
|
|
@ -526,6 +526,7 @@ export function CronManagementPanel() {
|
|||
)
|
||||
|
||||
const filteredJobs = cronJobs
|
||||
.filter((job) => typeof job.schedule === 'string' && job.schedule.length > 0)
|
||||
.filter((job) => {
|
||||
const query = searchQuery.trim().toLowerCase()
|
||||
const matchesQuery =
|
||||
|
|
@ -563,7 +564,7 @@ export function CronManagementPanel() {
|
|||
case 'name':
|
||||
return dir * a.name.localeCompare(b.name)
|
||||
case 'schedule':
|
||||
return dir * a.schedule.localeCompare(b.schedule)
|
||||
return dir * (a.schedule || '').localeCompare(b.schedule || '')
|
||||
case 'lastRun':
|
||||
return dir * ((a.lastRun || 0) - (b.lastRun || 0))
|
||||
case 'nextRun':
|
||||
|
|
|
|||
|
|
@ -119,4 +119,31 @@ Run "openclaw doctor --fix" to apply changes.
|
|||
expect(result.category).toBe('general')
|
||||
expect(result.canFix).toBe(false)
|
||||
})
|
||||
|
||||
it('treats positive security lines as healthy, not warnings (#331)', () => {
|
||||
const result = parseOpenClawDoctorOutput(`
|
||||
? Security
|
||||
- No channel security warnings detected.
|
||||
- Run: openclaw security audit --deep
|
||||
`, 0)
|
||||
|
||||
expect(result.healthy).toBe(true)
|
||||
expect(result.level).toBe('healthy')
|
||||
expect(result.issues).toEqual([])
|
||||
})
|
||||
|
||||
it('still detects real security warnings alongside positive lines', () => {
|
||||
const result = parseOpenClawDoctorOutput(`
|
||||
? Security
|
||||
- Channel "public" has no auth configured.
|
||||
- No channel security warnings detected.
|
||||
- Run: openclaw security audit --deep
|
||||
`, 0)
|
||||
|
||||
expect(result.healthy).toBe(false)
|
||||
expect(result.level).toBe('warning')
|
||||
expect(result.issues).toEqual([
|
||||
'Channel "public" has no auth configured.',
|
||||
])
|
||||
})
|
||||
})
|
||||
|
|
|
|||
|
|
@ -24,6 +24,13 @@ function isSessionAgingLine(line: string): boolean {
|
|||
return /^agent:[\w:-]+ \(\d+[mh] ago\)$/i.test(line)
|
||||
}
|
||||
|
||||
function isPositiveOrInstructionalLine(line: string): boolean {
|
||||
return /^no .* warnings? detected/i.test(line) ||
|
||||
/^no issues/i.test(line) ||
|
||||
/^run:\s/i.test(line) ||
|
||||
/^all .* (healthy|ok|valid|passed)/i.test(line)
|
||||
}
|
||||
|
||||
function isDecorativeLine(line: string): boolean {
|
||||
return /^[▄█▀░\s]+$/.test(line) || /openclaw doctor/i.test(line) || /🦞\s*openclaw\s*🦞/i.test(line)
|
||||
}
|
||||
|
|
@ -130,10 +137,12 @@ export function parseOpenClawDoctorOutput(
|
|||
const issues = lines
|
||||
.filter(line => /^[-*]\s+/.test(line))
|
||||
.map(line => line.replace(/^[-*]\s+/, '').trim())
|
||||
.filter(line => !isSessionAgingLine(line) && !isStateDirectoryListLine(line))
|
||||
.filter(line => !isSessionAgingLine(line) && !isStateDirectoryListLine(line) && !isPositiveOrInstructionalLine(line))
|
||||
|
||||
const mentionsWarnings = /\bwarning|warnings|problem|problems|invalid config|fix\b/i.test(raw)
|
||||
const mentionsHealthy = /\bok\b|\bhealthy\b|\bno issues\b|\bvalid\b/i.test(raw)
|
||||
// Strip positive/negated phrases before checking for warning keywords
|
||||
const rawForWarningCheck = raw.replace(/\bno\s+\w+\s+(?:security\s+)?warnings?\s+detected\b/gi, '')
|
||||
const mentionsWarnings = /\bwarning|warnings|problem|problems|invalid config|fix\b/i.test(rawForWarningCheck)
|
||||
const mentionsHealthy = /\bok\b|\bhealthy\b|\bno issues\b|\bno\b.*\bwarnings?\s+detected\b|\bvalid\b/i.test(raw)
|
||||
|
||||
let level: OpenClawDoctorLevel = 'healthy'
|
||||
if (exitCode !== 0 || /invalid config|failed|error/i.test(raw)) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue