diff options
| -rw-r--r-- | dot_claude/mcp-config.json | 8 | ||||
| -rw-r--r-- | dot_claude/settings.json | 15 | ||||
| -rw-r--r-- | dot_claude/symlink_CLAUDE.md | 1 | ||||
| -rw-r--r-- | dot_config/opencode/opencode.json | 13 | ||||
| -rw-r--r-- | dot_config/opencode/symlink_AGENTS.md | 1 | ||||
| -rw-r--r-- | dot_config/zsh/dot_zshrc | 3 | ||||
| -rw-r--r-- | dot_copilot/mcp-config.json | 9 | ||||
| -rw-r--r-- | dot_copilot/settings.json | 7 | ||||
| -rw-r--r-- | dot_copilot/symlink_copilot-instructions.md | 1 | ||||
| -rw-r--r-- | dot_hermes/managed/config.yaml | 4 | ||||
| -rw-r--r-- | dot_hermes/symlink_SOUL.md | 1 | ||||
| -rw-r--r-- | dot_omp/agent/mcp.json | 9 | ||||
| -rw-r--r-- | dot_omp/agent/policy.yml | 6 | ||||
| -rw-r--r-- | dot_omp/agent/symlink_AGENTS.md | 1 | ||||
| -rw-r--r-- | justfile | 11 | ||||
| -rw-r--r-- | nix/common.nix | 78 | ||||
| -rw-r--r-- | nix/flake.nix | 186 | ||||
| -rw-r--r-- | nix/releases.json | 37 | ||||
| -rw-r--r-- | nix/update-releases.sh | 142 |
19 files changed, 519 insertions, 14 deletions
diff --git a/dot_claude/mcp-config.json b/dot_claude/mcp-config.json new file mode 100644 index 0000000..fcde374 --- /dev/null +++ b/dot_claude/mcp-config.json @@ -0,0 +1,8 @@ +{ + "mcpServers": { + "openaiDeveloperDocs": { + "type": "http", + "url": "https://developers.openai.com/mcp" + } + } +} diff --git a/dot_claude/settings.json b/dot_claude/settings.json new file mode 100644 index 0000000..73db790 --- /dev/null +++ b/dot_claude/settings.json @@ -0,0 +1,15 @@ +{ + "permissions": { + "defaultMode": "bypassPermissions" + }, + "skipDangerousModePermissionPrompt": true, + "env": { + "CLAUDE_CODE_EFFORT_LEVEL": "max", + "DISABLE_AUTOUPDATER": "1" + }, + "attribution": { + "commit": "", + "pr": "" + }, + "autoMemoryEnabled": false +} diff --git a/dot_claude/symlink_CLAUDE.md b/dot_claude/symlink_CLAUDE.md new file mode 100644 index 0000000..b69d663 --- /dev/null +++ b/dot_claude/symlink_CLAUDE.md @@ -0,0 +1 @@ +../.codex/AGENTS.md diff --git a/dot_config/opencode/opencode.json b/dot_config/opencode/opencode.json new file mode 100644 index 0000000..c92e1fa --- /dev/null +++ b/dot_config/opencode/opencode.json @@ -0,0 +1,13 @@ +{ + "$schema": "https://opencode.ai/config.json", + "autoupdate": false, + "share": "disabled", + "permission": "allow", + "mcp": { + "openaiDeveloperDocs": { + "type": "remote", + "url": "https://developers.openai.com/mcp", + "enabled": true + } + } +} diff --git a/dot_config/opencode/symlink_AGENTS.md b/dot_config/opencode/symlink_AGENTS.md new file mode 100644 index 0000000..ea1aa2c --- /dev/null +++ b/dot_config/opencode/symlink_AGENTS.md @@ -0,0 +1 @@ +../../.codex/AGENTS.md diff --git a/dot_config/zsh/dot_zshrc b/dot_config/zsh/dot_zshrc index 17c3d1b..8371c15 100644 --- a/dot_config/zsh/dot_zshrc +++ b/dot_config/zsh/dot_zshrc @@ -428,9 +428,6 @@ alias astfc='flang -fc1 -fdebug-dump-parse-tree' alias symfc='flang -fc1 -fdebug-dump-symbols' alias gdbr='gdb -ex start --args' -# GitHub Copilot CLI -alias copilot='gh copilot --autopilot --enable-all-github-mcp-tools --yolo --resume' - # ── Alias completions ───────────────────────────────────────────────────────── # Guard compdef calls on registered completion functions. # Usage: _dot_compdef <target-cmd> <alias>=<target> [<alias>=<target>...] diff --git a/dot_copilot/mcp-config.json b/dot_copilot/mcp-config.json new file mode 100644 index 0000000..1440afe --- /dev/null +++ b/dot_copilot/mcp-config.json @@ -0,0 +1,9 @@ +{ + "mcpServers": { + "openaiDeveloperDocs": { + "type": "http", + "url": "https://developers.openai.com/mcp", + "tools": ["*"] + } + } +} diff --git a/dot_copilot/settings.json b/dot_copilot/settings.json new file mode 100644 index 0000000..5f7b9b2 --- /dev/null +++ b/dot_copilot/settings.json @@ -0,0 +1,7 @@ +{ + "model": "claude-opus-4.6", + "effortLevel": "max", + "autoUpdate": false, + "includeCoAuthoredBy": false, + "experimental": true +} diff --git a/dot_copilot/symlink_copilot-instructions.md b/dot_copilot/symlink_copilot-instructions.md new file mode 100644 index 0000000..b69d663 --- /dev/null +++ b/dot_copilot/symlink_copilot-instructions.md @@ -0,0 +1 @@ +../.codex/AGENTS.md diff --git a/dot_hermes/managed/config.yaml b/dot_hermes/managed/config.yaml new file mode 100644 index 0000000..c82340b --- /dev/null +++ b/dot_hermes/managed/config.yaml @@ -0,0 +1,4 @@ +agent: + reasoning_effort: max +approvals: + mode: "off" diff --git a/dot_hermes/symlink_SOUL.md b/dot_hermes/symlink_SOUL.md new file mode 100644 index 0000000..b69d663 --- /dev/null +++ b/dot_hermes/symlink_SOUL.md @@ -0,0 +1 @@ +../.codex/AGENTS.md diff --git a/dot_omp/agent/mcp.json b/dot_omp/agent/mcp.json new file mode 100644 index 0000000..3c610dc --- /dev/null +++ b/dot_omp/agent/mcp.json @@ -0,0 +1,9 @@ +{ + "$schema": "https://raw.githubusercontent.com/can1357/oh-my-pi/main/packages/coding-agent/src/config/mcp-schema.json", + "mcpServers": { + "openaiDeveloperDocs": { + "type": "http", + "url": "https://developers.openai.com/mcp" + } + } +} diff --git a/dot_omp/agent/policy.yml b/dot_omp/agent/policy.yml new file mode 100644 index 0000000..1da1a68 --- /dev/null +++ b/dot_omp/agent/policy.yml @@ -0,0 +1,6 @@ +defaultThinkingLevel: max +textVerbosity: low +tools: + approvalMode: yolo +startup: + checkUpdate: false diff --git a/dot_omp/agent/symlink_AGENTS.md b/dot_omp/agent/symlink_AGENTS.md new file mode 100644 index 0000000..ea1aa2c --- /dev/null +++ b/dot_omp/agent/symlink_AGENTS.md @@ -0,0 +1 @@ +../../.codex/AGENTS.md @@ -75,8 +75,11 @@ arch-news-check: arch-news-read: @sh "{{ justfile_directory() }}/dot_local/bin/executable_arch-news-check" --mark-read -# Refresh nix flake inputs (nixpkgs, home-manager) then re-activate the profile. -nix-update: _nix-flake-update nix-switch +# Refresh package releases and Nix flake inputs, then re-activate the profile. +nix-update: _nix-release-update _nix-flake-update nix-switch + +_nix-release-update: + @bash "{{ justfile_directory() }}/nix/update-releases.sh" _nix-flake-update: #!/usr/bin/env dash @@ -149,7 +152,7 @@ _lockfiles-commit: set -euo pipefail cd "{{ justfile_directory() }}" - lockfiles=(nix/flake.lock dot_config/nvim/nvim-pack-lock.json) + lockfiles=(nix/flake.lock nix/releases.json dot_config/nvim/nvim-pack-lock.json) changed=() for f in "${lockfiles[@]}"; do if ! git diff --quiet -- "$f" || ! git diff --cached --quiet -- "$f"; then @@ -172,7 +175,7 @@ _lockfiles-commit: has_nvim=0 for f in "${staged[@]}"; do case "$f" in - nix/flake.lock) has_nix=1 ;; + nix/flake.lock|nix/releases.json) has_nix=1 ;; dot_config/nvim/nvim-pack-lock.json) has_nvim=1 ;; esac done diff --git a/nix/common.nix b/nix/common.nix index 7c94c28..143b161 100644 --- a/nix/common.nix +++ b/nix/common.nix @@ -8,6 +8,45 @@ # Shared Home-Manager package profile. Chezmoi owns dotfile deployment. +let + configuredClaude = pkgs.symlinkJoin { + name = "claude-configured-${pkgs.claude-release.version}"; + paths = [ pkgs.claude-release ]; + nativeBuildInputs = [ pkgs.makeWrapper ]; + postBuild = '' + wrapProgram "$out/bin/claude" \ + --add-flags --mcp-config \ + --add-flags "${config.home.homeDirectory}/.claude/mcp-config.json" + ''; + }; + configuredCopilot = pkgs.symlinkJoin { + name = "copilot-configured-${pkgs.copilot-release.version}"; + paths = [ pkgs.copilot-release ]; + nativeBuildInputs = [ pkgs.makeWrapper ]; + postBuild = '' + wrapProgram "$out/bin/copilot" \ + --set COPILOT_ALLOW_ALL true + ''; + }; + configuredHermes = pkgs.symlinkJoin { + name = "hermes-configured-${pkgs.hermes-release.version}"; + paths = [ pkgs.hermes-release ]; + nativeBuildInputs = [ pkgs.makeWrapper ]; + postBuild = '' + wrapProgram "$out/bin/hermes" \ + --set HERMES_MANAGED_DIR "${config.home.homeDirectory}/.hermes/managed" + ''; + }; + configuredOmp = pkgs.symlinkJoin { + name = "omp-configured-${pkgs.omp-release.version}"; + paths = [ pkgs.omp-release ]; + nativeBuildInputs = [ pkgs.makeWrapper ]; + postBuild = '' + wrapProgram "$out/bin/omp" \ + --set PI_CONFIG_FILES "${config.home.homeDirectory}/.omp/agent/policy.yml" + ''; + }; +in { home.stateVersion = "25.05"; @@ -139,10 +178,14 @@ uv # for project tooling that asks for `uv`/`uvx`; brings no python python3Packages.ipython # interactive REPL; pulls its own python, only `ipython` lands on PATH - # AI coding agents - claude-code - codex # OpenAI Codex CLI - github-copilot-cli # `copilot`; prebuilt-binary derivation since 1.0.43 + # AI tools + configuredClaude # Anthropic latest release pinned in nix/releases.json + codex-release # OpenAI stable release pinned in nix/releases.json + configuredCopilot # GitHub stable release pinned in nix/releases.json + configuredHermes # Hermes Agent stable release pinned in nix/releases.json + configuredOmp # Oh My Pi stable release pinned in nix/releases.json + opencode-release # OpenCode stable release pinned in nix/releases.json + ori-release # OpenRouter Ori stable release pinned in nix/releases.json tuicr # interactive git-change reviewer; flake input, see nix/flake.nix. Skill: dot_claude/skills/tuicr/ aibox # Bubblewrap sandbox for AI coding agent sessions; flake input, see nix/flake.nix @@ -189,7 +232,32 @@ zsh-history-substring-search ]; - # ── direnv + nix-direnv ───────────────────────────────────────────────────── + # AI agent policy + # Hermes keeps MCP and provider settings in one mutable file. Merge only the + # shared server so authentication and provider choices stay untracked. + home.activation.configureHermesMcp = lib.hm.dag.entryAfter [ "writeBoundary" ] '' + config_file="$HOME/.hermes/config.yaml" + mkdir -p "$(dirname "$config_file")" + if [ ! -e "$config_file" ]; then + printf '{}\n' >"$config_file" + fi + + if current_url="$(${pkgs.yq-go}/bin/yq -r '.mcp_servers.openaiDeveloperDocs.url // ""' "$config_file" 2>/dev/null)" \ + && current_enabled="$(${pkgs.yq-go}/bin/yq -r '.mcp_servers.openaiDeveloperDocs.enabled // false' "$config_file" 2>/dev/null)"; then + if [ "$current_url" != "https://developers.openai.com/mcp" ] || [ "$current_enabled" != true ]; then + ${pkgs.yq-go}/bin/yq -i ' + .mcp_servers.openaiDeveloperDocs = { + "url": "https://developers.openai.com/mcp", + "enabled": true + } + ' "$config_file" + fi + else + echo "warning: cannot update invalid Hermes config: $config_file" >&2 + fi + ''; + + # direnv + nix-direnv programs.direnv = { enable = true; nix-direnv.enable = true; diff --git a/nix/flake.nix b/nix/flake.nix index 834e213..d871ce7 100644 --- a/nix/flake.nix +++ b/nix/flake.nix @@ -35,6 +35,8 @@ ... }: let + releases = builtins.fromJSON (builtins.readFile ./releases.json); + hermes = builtins.getFlake "github:NousResearch/hermes-agent/${releases.hermes.rev}"; system = "x86_64-linux"; pkgs = import nixpkgs { inherit system; @@ -44,10 +46,190 @@ (final: prev: { tuicr = tuicr.packages.${system}.default; aibox = aibox.packages.${system}.default; + claude-release = prev.claude-code.overrideAttrs { + version = releases.claude.version; + src = final.fetchurl { + inherit (releases.claude) url hash; + }; + }; + copilot-release = final.stdenvNoCC.mkDerivation { + pname = "github-copilot-cli"; + version = releases.copilot.version; + src = final.fetchurl { + inherit (releases.copilot) url hash; + }; + sourceRoot = "."; + nativeBuildInputs = [ + final.autoPatchelfHook + final.makeBinaryWrapper + ]; + buildInputs = [ + final.glibc + final.stdenv.cc.cc.lib + final.glib + final.libsecret + ]; + runtimeDependencies = [ + final.glibc + final.stdenv.cc.cc.lib + final.glib + final.libsecret + ]; + dontStrip = true; + installPhase = '' + runHook preInstall + install -Dm755 copilot "$out/libexec/copilot" + makeWrapper "$out/libexec/copilot" "$out/bin/copilot" \ + --add-flag --no-auto-update \ + --set-default SSL_CERT_DIR ${final.cacert}/etc/ssl/certs \ + --prefix PATH : ${final.lib.makeBinPath [ final.bash ]} + runHook postInstall + ''; + meta = { + description = "GitHub Copilot CLI"; + homepage = "https://github.com/github/copilot-cli"; + license = final.lib.licenses.unfree; + mainProgram = "copilot"; + platforms = [ "x86_64-linux" ]; + sourceProvenance = with final.lib.sourceTypes; [ + binaryNativeCode + binaryBytecode + obfuscatedCode + ]; + }; + }; + codex-release = final.stdenvNoCC.mkDerivation { + pname = "codex"; + version = releases.codex.version; + src = final.fetchurl { + inherit (releases.codex) url hash; + }; + sourceRoot = "."; + nativeBuildInputs = [ final.autoPatchelfHook ]; + buildInputs = [ + final.glibc + final.ncurses + ]; + runtimeDependencies = [ + final.glibc + final.ncurses + ]; + installPhase = '' + runHook preInstall + mkdir -p "$out" + cp -R . "$out/" + chmod -R u+w "$out" + runHook postInstall + ''; + meta = { + description = "OpenAI Codex CLI"; + homepage = "https://developers.openai.com/codex/cli"; + license = final.lib.licenses.asl20; + mainProgram = "codex"; + platforms = [ "x86_64-linux" ]; + sourceProvenance = [ final.lib.sourceTypes.binaryNativeCode ]; + }; + }; + hermes-release = hermes.packages.${system}.minimal; + omp-release = final.stdenvNoCC.mkDerivation { + pname = "oh-my-pi"; + version = releases.omp.version; + src = final.fetchurl { + inherit (releases.omp) url hash; + }; + dontUnpack = true; + nativeBuildInputs = [ final.makeBinaryWrapper ]; + dontStrip = true; + installPhase = '' + runHook preInstall + install -Dm755 "$src" "$out/libexec/omp" + makeWrapper ${final.glibc}/lib/ld-linux-x86-64.so.2 "$out/bin/omp" \ + --add-flags --library-path \ + --add-flags ${final.glibc}/lib \ + --add-flags "$out/libexec/omp" + runHook postInstall + ''; + meta = { + description = "AI coding agent for the terminal"; + homepage = "https://github.com/can1357/oh-my-pi"; + license = final.lib.licenses.mit; + mainProgram = "omp"; + platforms = [ "x86_64-linux" ]; + sourceProvenance = with final.lib.sourceTypes; [ + binaryNativeCode + binaryBytecode + ]; + }; + }; + opencode-release = final.stdenvNoCC.mkDerivation { + pname = "opencode"; + version = releases.opencode.version; + src = final.fetchurl { + inherit (releases.opencode) url hash; + }; + sourceRoot = "."; + nativeBuildInputs = [ + final.autoPatchelfHook + final.makeBinaryWrapper + ]; + buildInputs = [ final.glibc ]; + runtimeDependencies = [ final.glibc ]; + dontStrip = true; + installPhase = '' + runHook preInstall + install -Dm755 opencode "$out/bin/opencode" + wrapProgram "$out/bin/opencode" \ + --prefix PATH : ${final.lib.makeBinPath [ final.ripgrep ]} \ + --set OPENCODE_DISABLE_AUTOUPDATE true + runHook postInstall + ''; + meta = { + description = "AI coding agent built for the terminal"; + homepage = "https://opencode.ai"; + license = final.lib.licenses.mit; + mainProgram = "opencode"; + platforms = [ "x86_64-linux" ]; + sourceProvenance = with final.lib.sourceTypes; [ + binaryNativeCode + binaryBytecode + ]; + }; + }; + ori-release = final.stdenvNoCC.mkDerivation { + pname = "ori"; + version = releases.ori.version; + src = final.fetchurl { + inherit (releases.ori) url hash; + }; + dontUnpack = true; + nativeBuildInputs = [ final.makeBinaryWrapper ]; + dontStrip = true; + installPhase = '' + runHook preInstall + install -Dm755 "$src" "$out/libexec/ori" + makeWrapper ${final.glibc}/lib/ld-linux-x86-64.so.2 "$out/bin/ori" \ + --add-flags --library-path \ + --add-flags ${final.glibc}/lib \ + --add-flags "$out/libexec/ori" \ + --set ORI_NO_UPDATE_CHECK 1 \ + --set ORI_TELEMETRY 0 + runHook postInstall + ''; + meta = { + description = "OpenRouter harness for local coding agents"; + homepage = "https://openrouter.ai/blog/announcements/ori-harness/"; + license = final.lib.licenses.asl20; + mainProgram = "ori"; + platforms = [ "x86_64-linux" ]; + sourceProvenance = with final.lib.sourceTypes; [ + binaryNativeCode + binaryBytecode + ]; + }; + }; }) ]; - # Whitelist specific unfree packages (claude-code, - # github-copilot-cli) instead of globally setting allowUnfree, + # Whitelist specific unfree packages instead of globally setting allowUnfree, # so a typo elsewhere can't silently pull in additional unfree # deps. config.allowUnfreePredicate = diff --git a/nix/releases.json b/nix/releases.json new file mode 100644 index 0000000..9e5825a --- /dev/null +++ b/nix/releases.json @@ -0,0 +1,37 @@ +{ + "claude": { + "version": "2.1.267", + "url": "https://downloads.claude.ai/claude-code-releases/2.1.267/linux-x64/claude.zst", + "hash": "sha256-8h7WbQLr3XWzO4zhnJMJaLKgBqba1cW1nV8rNVYixMA=" + }, + "codex": { + "version": "0.154.0", + "url": "https://github.com/openai/codex/releases/download/rust-v0.154.0/codex-package-x86_64-unknown-linux-musl.tar.gz", + "hash": "sha256-/G4+O4Xyz31mRSDuXGan/kqhK659RoNPR+LxZf0Nb3g=" + }, + "copilot": { + "version": "1.0.83", + "url": "https://github.com/github/copilot-cli/releases/download/v1.0.83/copilot-linux-x64.tar.gz", + "hash": "sha256-/74cQpZkuKBe/tZ+zbRnEj5A/Ko8bBTvmpi6dNpGh7c=" + }, + "hermes": { + "version": "0.21.1", + "tag": "v2026.9.7", + "rev": "2237be355906fbe6065ce1815711eee52b2d646e" + }, + "omp": { + "version": "18.1.16", + "url": "https://github.com/can1357/oh-my-pi/releases/download/v18.1.16/omp-linux-x64", + "hash": "sha256-7+vvt0NZ0gNi4HNB8Bpl/AolnnvHlFTvCLDr9SMquJc=" + }, + "opencode": { + "version": "1.18.30", + "url": "https://github.com/anomalyco/opencode/releases/download/v1.18.30/opencode-linux-x64.tar.gz", + "hash": "sha256-VQByRoWBZUlv+FuhwrZI90IejiATv0GJpoDJ/45pnRc=" + }, + "ori": { + "version": "0.14.1+5bb4241", + "url": "https://github.com/OpenRouterLabs/ori-releases/releases/download/cli-0.14.1-5bb4241/ori-linux-x64", + "hash": "sha256-VqzA5u97tRqgXpy/tS1oXrby+Gtv/hgi6TRfkGLU66Q=" + } +} diff --git a/nix/update-releases.sh b/nix/update-releases.sh new file mode 100644 index 0000000..661bec5 --- /dev/null +++ b/nix/update-releases.sh @@ -0,0 +1,142 @@ +#!/usr/bin/env bash +set -euo pipefail + +if ! command -v nix >/dev/null 2>&1; then + echo "nix not installed; skipping release update" >&2 + exit 0 +fi + +repo_root=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")/.." && pwd) +lockfile="$repo_root/nix/releases.json" +tmp=$(mktemp) +trap 'rm -f "$tmp"' EXIT + +fetch_url() { + local response + if response=$(curl --fail-with-body -sSL "$1"); then + printf '%s\n' "$response" + else + printf 'Failed to fetch %s\n%s\n' "$1" "$response" >&2 + return 1 + fi +} + +github_api() { + if command -v gh >/dev/null 2>&1 && gh auth token --hostname github.com >/dev/null 2>&1; then + gh api --hostname github.com "$1" + else + fetch_url "https://api.github.com/$1" || { + echo 'For a GitHub rate limit, wait for reset or authenticate with: gh auth login --hostname github.com' >&2 + return 1 + } + fi +} + +github_asset() { + local repository=$1 + local asset=$2 + local release + + release=$(github_api "repos/$repository/releases/latest") || return + jq -er --arg asset "$asset" ' + . as $release + | .assets[] + | select(.name == $asset) + | [$release.tag_name, .browser_download_url, .digest] + | @tsv + ' <<<"$release" +} + +sri_hash() { + local digest=${1#sha256:} + nix hash convert --hash-algo sha256 --to sri "$digest" +} + +claude_base=https://downloads.claude.ai/claude-code-releases +claude_version=$(fetch_url "$claude_base/latest") +claude_manifest=$(fetch_url "$claude_base/$claude_version/manifest.zst.json") +claude_binary=$(jq -er '.platforms["linux-x64"].binary' <<<"$claude_manifest") +claude_digest=$(jq -er '.platforms["linux-x64"].checksum' <<<"$claude_manifest") +claude_url="$claude_base/$claude_version/linux-x64/$claude_binary" +asset_info=$(github_asset openai/codex codex-package-x86_64-unknown-linux-musl.tar.gz) +read -r codex_tag codex_url codex_digest <<<"$asset_info" +asset_info=$(github_asset github/copilot-cli copilot-linux-x64.tar.gz) +read -r copilot_tag copilot_url copilot_digest <<<"$asset_info" +hermes_release=$(github_api repos/NousResearch/hermes-agent/releases/latest) +hermes_tag=$(jq -er .tag_name <<<"$hermes_release") +hermes_version=$(jq -er '.name | capture("^Hermes Agent v(?<version>[0-9]+\\.[0-9]+\\.[0-9]+)").version' <<<"$hermes_release") +hermes_rev=$( + github_api "repos/NousResearch/hermes-agent/commits/$hermes_tag" | + jq -er .sha +) +asset_info=$(github_asset can1357/oh-my-pi omp-linux-x64) +read -r omp_tag omp_url omp_digest <<<"$asset_info" +asset_info=$(github_asset anomalyco/opencode opencode-linux-x64.tar.gz) +read -r opencode_tag opencode_url opencode_digest <<<"$asset_info" +asset_info=$(github_asset OpenRouterLabs/ori-releases ori-linux-x64) +read -r ori_tag ori_url ori_digest <<<"$asset_info" + +codex_version=${codex_tag#rust-v} +copilot_version=${copilot_tag#v} +omp_version=${omp_tag#v} +opencode_version=${opencode_tag#v} +ori_version=${ori_tag#cli-} +ori_version=${ori_version/-/+} +if [[ ! $claude_version =~ ^[0-9]+\.[0-9]+\.[0-9]+$ || + $codex_version == "$codex_tag" || + $copilot_version == "$copilot_tag" || + ! $hermes_tag =~ ^v[0-9]{4}\.[0-9]{1,2}\.[0-9]{1,2}$ || + ! $hermes_rev =~ ^[0-9a-f]{40}$ || + $omp_version == "$omp_tag" || + $opencode_version == "$opencode_tag" || + $ori_version == "$ori_tag" ]]; then + echo "unexpected release tag" >&2 + exit 1 +fi +claude_hash=$(sri_hash "$claude_digest") +codex_hash=$(sri_hash "$codex_digest") +copilot_hash=$(sri_hash "$copilot_digest") +omp_hash=$(sri_hash "$omp_digest") +opencode_hash=$(sri_hash "$opencode_digest") +ori_hash=$(sri_hash "$ori_digest") + +jq -n \ + --arg claude_version "$claude_version" \ + --arg claude_url "$claude_url" \ + --arg claude_hash "$claude_hash" \ + --arg codex_version "$codex_version" \ + --arg codex_url "$codex_url" \ + --arg codex_hash "$codex_hash" \ + --arg copilot_version "$copilot_version" \ + --arg copilot_url "$copilot_url" \ + --arg copilot_hash "$copilot_hash" \ + --arg hermes_version "$hermes_version" \ + --arg hermes_tag "$hermes_tag" \ + --arg hermes_rev "$hermes_rev" \ + --arg omp_version "$omp_version" \ + --arg omp_url "$omp_url" \ + --arg omp_hash "$omp_hash" \ + --arg opencode_version "$opencode_version" \ + --arg opencode_url "$opencode_url" \ + --arg opencode_hash "$opencode_hash" \ + --arg ori_version "$ori_version" \ + --arg ori_url "$ori_url" \ + --arg ori_hash "$ori_hash" \ + '{ + claude: {version: $claude_version, url: $claude_url, hash: $claude_hash}, + codex: {version: $codex_version, url: $codex_url, hash: $codex_hash}, + copilot: {version: $copilot_version, url: $copilot_url, hash: $copilot_hash}, + hermes: {version: $hermes_version, tag: $hermes_tag, rev: $hermes_rev}, + omp: {version: $omp_version, url: $omp_url, hash: $omp_hash}, + opencode: {version: $opencode_version, url: $opencode_url, hash: $opencode_hash}, + ori: {version: $ori_version, url: $ori_url, hash: $ori_hash} + }' >"$tmp" + +if cmp -s "$tmp" "$lockfile"; then + echo "release lock is current" + exit 0 +fi + +chmod 0644 "$tmp" +mv "$tmp" "$lockfile" +echo "updated: nix/releases.json" |
