-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathcodex_apply_config
More file actions
executable file
·138 lines (108 loc) · 3.74 KB
/
codex_apply_config
File metadata and controls
executable file
·138 lines (108 loc) · 3.74 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
#!/usr/bin/env bash
set -euo pipefail
CONFIG_DIR="${CODEX_HOME:-$HOME/.codex}"
TEMPLATE_PATH="${1:-$CONFIG_DIR/config.template.toml}"
CONFIG_PATH="$CONFIG_DIR/config.toml"
if [[ ! -f "$TEMPLATE_PATH" ]]; then
echo "Codex template not found: $TEMPLATE_PATH" >&2
exit 1
fi
mkdir -p "$CONFIG_DIR"
if [[ -f "$CONFIG_PATH" ]]; then
timestamp="$(date +"%Y%m%d%H%M%S")"
cp "$CONFIG_PATH" "$CONFIG_PATH.$timestamp.bak"
fi
touch "$CONFIG_PATH"
python3 - "$TEMPLATE_PATH" "$CONFIG_PATH" <<'PY'
from __future__ import annotations
import re
import sys
from pathlib import Path
template_path = Path(sys.argv[1])
config_path = Path(sys.argv[2])
template_lines = template_path.read_text().splitlines()
config_text = config_path.read_text() if config_path.exists() else ""
config_lines = config_text.splitlines()
def first_section_index(lines: list[str]) -> int:
for idx, line in enumerate(lines):
if line.lstrip().startswith("["):
return idx
return len(lines)
def upsert_top_level(lines: list[str], key: str, value: str) -> None:
first_section = first_section_index(lines)
pattern = re.compile(rf"^{re.escape(key)}\s*=")
for idx in range(first_section):
if pattern.match(lines[idx].strip()):
lines[idx] = f"{key} = {value}"
return
insert_at = 0
for idx in range(first_section):
stripped = lines[idx].strip()
if stripped.startswith("model_reasoning_effort ="):
insert_at = idx + 1
break
if stripped.startswith("model ="):
insert_at = idx + 1
lines.insert(insert_at, f"{key} = {value}")
def find_section(lines: list[str], header: str) -> int | None:
for idx, line in enumerate(lines):
if line.strip() == header:
return idx
return None
def section_end(lines: list[str], start: int) -> int:
for idx in range(start + 1, len(lines)):
if lines[idx].lstrip().startswith("["):
return idx
return len(lines)
def upsert_section(lines: list[str], header: str, kvs: list[tuple[str, str]]) -> None:
idx = find_section(lines, header)
if idx is None:
if lines and lines[-1].strip():
lines.append("")
lines.append(header)
for key, value in kvs:
lines.append(f"{key} = {value}")
return
end = section_end(lines, idx)
insert_at = idx + 1
for key, value in kvs:
pattern = re.compile(rf"^{re.escape(key)}\s*=")
found = False
for line_idx in range(idx + 1, end):
if pattern.match(lines[line_idx].strip()):
lines[line_idx] = f"{key} = {value}"
found = True
break
if not found:
lines.insert(insert_at, f"{key} = {value}")
insert_at += 1
end += 1
top_level: list[tuple[str, str]] = []
sections: dict[str, list[tuple[str, str]]] = {}
current_section: str | None = None
for line in template_lines:
stripped = line.strip()
if not stripped or stripped.startswith("#"):
continue
if stripped.startswith("[") and stripped.endswith("]"):
current_section = stripped
sections.setdefault(current_section, [])
continue
if "=" not in line:
continue
key, value = line.split("=", 1)
key = key.strip()
value = value.strip()
if current_section is None:
top_level.append((key, value))
else:
sections[current_section].append((key, value))
for key, value in top_level:
upsert_top_level(config_lines, key, value)
for header, kvs in sections.items():
upsert_section(config_lines, header, kvs)
new_text = "\n".join(config_lines)
if config_text.endswith("\n") or not new_text.endswith("\n"):
new_text += "\n"
config_path.write_text(new_text)
PY