diff --git a/modules/workstation.nix b/modules/workstation.nix index 60abd360..a2d1082b 100644 --- a/modules/workstation.nix +++ b/modules/workstation.nix @@ -57,6 +57,7 @@ _: { git-find-commit agents hass-cli-wrapped + llm-wrapped pm pdfshrink nixplatforms diff --git a/pkgs/default.nix b/pkgs/default.nix index 9de0d50b..97538c9a 100644 --- a/pkgs/default.nix +++ b/pkgs/default.nix @@ -84,6 +84,7 @@ gen-commit-msg = pkgs.callPackage ./gen-commit-msg { inherit self'; }; git-find-commit = pkgs.callPackage ./git-find-commit { }; agents = pkgs.callPackage ./agents { inherit self'; }; + llm-wrapped = pkgs.callPackage ./llm-wrapped { inherit wrapPackage; }; inherit ntfy-wrapped hass-cli-wrapped git-wrapped; send-file = pkgs.callPackage ./send-file { inherit ntfy-wrapped; }; pm = pkgs.callPackage ./pm { }; diff --git a/pkgs/llm-wrapped/default.nix b/pkgs/llm-wrapped/default.nix new file mode 100644 index 00000000..35a53e43 --- /dev/null +++ b/pkgs/llm-wrapped/default.nix @@ -0,0 +1,37 @@ +# Wraps the llm CLI (simonw/llm) so switching between model providers needs +# no imperative setup (`llm keys set`, hand-edited config in $HOME): +# - OpenAI: OPENAI_API_KEY read at runtime from the agenix secret (an +# existing value in the environment wins), mirroring hass-cli-wrapped +# - GitHub Copilot: extra-openai-models.yaml routes copilot-* models through +# the local copilot-api proxy (modules/copilot-api.nix, port 4141) +# - Ollama: llm-ollama plugin baked in; talks to a server on localhost:11434 +# +# llm reads extra-openai-models.yaml from LLM_USER_PATH, but that directory +# must stay writable (llm keeps logs.db there), so it can't point at the +# store. The wrapper points it at a state directory and refreshes the +# store-sourced config there on every launch, keeping the file declarative. +{ + llm, + writeText, + wrapPackage, +}: +let + extraOpenaiModels = writeText "extra-openai-models.yaml" '' + - model_id: copilot-gpt-4.1 + model_name: gpt-4.1 + api_base: http://localhost:4141/v1 + - model_id: copilot-sonnet + model_name: claude-sonnet-4.6 + api_base: http://localhost:4141/v1 + ''; +in +wrapPackage { + package = llm.withPlugins { llm-ollama = true; }; + + run = [ + ''export LLM_USER_PATH="''${LLM_USER_PATH:-''${XDG_STATE_HOME:-$HOME/.local/state}/llm}"'' + ''mkdir -p "$LLM_USER_PATH"'' + ''cp -f ${extraOpenaiModels} "$LLM_USER_PATH/extra-openai-models.yaml"'' + ''export OPENAI_API_KEY="''${OPENAI_API_KEY:-$(< /run/agenix/openai-api-key)}"'' + ]; +}