nesquena/hermes-webui

feat(cron): add a name filter to the Scheduled Jobs sidebar (parity with the other list panels)

オープン

#6,724 opened on 2026/08/03

 (4 件のコメント) (0 件のリアクション) (0 人の担当者)Python (2,417 件のフォーク)github user discovery
enhancementhelp wantedtasksux

Repository metrics

Stars
 (17,507 個のスター)
PR merge metrics
 (平均マージ 14h 31m) (30d で 314 merged PRs)

説明

Problem

The Scheduled Jobs sidebar (#panelTasks) is the only list panel in the sidebar without a filter box. Past ~10 jobs the list scrolls, and finding a specific job becomes a visual scan.

On my install I have 15+ jobs whose names share long prefixes (05h_skill_mercado_research_be…, 06h_skill_open_source_modelos…, 06h30_skill_consolidado_dedupl…). They are truncated in the sidebar, so the distinguishing part of the name is exactly the part I cannot see.

The inconsistency

Every other list panel already has this, and they all share the same .sidebar-search component:

Panel Input Handler
Chat #sessionSearch filterSessions()static/sessions.js
Kanban #kanbanSearch filterKanban()_kanbanRenderBoard()static/panels.js
Skills #skillsSearch filterSkills()
Settings #settingsSearch
MCP tools #mcpToolSearch
Scheduled Jobs

.sidebar-search in static/style.css is already panel-agnostic (it is not scoped to the chat panel), so this needs no new CSS.

Suggested shape

loadCrons() in static/panels.js already has the right seam. The active/paused partition from #4026 carries the comment "_cronList stays the single source of truth — only the render is split, which keeps openCronDetail, _cronNewJobIds, and detail refresh untouched." A name filter fits the same split:

  • Add a .sidebar-search block with #cronSearch between the panel head and .cron-list, mirroring #skillsSearch (including type="search" and the password-manager opt-out attributes).
  • Filter _activeJobs / _pausedJobs by a case-insensitive substring of job.name, right after the partition — so the paused (N) count reflects matches and _appendCronProfileToggle() keeps working unchanged.
  • filterCrons() re-renders from the cached _cronList with no API call, exactly like filterKanban().
  • Because the filter lives inside the render, it survives both the refresh button and the polling refresh — no extra bookkeeping.
  • One new i18n key (e.g. filter_jobs), alongside filter_conversations.
  • Empty-result state: reuse the existing muted-text block with a "no jobs match" string rather than showing an empty panel.

I deliberately kept this to the job name, mirroring filter_conversations. Also matching status or profile would be nearly free (both are already rendered per item), but it produces surprising hits — a job named "Cleanup after errors" would match a search for error. If status filtering is wanted, separate chips would likely be cleaner than overloading the text input.

Notes

Happy to send a PR if you're open to it — following CONTRIBUTING Path 2 and opening this first to align on direction. Two things worth deciding before I do:

  1. name-only, or name + status/profile?
  2. should the query persist across reloads (localStorage, like cron-paused-collapsed), or reset each time like the Chat filter?

コントリビューターガイド