diff --git a/scripts/install_codex_kit.sh b/scripts/install_codex_kit.sh index 53d0408..9089e38 100755 --- a/scripts/install_codex_kit.sh +++ b/scripts/install_codex_kit.sh @@ -78,22 +78,48 @@ def strip_managed(chunk): return "\n".join(filtered_lines).strip() +def split_root(chunk): + """Separate bare root keys from [table] sections, preserving order within each.""" + root, tables, seen_table = [], [], False + for line in chunk.splitlines(): + stripped = line.strip() + if stripped.startswith("[") and stripped.endswith("]"): + seen_table = True + (tables if seen_table else root).append(line) + return "\n".join(root).strip(), "\n".join(tables).strip() + + # Settings may sit on either side of the managed block -- notably `codex mcp add` # appends [mcp_servers.*] to the end of the file. Keep both sides; rewriting only # what precedes the block silently discards everything after it. +# +# The block's *interior* is filtered too, never dropped. Where an older kit let the +# end marker drift below content Codex had written, real [plugins.*]/[projects.*] +# sections ended up inside the block; discarding it wholesale would delete them. +# Filtering keeps whatever the kit does not own and heals the layout in one run. if managed_start in text and managed_end in text: - before = text.split(managed_start, 1)[0] - after = text.split(managed_end, 1)[1] + before, rest = text.split(managed_start, 1) + interior, after = rest.split(managed_end, 1) else: before = text + interior = "" after = "" -before = strip_managed(before) -after = strip_managed(after) +preserved = "\n\n".join( + part + for part in (strip_managed(before), strip_managed(interior), strip_managed(after)) + if part +) +preserved_root, preserved_tables = split_root(preserved) block = f"{managed_start}\n{managed}\n{managed_end}\n" -parts = [part for part in (before, block.rstrip(), after) if part] +# Bare root keys must precede every [table] header, or TOML binds them to the table +# above them rather than to the document root -- appending the block last quietly +# filed model/web_search under whichever table happened to come before it. +parts = [ + part for part in (preserved_root, block.rstrip(), preserved_tables) if part +] config_path.write_text("\n\n".join(parts) + "\n", encoding="utf-8") PY