kaiju-coder-7-opencode / scripts /install_kaiju_opencode_profile.py
restokes92's picture
Upload Kaiju Coder 7 OpenCode helper package
81ee344 verified
#!/usr/bin/env python3
"""Install the Kaiju Coder 7 OpenCode provider and lean agent locally."""
from __future__ import annotations
import argparse
import json
import shlex
import shutil
import stat
from pathlib import Path
from typing import Any
ROOT = Path(__file__).resolve().parents[1]
AGENT_SOURCE_CANDIDATES = [
ROOT / ".opencode/agents/kaiju-coder-7.md",
ROOT / "agents/kaiju-coder-7.md",
]
CONFIG_SOURCE_CANDIDATES = [
ROOT / "release/opencode/opencode.kaiju-coder-7.jsonc",
ROOT / "opencode.kaiju-coder-7.jsonc",
]
PLUGIN_SOURCE_CANDIDATES = [
ROOT / "scripts/opencode-kaiju-no-autocontinue.mjs",
ROOT / "opencode-kaiju-no-autocontinue.mjs",
]
COMMAND_SOURCE_CANDIDATES = [
ROOT / ".opencode/commands/kaiju.md",
ROOT / "commands/kaiju.md",
]
PLUGIN_DEST_NAME = "kaiju-no-autocontinue.mjs"
RUNTIME_DEST_NAME = "kaiju-coder-7-runtime"
RUNNER_NAME = "kaiju-coder-7-run"
DEFAULT_MODEL = "kaiju/kaiju-coder-7"
DEFAULT_AGENT = "kaiju-coder-7"
RUNTIME_REQUIRED = [
ROOT / "kaiju_harness",
ROOT / "prompts",
ROOT / "scripts/run_kaiju_router.py",
]
def strip_jsonc(text: str) -> str:
# The template intentionally stays plain JSON-compatible today. This helper
# keeps the installer tolerant if comments are added later.
lines = []
for line in text.splitlines():
if line.lstrip().startswith("//"):
continue
lines.append(line)
return "\n".join(lines)
def load_json(path: Path) -> dict[str, Any]:
if not path.exists():
return {}
return json.loads(strip_jsonc(path.read_text(encoding="utf-8")))
def write_json(path: Path, data: dict[str, Any]) -> None:
path.parent.mkdir(parents=True, exist_ok=True)
path.write_text(json.dumps(data, indent=2) + "\n", encoding="utf-8")
def write_plugin_package_json(config_dir: Path) -> Path:
path = config_dir / "package.json"
data = load_json(path)
dependencies = dict(data.get("dependencies") or {})
dependencies.setdefault("@opencode-ai/plugin", "1.14.33")
data["dependencies"] = dependencies
write_json(path, data)
return path
def first_existing(candidates: list[Path], label: str) -> Path:
for candidate in candidates:
if candidate.is_file():
return candidate
joined = ", ".join(str(candidate) for candidate in candidates)
raise FileNotFoundError(f"Missing {label}. Looked in: {joined}")
def plugin_list(value: Any) -> list[str]:
if isinstance(value, str):
return [value]
if isinstance(value, list):
return [item for item in value if isinstance(item, str)]
return []
def runtime_available() -> bool:
return all(path.exists() for path in RUNTIME_REQUIRED)
def ignore_runtime_junk(_directory: str, names: list[str]) -> set[str]:
return {
name
for name in names
if name == "__pycache__" or name.endswith(".pyc") or name == ".DS_Store"
}
def copy_runtime(runtime_dest: Path) -> None:
if not runtime_available():
missing = ", ".join(str(path) for path in RUNTIME_REQUIRED if not path.exists())
raise FileNotFoundError(f"Missing Kaiju router runtime file(s): {missing}")
shutil.rmtree(runtime_dest, ignore_errors=True)
(runtime_dest / "scripts").mkdir(parents=True, exist_ok=True)
shutil.copytree(ROOT / "kaiju_harness", runtime_dest / "kaiju_harness", ignore=ignore_runtime_junk)
shutil.copytree(ROOT / "prompts", runtime_dest / "prompts", ignore=ignore_runtime_junk)
shutil.copy2(ROOT / "scripts/run_kaiju_router.py", runtime_dest / "scripts/run_kaiju_router.py")
def write_runner(runner_dest: Path, runtime_dest: Path) -> None:
runner_dest.parent.mkdir(parents=True, exist_ok=True)
runtime_arg = shlex.quote(str(runtime_dest))
script_arg = shlex.quote(str(runtime_dest / "scripts/run_kaiju_router.py"))
content = f"""#!/usr/bin/env bash
set -euo pipefail
RUNTIME_DIR={runtime_arg}
PYTHON_BIN="${{KAIJU_PYTHON:-python3}}"
BASE_URL="${{KAIJU_OPENAI_BASE_URL:-http://127.0.0.1:18181/v1}}"
MODEL="${{KAIJU_MODEL:-kaiju-coder-7}}"
PLANNER_TIMEOUT="${{KAIJU_PLANNER_TIMEOUT:-45}}"
if [ ! -f {script_arg} ]; then
echo "Kaiju Coder 7 runtime is missing: $RUNTIME_DIR" >&2
exit 2
fi
exec "$PYTHON_BIN" {script_arg} \\
--openai-base-url "$BASE_URL" \\
--model "$MODEL" \\
--planner-timeout "$PLANNER_TIMEOUT" \\
"$@"
"""
runner_dest.write_text(content, encoding="utf-8")
runner_dest.chmod(runner_dest.stat().st_mode | stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH)
def merge_provider(
existing: dict[str, Any],
template: dict[str, Any],
base_url: str | None,
plugin_path: Path,
*,
set_defaults: bool,
) -> dict[str, Any]:
merged = dict(existing)
provider = dict(merged.get("provider") or {})
kaiju = dict((template.get("provider") or {})["kaiju"])
if base_url:
options = dict(kaiju.get("options") or {})
options["baseURL"] = base_url
kaiju["options"] = options
provider["kaiju"] = kaiju
merged["$schema"] = merged.get("$schema") or template.get("$schema", "https://opencode.ai/config.json")
merged["provider"] = provider
plugins = plugin_list(merged.get("plugin"))
plugin_path_str = str(plugin_path)
if plugin_path_str not in plugins:
plugins.append(plugin_path_str)
merged["plugin"] = plugins
if set_defaults:
merged["model"] = DEFAULT_MODEL
merged["default_agent"] = DEFAULT_AGENT
return merged
def main() -> int:
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument(
"--config-dir",
type=Path,
default=Path.home() / ".config/opencode",
help="OpenCode config directory to update.",
)
parser.add_argument("--base-url", default=None, help="Override Kaiju OpenAI-compatible base URL.")
parser.add_argument(
"--bin-dir",
type=Path,
default=Path.home() / ".local/bin",
help="Directory where the kaiju-coder-7-run command is installed.",
)
parser.add_argument("--skip-runner", action="store_true", help="Install only the OpenCode provider, agent, and plugin.")
parser.add_argument(
"--no-defaults",
action="store_true",
help="Do not set Kaiju Coder 7 as the default OpenCode model and default agent.",
)
parser.add_argument("--dry-run", action="store_true")
args = parser.parse_args()
config_path = args.config_dir / "opencode.jsonc"
agent_dest = args.config_dir / "agents/kaiju-coder-7.md"
plugin_dest = args.config_dir / PLUGIN_DEST_NAME
command_dest = args.config_dir / "commands/kaiju.md"
package_dest = args.config_dir / "package.json"
runtime_dest = args.config_dir / RUNTIME_DEST_NAME
runner_dest = args.bin_dir / RUNNER_NAME
agent_source = first_existing(AGENT_SOURCE_CANDIDATES, "Kaiju Coder 7 OpenCode agent")
config_source = first_existing(CONFIG_SOURCE_CANDIDATES, "Kaiju Coder 7 OpenCode config")
plugin_source = first_existing(PLUGIN_SOURCE_CANDIDATES, "Kaiju Coder 7 OpenCode loop guard")
command_source = first_existing(COMMAND_SOURCE_CANDIDATES, "Kaiju Coder 7 OpenCode command")
if not args.skip_runner and not runtime_available():
missing = ", ".join(str(path) for path in RUNTIME_REQUIRED if not path.exists())
raise FileNotFoundError(f"Missing Kaiju router runtime file(s): {missing}")
existing = load_json(config_path)
template = load_json(config_source)
merged = merge_provider(existing, template, args.base_url, plugin_dest, set_defaults=not args.no_defaults)
print(f"Config: {config_path}")
print(f"Agent: {agent_dest}")
print(f"Plugin: {plugin_dest}")
print(f"Command: {command_dest}")
print(f"Package: {package_dest}")
if not args.skip_runner:
print(f"Runtime: {runtime_dest}")
print(f"Runner: {runner_dest}")
if args.dry_run:
print(
json.dumps(
{
"plugin": merged.get("plugin", []),
"model": merged.get("model"),
"default_agent": merged.get("default_agent"),
"kaiju": merged.get("provider", {}).get("kaiju", {}),
"command": str(command_dest),
"package": str(package_dest),
"package_dependency": "@opencode-ai/plugin",
"runtime": None if args.skip_runner else str(runtime_dest),
"runner": None if args.skip_runner else str(runner_dest),
},
indent=2,
)
)
return 0
write_json(config_path, merged)
agent_dest.parent.mkdir(parents=True, exist_ok=True)
command_dest.parent.mkdir(parents=True, exist_ok=True)
shutil.copy2(agent_source, agent_dest)
shutil.copy2(plugin_source, plugin_dest)
shutil.copy2(command_source, command_dest)
write_plugin_package_json(args.config_dir)
if not args.skip_runner:
copy_runtime(runtime_dest)
write_runner(runner_dest, runtime_dest)
print("Installed Kaiju Coder 7 OpenCode profile.")
if not args.skip_runner:
print(f"Runner command: {runner_dest}")
if args.no_defaults:
print("Run: opencode -m kaiju/kaiju-coder-7 --agent kaiju-coder-7")
else:
print("Run: opencode")
return 0
if __name__ == "__main__":
raise SystemExit(main())