diff --git a/crates/openfang-kernel/src/kernel.rs b/crates/openfang-kernel/src/kernel.rs index 7a39e7bafb..3c3b3d5c25 100644 --- a/crates/openfang-kernel/src/kernel.rs +++ b/crates/openfang-kernel/src/kernel.rs @@ -1196,7 +1196,11 @@ impl OpenFangKernel { &toml_str, ) { Ok(disk_manifest) => { - // Compare key fields to detect changes + // Compare key fields to detect changes. + // IMPORTANT: keep this list in sync with AgentManifest + // fields that users may legitimately edit in agent.toml. + // Missing a field here means changes to it are silently + // ignored until the agent is deleted and recreated. let changed = disk_manifest.name != entry.manifest.name || disk_manifest.description != entry.manifest.description @@ -1214,7 +1218,19 @@ impl OpenFangKernel { != entry.manifest.tool_blocklist || disk_manifest.skills != entry.manifest.skills || disk_manifest.mcp_servers - != entry.manifest.mcp_servers; + != entry.manifest.mcp_servers + // Fields previously missing from this check (#1087): + // Only compare workspace when the TOML explicitly sets + // one, so the kernel-assigned default path in the DB + // is not overwritten for agents that omit the field. + || disk_manifest.workspace.as_ref().is_some_and( + |w| Some(w) != entry.manifest.workspace.as_ref(), + ) + || disk_manifest.schedule != entry.manifest.schedule + || disk_manifest.autonomous != entry.manifest.autonomous + || disk_manifest.resources != entry.manifest.resources + || disk_manifest.exec_policy + != entry.manifest.exec_policy; if changed { info!( agent = %name, diff --git a/crates/openfang-types/src/agent.rs b/crates/openfang-types/src/agent.rs index c3da70eee9..c3ebbf6750 100644 --- a/crates/openfang-types/src/agent.rs +++ b/crates/openfang-types/src/agent.rs @@ -67,7 +67,7 @@ impl Default for ModelRoutingConfig { } /// Autonomous agent configuration — guardrails for 24/7 agents. -#[derive(Debug, Clone, Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] #[serde(default)] pub struct AutonomousConfig { /// Cron expression for quiet hours (e.g., "0 22 * * *" to "0 6 * * *"). @@ -223,7 +223,7 @@ impl AgentMode { } /// How an agent is scheduled to run. -#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)] #[serde(rename_all = "snake_case")] pub enum ScheduleMode { /// Agent wakes up when a message/event arrives (default). @@ -245,7 +245,7 @@ fn default_check_interval() -> u64 { } /// Resource limits for an agent. -#[derive(Debug, Clone, Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] #[serde(default)] pub struct ResourceQuota { /// Maximum WASM memory in bytes. diff --git a/crates/openfang-types/src/config.rs b/crates/openfang-types/src/config.rs index 698e5f3bc0..f72ff912fc 100644 --- a/crates/openfang-types/src/config.rs +++ b/crates/openfang-types/src/config.rs @@ -858,7 +858,7 @@ pub enum ExecSecurityMode { } /// Shell/exec security policy. -#[derive(Debug, Clone, Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] #[serde(default)] pub struct ExecPolicy { /// Security mode: "deny" blocks all, "allowlist" only allows listed,