feat(hermes): add kanban dispatcher controls

This commit is contained in:
晴天
2026-05-27 00:12:20 +08:00
parent 425fcd847f
commit 80ed2d0e8c
7 changed files with 263 additions and 6 deletions

View File

@@ -174,6 +174,11 @@ const HUMAN_DELAY_DEFAULTS = {
}
const KANBAN_DEFAULTS = {
dispatchInGateway: true,
dispatchIntervalSeconds: 60,
failureLimit: 2,
autoDecompose: true,
autoDecomposePerTick: 3,
dispatchStaleTimeoutSeconds: 14400,
}
@@ -1486,6 +1491,30 @@ export function render() {
<div class="hm-panel-body">
${renderError(kanbanError)}
<div class="hm-config-runtime-grid hm-config-kanban-grid">
<label class="hm-field hm-field--checkbox">
<input id="hm-kanban-dispatch-in-gateway" type="checkbox" ${kanbanValues.dispatchInGateway ? 'checked' : ''} ${disabled ? 'disabled' : ''}>
<span>
<span class="hm-field-label">${t('engine.hermesKanbanConfigDispatchInGateway')}</span>
</span>
</label>
<label class="hm-field">
<span class="hm-field-label">${t('engine.hermesKanbanConfigDispatchIntervalSeconds')}</span>
<input id="hm-kanban-dispatch-interval-seconds" class="hm-input" type="number" inputmode="numeric" min="1" max="86400" step="1" value="${esc(kanbanValues.dispatchIntervalSeconds)}" ${disabled ? 'disabled' : ''}>
</label>
<label class="hm-field">
<span class="hm-field-label">${t('engine.hermesKanbanConfigFailureLimit')}</span>
<input id="hm-kanban-failure-limit" class="hm-input" type="number" inputmode="numeric" min="1" max="100" step="1" value="${esc(kanbanValues.failureLimit)}" ${disabled ? 'disabled' : ''}>
</label>
<label class="hm-field hm-field--checkbox">
<input id="hm-kanban-auto-decompose" type="checkbox" ${kanbanValues.autoDecompose ? 'checked' : ''} ${disabled ? 'disabled' : ''}>
<span>
<span class="hm-field-label">${t('engine.hermesKanbanConfigAutoDecompose')}</span>
</span>
</label>
<label class="hm-field">
<span class="hm-field-label">${t('engine.hermesKanbanConfigAutoDecomposePerTick')}</span>
<input id="hm-kanban-auto-decompose-per-tick" class="hm-input" type="number" inputmode="numeric" min="1" max="1000" step="1" value="${esc(kanbanValues.autoDecomposePerTick)}" ${disabled ? 'disabled' : ''}>
</label>
<label class="hm-field">
<span class="hm-field-label">${t('engine.hermesKanbanConfigDispatchStaleTimeoutSeconds')}</span>
<input id="hm-kanban-dispatch-stale-timeout-seconds" class="hm-input" type="number" inputmode="numeric" min="0" max="604800" step="60" value="${esc(kanbanValues.dispatchStaleTimeoutSeconds)}" ${disabled ? 'disabled' : ''}>
@@ -3484,6 +3513,11 @@ export function render() {
async function saveKanbanConfig() {
const form = {
dispatchInGateway: el.querySelector('#hm-kanban-dispatch-in-gateway')?.checked ?? true,
dispatchIntervalSeconds: el.querySelector('#hm-kanban-dispatch-interval-seconds')?.value || '60',
failureLimit: el.querySelector('#hm-kanban-failure-limit')?.value || '2',
autoDecompose: el.querySelector('#hm-kanban-auto-decompose')?.checked ?? true,
autoDecomposePerTick: el.querySelector('#hm-kanban-auto-decompose-per-tick')?.value || '3',
dispatchStaleTimeoutSeconds: el.querySelector('#hm-kanban-dispatch-stale-timeout-seconds')?.value || '14400',
}
kanbanSaving = true

View File

@@ -741,6 +741,11 @@
gap: 8px;
}
[data-engine="hermes"] .hm-field--checkbox {
min-height: 44px;
justify-content: center;
}
[data-engine="hermes"] .hm-field-label {
font-family: var(--hm-font-serif);
font-style: italic;

View File

@@ -1029,14 +1029,19 @@ export default {
hermesHumanDelayConfigMaxMs: _('最大延迟 ms', 'Maximum delay ms', '最大延遲 ms'),
hermesHumanDelayConfigFootnote: _('natural 使用 800-2500mscustom 使用下方范围。Signal 等平台可能忽略或仅部分支持该设置。', 'natural uses 800-2500ms; custom uses the range below. Platforms such as Signal may ignore or only partially support this setting.', 'natural 使用 800-2500mscustom 使用下方範圍。Signal 等平台可能忽略或僅部分支援此設定。'),
hermesKanbanConfigTitle: _('Kanban 调度稳定性', 'Kanban dispatch reliability', 'Kanban 調度穩定性'),
hermesKanbanConfigDesc: _('控制 Kanban Worker 多久没有心跳后被自动回收,避免长任务卡在运行中。', 'Control how long a Kanban worker may go without a heartbeat before it is reclaimed, preventing long tasks from staying stuck as running.', '控制 Kanban Worker 多久沒有心跳後被自動回收,避免長任務卡在執行中。'),
hermesKanbanConfigDesc: _('控制 Gateway 是否自动派发 Kanban 任务、派发频率、失败上限和无心跳回收策略。', 'Control whether Gateway dispatches Kanban work, its interval, failure limit, and heartbeat reclaim policy.', '控制 Gateway 是否自動派發 Kanban 任務、派發頻率、失敗上限和無心跳回收策略。'),
hermesKanbanConfigStatusReady: _('结构化配置', 'structured settings', '結構化設定'),
hermesKanbanConfigSave: _('保存 Kanban 设置', 'Save Kanban settings', '儲存 Kanban 設定'),
hermesKanbanConfigSaveSuccess: _('Kanban 调度配置已保存,建议重启 Hermes Gateway 生效', 'Kanban dispatch settings saved. Restart Hermes Gateway to take effect.', 'Kanban 調度設定已儲存,建議重啟 Hermes Gateway 生效'),
hermesKanbanConfigLoadFailed: _('加载 Kanban 调度配置失败', 'Load Kanban dispatch settings failed', '載入 Kanban 調度設定失敗'),
hermesKanbanConfigSaveFailed: _('保存 Kanban 调度配置失败', 'Save Kanban dispatch settings failed', '儲存 Kanban 調度設定失敗'),
hermesKanbanConfigDispatchInGateway: _('由 Gateway 自动派发任务', 'Dispatch tasks in Gateway', '由 Gateway 自動派發任務'),
hermesKanbanConfigDispatchIntervalSeconds: _('派发检查间隔(秒)', 'Dispatch interval (s)', '派發檢查間隔(秒)'),
hermesKanbanConfigFailureLimit: _('失败重试上限', 'Failure retry limit', '失敗重試上限'),
hermesKanbanConfigAutoDecompose: _('自动拆解待办任务', 'Auto decompose tasks', '自動拆解待辦任務'),
hermesKanbanConfigAutoDecomposePerTick: _('每轮自动拆解数量', 'Auto decompose per tick', '每輪自動拆解數量'),
hermesKanbanConfigDispatchStaleTimeoutSeconds: _('无心跳回收时间(秒)', 'Heartbeat reclaim timeout (s)', '無心跳回收時間(秒)'),
hermesKanbanConfigFootnote: _('写入 kanban.dispatch_stale_timeout_seconds。默认 14400 秒;设为 0 会关闭无心跳自动回收。建议只在确认 Worker 会长时间离线且由外部系统接管时关闭。', 'Writes kanban.dispatch_stale_timeout_seconds. Default is 14400 seconds; set 0 to disable heartbeat-based reclaim. Disable it only when workers may stay offline for long periods and an external supervisor handles recovery.', '寫入 kanban.dispatch_stale_timeout_seconds。預設 14400 秒;設為 0 會關閉無心跳自動回收。建議只在確認 Worker 會長時間離線且由外部系統接管時關閉。'),
hermesKanbanConfigFootnote: _('写入 kanban.dispatch_in_gateway、dispatch_interval_seconds、failure_limit、auto_decompose、auto_decompose_per_tick、dispatch_stale_timeout_seconds。无心跳回收默认 14400 秒;设为 0 会关闭自动回收。', 'Writes kanban.dispatch_in_gateway, dispatch_interval_seconds, failure_limit, auto_decompose, auto_decompose_per_tick, and dispatch_stale_timeout_seconds. Heartbeat reclaim defaults to 14400 seconds; set 0 to disable automatic reclaim.', '寫入 kanban.dispatch_in_gateway、dispatch_interval_seconds、failure_limit、auto_decompose、auto_decompose_per_tick、dispatch_stale_timeout_seconds。無心跳回收預設 14400 秒;設為 0 會關閉自動回收。'),
hermesSecurityConfigTitle: _('Tirith 安全扫描', 'Tirith security scanning', 'Tirith 安全掃描'),
hermesSecurityConfigDesc: _('控制终端命令执行前的 Tirith 内容扫描,拦截明显的 URL 伪装、管道执行和注入风险。', 'Control Tirith content scanning before terminal commands run to catch obvious URL spoofing, pipe-to-shell, and injection risks.', '控制終端命令執行前的 Tirith 內容掃描,攔截明顯的 URL 偽裝、管道執行和注入風險。'),
hermesSecurityConfigStatusReady: _('结构化配置', 'structured settings', '結構化設定'),