From ae9d6e8844cca57aff46c9a3e13e0e181474d6e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=99=B4=E5=A4=A9?= Date: Wed, 27 May 2026 00:57:00 +0800 Subject: [PATCH] feat(hermes): add kanban worker log controls --- scripts/dev-api.js | 32 +++++++++++++++ src-tauri/src/commands/hermes.rs | 62 +++++++++++++++++++++++++++++ src/engines/hermes/pages/config.js | 12 ++++++ src/locales/modules/engine.js | 4 +- tests/hermes-config-page-ui.test.js | 2 + tests/hermes-kanban-config.test.js | 18 +++++++++ 6 files changed, 129 insertions(+), 1 deletion(-) diff --git a/scripts/dev-api.js b/scripts/dev-api.js index 2e10ced..6e02ae0 100644 --- a/scripts/dev-api.js +++ b/scripts/dev-api.js @@ -3800,6 +3800,22 @@ export function buildHermesKanbanConfigValues(config = {}) { 1000, false, ), + workerLogRotateBytes: parseHermesInteger( + kanban.worker_log_rotate_bytes, + 'kanban.worker_log_rotate_bytes', + 2097152, + 1, + 1073741824, + false, + ), + workerLogBackupCount: parseHermesInteger( + kanban.worker_log_backup_count, + 'kanban.worker_log_backup_count', + 1, + 0, + 100, + false, + ), dispatchStaleTimeoutSeconds: parseHermesInteger( kanban.dispatch_stale_timeout_seconds, 'kanban.dispatch_stale_timeout_seconds', @@ -3864,6 +3880,22 @@ export function mergeHermesKanbanConfig(config = {}, form = {}) { 1000, true, ) + kanban.worker_log_rotate_bytes = parseHermesInteger( + Object.hasOwn(form, 'workerLogRotateBytes') ? form.workerLogRotateBytes : currentValues.workerLogRotateBytes, + 'kanban.worker_log_rotate_bytes', + 2097152, + 1, + 1073741824, + true, + ) + kanban.worker_log_backup_count = parseHermesInteger( + Object.hasOwn(form, 'workerLogBackupCount') ? form.workerLogBackupCount : currentValues.workerLogBackupCount, + 'kanban.worker_log_backup_count', + 1, + 0, + 100, + true, + ) kanban.dispatch_stale_timeout_seconds = parseHermesInteger( Object.hasOwn(form, 'dispatchStaleTimeoutSeconds') ? form.dispatchStaleTimeoutSeconds : currentValues.dispatchStaleTimeoutSeconds, 'kanban.dispatch_stale_timeout_seconds', diff --git a/src-tauri/src/commands/hermes.rs b/src-tauri/src/commands/hermes.rs index e62b2e3..264f07c 100644 --- a/src-tauri/src/commands/hermes.rs +++ b/src-tauri/src/commands/hermes.rs @@ -6589,6 +6589,22 @@ fn build_hermes_kanban_config_values(config: &serde_yaml::Value) -> Value { 1000, )) .unwrap_or(3), + "workerLogRotateBytes": kanban + .map(|map| bounded_hermes_i64( + yaml_i64_field(map, "worker_log_rotate_bytes"), + 2097152, + 1, + 1073741824, + )) + .unwrap_or(2097152), + "workerLogBackupCount": kanban + .map(|map| bounded_hermes_i64( + yaml_i64_field(map, "worker_log_backup_count"), + 1, + 0, + 100, + )) + .unwrap_or(1), "dispatchStaleTimeoutSeconds": kanban .map(|map| bounded_hermes_i64( yaml_i64_field(map, "dispatch_stale_timeout_seconds"), @@ -6644,6 +6660,20 @@ fn merge_hermes_kanban_config(config: &mut serde_yaml::Value, form: &Value) -> R 1, 1000, )?; + let worker_log_rotate_bytes = validate_hermes_i64( + form_i64(form, "workerLogRotateBytes").or_else(|| current["workerLogRotateBytes"].as_i64()), + "kanban.worker_log_rotate_bytes", + 2097152, + 1, + 1073741824, + )?; + let worker_log_backup_count = validate_hermes_i64( + form_i64(form, "workerLogBackupCount").or_else(|| current["workerLogBackupCount"].as_i64()), + "kanban.worker_log_backup_count", + 1, + 0, + 100, + )?; let stale_timeout = validate_hermes_i64( form_i64(form, "dispatchStaleTimeoutSeconds") .or_else(|| current["dispatchStaleTimeoutSeconds"].as_i64()), @@ -6690,6 +6720,14 @@ fn merge_hermes_kanban_config(config: &mut serde_yaml::Value, form: &Value) -> R yaml_key("auto_decompose_per_tick"), serde_yaml::Value::Number(serde_yaml::Number::from(auto_decompose_per_tick)), ); + kanban.insert( + yaml_key("worker_log_rotate_bytes"), + serde_yaml::Value::Number(serde_yaml::Number::from(worker_log_rotate_bytes)), + ); + kanban.insert( + yaml_key("worker_log_backup_count"), + serde_yaml::Value::Number(serde_yaml::Number::from(worker_log_backup_count)), + ); kanban.insert( yaml_key("dispatch_stale_timeout_seconds"), serde_yaml::Value::Number(serde_yaml::Number::from(stale_timeout)), @@ -19460,6 +19498,8 @@ mod hermes_kanban_config_tests { assert_eq!(values["failureLimit"], 2); assert_eq!(values["autoDecompose"], true); assert_eq!(values["autoDecomposePerTick"], 3); + assert_eq!(values["workerLogRotateBytes"], 2097152); + assert_eq!(values["workerLogBackupCount"], 1); assert_eq!(values["dispatchStaleTimeoutSeconds"], 14400); } @@ -19475,6 +19515,8 @@ kanban: failure_limit: "5" auto_decompose: false auto_decompose_per_tick: "7" + worker_log_rotate_bytes: "4194304" + worker_log_backup_count: "3" dispatch_stale_timeout_seconds: "7200" "#, ) @@ -19487,6 +19529,8 @@ kanban: assert_eq!(values["failureLimit"], 5); assert_eq!(values["autoDecompose"], false); assert_eq!(values["autoDecomposePerTick"], 7); + assert_eq!(values["workerLogRotateBytes"], 4194304); + assert_eq!(values["workerLogBackupCount"], 3); assert_eq!(values["dispatchStaleTimeoutSeconds"], 7200); } @@ -19517,6 +19561,8 @@ memory: "failureLimit": 4, "autoDecompose": false, "autoDecomposePerTick": 2, + "workerLogRotateBytes": 1048576, + "workerLogBackupCount": 0, "dispatchStaleTimeoutSeconds": 0, }), ) @@ -19541,6 +19587,14 @@ memory: config["kanban"]["auto_decompose_per_tick"].as_i64(), Some(2) ); + assert_eq!( + config["kanban"]["worker_log_rotate_bytes"].as_i64(), + Some(1048576) + ); + assert_eq!( + config["kanban"]["worker_log_backup_count"].as_i64(), + Some(0) + ); assert_eq!( config["kanban"]["dispatch_stale_timeout_seconds"].as_i64(), Some(0) @@ -19595,6 +19649,14 @@ kanban: .unwrap_err(); assert!(err.contains("kanban.auto_decompose_per_tick")); + let err = merge_hermes_kanban_config(&mut config, &json!({ "workerLogRotateBytes": 0 })) + .unwrap_err(); + assert!(err.contains("kanban.worker_log_rotate_bytes")); + + let err = merge_hermes_kanban_config(&mut config, &json!({ "workerLogBackupCount": -1 })) + .unwrap_err(); + assert!(err.contains("kanban.worker_log_backup_count")); + let err = merge_hermes_kanban_config(&mut config, &json!({ "dispatchStaleTimeoutSeconds": -1 })) .unwrap_err(); diff --git a/src/engines/hermes/pages/config.js b/src/engines/hermes/pages/config.js index b01ba1e..8b955e9 100644 --- a/src/engines/hermes/pages/config.js +++ b/src/engines/hermes/pages/config.js @@ -181,6 +181,8 @@ const KANBAN_DEFAULTS = { failureLimit: 2, autoDecompose: true, autoDecomposePerTick: 3, + workerLogRotateBytes: 2097152, + workerLogBackupCount: 1, dispatchStaleTimeoutSeconds: 14400, } @@ -1525,6 +1527,14 @@ export function render() { ${t('engine.hermesKanbanConfigAutoDecomposePerTick')} + +