fix(codex): move common-config TOML merge off smol-toml to backend toml_edit

updateTomlCommonConfigSnippet re-serialized the whole document through
smol-toml (parse -> deepMerge -> stringify): comments dropped, keys
reordered, and empty parent table headers synthesized -- the
long-standing "config.toml keeps getting reordered" symptom (audit C5,
introduced in 083e48bf).

Replace it with a backend command backed by the same
merge_toml_table_like / remove_toml_table_like used when writing live
configs, so the form preview and the live write share one merge
semantic and user formatting survives edit-time merges. The frontend
sync helper is deleted outright to keep the pattern from coming back.

Making the form operations async exposes them to interleaving, so a
result is discarded unless it is still current when it lands:

- a per-hook sequence number (last operation wins) covers rapid
  toggle/save races where an earlier merge resolves after a later
  removal and would flip the switch back;
- a config-baseline check covers the user hand-editing the TOML while
  a merge is in flight -- the stale result must not clobber their edit.
  The checkbox state self-heals via the existing inference effect.

Regression tests pin both by resolving a suspended merge after a newer
operation / an external edit, plus backend tests locking comment and
key-order preservation, scalar override, and value-matched removal.
This commit is contained in:
Jason
2026-07-08 22:21:57 +08:00
parent 94fc1cc064
commit 88d5ffba44
10 changed files with 381 additions and 97 deletions
+17
View File
@@ -275,6 +275,23 @@ pub async fn get_common_config_snippet(
.map_err(|e| e.to_string())
}
/// 对前端编辑器里的 config.toml 文本做通用配置片段的合并/剥离。
/// 放后端是为了走 toml_edit(保注释、保键序);前端 smol-toml 的
/// 整文档重序列化会破坏用户手写格式。
#[tauri::command]
pub async fn update_toml_common_config_snippet(
config_toml: String,
snippet_toml: String,
enabled: bool,
) -> Result<String, String> {
crate::services::provider::update_toml_common_config_snippet(
&config_toml,
&snippet_toml,
enabled,
)
.map_err(|e| e.to_string())
}
#[tauri::command]
pub async fn set_common_config_snippet(
app_type: String,