Skip to content

Commit a1d22d1

Browse files
committed
scripts: ini_to_opencode.py
1 parent 2943210 commit a1d22d1

1 file changed

Lines changed: 102 additions & 0 deletions

File tree

scripts/ini_to_opencode.py

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
#!/usr/bin/env python3
2+
"""
3+
Convert llama.cpp .ini model presets to opencode.json provider config
4+
"""
5+
6+
import json
7+
import re
8+
import sys
9+
from pathlib import Path
10+
11+
12+
def parse_ini(content: str) -> dict:
13+
"""Parse simple INI format with sections and key-value pairs"""
14+
result = {}
15+
current_section = None
16+
17+
for line in content.split("\n"):
18+
line = line.strip()
19+
20+
# Skip empty lines and comments
21+
if not line or line.startswith(";") or line.startswith("#"):
22+
continue
23+
24+
# Section header
25+
section_match = re.match(r"^\[([^\]]+)\]$", line)
26+
if section_match:
27+
current_section = section_match.group(1)
28+
result[current_section] = {}
29+
continue
30+
31+
# Key-value pair
32+
if "=" in line and current_section:
33+
key, _, value = line.partition("=")
34+
key = key.strip()
35+
value = value.strip()
36+
result[current_section][key] = value
37+
38+
return result
39+
40+
41+
def ini_to_opencode(ini_file: str, output_file: str = None):
42+
"""Convert INI preset file to opencode.json"""
43+
44+
# Read and parse INI
45+
ini_path = Path(ini_file)
46+
ini_content = ini_path.read_text()
47+
ini_data = parse_ini(ini_content)
48+
49+
# Build opencode.json structure
50+
opencode_config = {
51+
"$schema": "https://opencode.ai/config.json",
52+
"provider": {
53+
"llamacpp": {
54+
"npm": "@ai-sdk/openai-compatible",
55+
"name": "llama.cpp (local)",
56+
"options": {"baseURL": "http://127.0.0.1:8080/v1", "apiKey": ""},
57+
"models": {},
58+
}
59+
},
60+
}
61+
62+
# Map INI presets to opencode models
63+
# Skip global section [*] and version
64+
for section_name, settings in ini_data.items():
65+
if section_name == "[*]" or section_name == "version":
66+
continue
67+
68+
model_id = section_name.lower().replace(" ", "-").replace(":", "-")
69+
model_config = {"name": section_name}
70+
71+
# Map common INI options to opencode/llama.cpp server settings
72+
if "model" in settings:
73+
model_config["model"] = settings["model"]
74+
75+
if "n-gpu-layer" in settings or "n-gpu-layers" in settings:
76+
gpu_layer = settings.get("n-gpu-layer") or settings.get("n-gpu-layers")
77+
model_config["n_gpu_layers"] = gpu_layer
78+
79+
if "c" in settings:
80+
model_config["context_size"] = settings["c"]
81+
82+
if "chat-template" in settings:
83+
model_config["chat_template"] = settings["chat-template"]
84+
85+
if "jinja" in settings:
86+
model_config["jinja"] = settings["jinja"].lower() == "true"
87+
88+
opencode_config["provider"]["llamacpp"]["models"][model_id] = model_config
89+
90+
# Write output
91+
output_path = Path(output_file) if output_file else ini_path.with_suffix(".json")
92+
output_path.write_text(json.dumps(opencode_config, indent=2) + "\n")
93+
94+
print(json.dumps(opencode_config, indent=2))
95+
96+
97+
if __name__ == "__main__":
98+
if len(sys.argv) < 2:
99+
print("Usage: python3 ini_to_opencode.py <input.ini> [output.json]")
100+
sys.exit(1)
101+
102+
ini_to_opencode(sys.argv[1], sys.argv[2] if len(sys.argv) > 2 else None)

0 commit comments

Comments
 (0)