llm: re-add withPlugins, add many plugins, 0.25 -> 0.26 (#411459)

This commit is contained in:
Philip Taron 2025-06-03 11:19:26 -07:00 committed by GitHub
commit 24f4a11d7b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
54 changed files with 1892 additions and 330 deletions

View file

@ -1,43 +1,3 @@
{
lib,
python3Packages,
fetchFromGitHub,
versionCheckHook,
}:
{ python3Packages }:
python3Packages.buildPythonApplication rec {
pname = "files-to-prompt";
version = "0.6";
pyproject = true;
src = fetchFromGitHub {
owner = "simonw";
repo = "files-to-prompt";
tag = version;
hash = "sha256-LWp/DNP3bsh7/goQGkpi4x2N11tRuhLVh2J8H6AUH0w=";
};
build-system = with python3Packages; [
setuptools
];
dependencies = with python3Packages; [
click
];
nativeCheckInputs = with python3Packages; [
pytestCheckHook
versionCheckHook
];
versionCheckProgramArg = "--version";
meta = {
description = "Concatenate a directory full of files into a single prompt for use with LLMs";
homepage = "https://github.com/simonw/files-to-prompt/";
changelog = "https://github.com/simonw/files-to-prompt/releases/tag/${src.tag}";
license = lib.licenses.asl20;
maintainers = with lib.maintainers; [ erethon ];
mainProgram = "files-to-prompt";
};
}
python3Packages.toPythonApplication python3Packages.files-to-prompt

View file

@ -1,41 +1,3 @@
{
lib,
python3Packages,
fetchFromGitHub,
bash,
git,
less,
}:
{ python3Packages }:
python3Packages.buildPythonApplication rec {
pname = "icdiff";
version = "2.0.7";
src = fetchFromGitHub {
owner = "jeffkaufman";
repo = "icdiff";
tag = "release-${version}";
hash = "sha256-XOw/xhPGlzi1hAgzQ1EtioUM476A+lQWLlvvaxd9j08=";
};
# error: could not lock config file /homeless-shelter/.gitconfig: No such file or directory
doCheck = false;
nativeCheckInputs = [
bash
git
less
];
checkPhase = ''
patchShebangs test.sh
./test.sh ${python3Packages.python.interpreter}
'';
meta = {
homepage = "https://www.jefftk.com/icdiff";
description = "Side-by-side highlighted command line diffs";
maintainers = [ ];
license = lib.licenses.psfl;
};
}
python3Packages.toPythonApplication python3Packages.icdiff

View file

@ -0,0 +1,46 @@
# The `...` allows this derivation to be overridden with `enable-<llm-plugin>`.
#
# Example:
#
# ```nix
# llm.override {
# enable-llm-anthropic = true;
# enable-llm-gemini = true;
# enable-llm-cmd = true;
# enable-llm-templates-github = true;
# }
# ```
#
# Whatever names are accepted by `llm.withPlugins` are accepted with an added `enable-` prefix as
# an override of this derivation. The user can also do `llm.withPlugins { llm-anthropic = true; }`.
{ lib, python3Packages, ... }@args:
let
inherit (python3Packages) llm;
hasEnablePrefix = lib.hasPrefix "enable-";
addEnablePrefix = name: "enable-${name}";
removeEnablePrefix = lib.removePrefix "enable-";
# Filter to just the attributes which are named "enable-<plugin-name>"
enableArgs = lib.filterAttrs (name: value: hasEnablePrefix name) args;
pluginArgs = lib.mapAttrs' (
name: value: lib.nameValuePair (removeEnablePrefix name) value
) enableArgs;
# Provide some diagnostics for the plugin names
pluginNames = lib.attrNames (lib.functionArgs llm.withPlugins);
enableNames = lib.map addEnablePrefix pluginNames;
unknownPluginNames = lib.removeAttrs pluginArgs pluginNames;
unknownNames = lib.map addEnablePrefix (lib.attrNames unknownPluginNames);
unknownNamesDiagnostic = ''
Unknown plugins specified in override: ${lib.concatStringsSep ", " unknownNames}
Valid overrides:
- ${lib.concatStringsSep "\n - " enableNames}
'';
in
assert lib.assertMsg (lib.length unknownNames == 0) unknownNamesDiagnostic;
llm.withPlugins pluginArgs

View file

@ -0,0 +1,45 @@
{
lib,
click,
setuptools,
fetchFromGitHub,
buildPythonPackage,
pytestCheckHook,
versionCheckHook,
}:
buildPythonPackage rec {
pname = "files-to-prompt";
version = "0.6";
pyproject = true;
src = fetchFromGitHub {
owner = "simonw";
repo = "files-to-prompt";
tag = version;
hash = "sha256-LWp/DNP3bsh7/goQGkpi4x2N11tRuhLVh2J8H6AUH0w=";
};
build-system = [ setuptools ];
dependencies = [ click ];
nativeCheckInputs = [
pytestCheckHook
versionCheckHook
];
versionCheckProgramArg = "--version";
meta = {
mainProgram = "files-to-prompt";
description = "Concatenate a directory full of files into a single prompt for use with LLMs";
homepage = "https://github.com/simonw/files-to-prompt";
changelog = "https://github.com/simonw/files-to-prompt/releases/tag/${src.tag}";
license = lib.licenses.asl20;
maintainers = with lib.maintainers; [
erethon
philiptaron
];
};
}

View file

@ -0,0 +1,35 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Philip Taron <philip.taron@gmail.com>
Date: Thu, 29 May 2025 14:47:58 -0700
Subject: [PATCH] Don't test black or flake8
Signed-off-by: Philip Taron <philip.taron@gmail.com>
---
test.sh | 14 --------------
1 file changed, 14 deletions(-)
diff --git a/test.sh b/test.sh
index 1dd6c4be579e8a61d2d284b042c54cd2a1e0ff77..dc9ecab4a9097878a0a65c45df38a4fa25eb9fa2 100755
--- a/test.sh
+++ b/test.sh
@@ -210,20 +210,6 @@ function ensure_installed() {
fi
}
-ensure_installed "black"
-echo 'Running black formatter...'
-if ! black icdiff --quiet --line-length 79 --check; then
- echo ""
- echo 'Consider running `black icdiff --line-length 79`'
- fail
-fi
-
-ensure_installed "flake8"
-echo 'Running flake8 linter...'
-if ! flake8 icdiff; then
- fail
-fi
-
if ! $REGOLD; then
echo PASS
fi

View file

@ -0,0 +1,61 @@
{
lib,
stdenv,
python,
buildPythonPackage,
fetchFromGitHub,
setuptools,
pytestCheckHook,
writableTmpDirAsHomeHook,
pkgs,
}:
let
inherit (pkgs) bash git less;
in
buildPythonPackage rec {
pname = "icdiff";
version = "2.0.7";
pyproject = true;
src = fetchFromGitHub {
owner = "jeffkaufman";
repo = "icdiff";
tag = "release-${version}";
hash = "sha256-XOw/xhPGlzi1hAgzQ1EtioUM476A+lQWLlvvaxd9j08=";
leaveDotGit = true;
};
patches = [ ./0001-Don-t-test-black-or-flake8.patch ];
build-system = [ setuptools ];
pythonImportsCheck = [ "icdiff" ];
nativeCheckInputs = [
bash
git
less
writableTmpDirAsHomeHook
];
# Odd behavior in the sandbox
doCheck = !stdenv.hostPlatform.isDarwin;
checkPhase = ''
runHook preCheck
patchShebangs test.sh
./test.sh ${python.interpreter}
runHook postCheck
'';
meta = {
description = "Improved colorized diff";
homepage = "https://github.com/jeffkaufman/icdiff";
changelog = "https://github.com/jeffkaufman/icdiff/releases/tag/release-${version}/CHANGELOG.md";
license = lib.licenses.psfl;
maintainers = with lib.maintainers; [ philiptaron ];
};
}

View file

@ -1,10 +1,10 @@
{
lib,
callPackage,
buildPythonPackage,
fetchFromGitHub,
setuptools,
llm,
llm-anthropic,
anthropic,
pytestCheckHook,
pytest-asyncio,
@ -14,21 +14,24 @@
buildPythonPackage rec {
pname = "llm-anthropic";
version = "0.15.1";
version = "0.17";
pyproject = true;
src = fetchFromGitHub {
owner = "simonw";
repo = "llm-anthropic";
tag = version;
hash = "sha256-8bVs3MJteOTCiw7n/4pMf+oXMhsQbCSzUFVQqm2ezcE=";
hash = "sha256-2fatBKZMttC5flzfC7MWCpduc3m6IOVWZiW1K2dYqis=";
};
build-system = [
setuptools
];
dependencies = [
anthropic
llm
];
dependencies = [ anthropic ];
nativeCheckInputs = [
pytestCheckHook
@ -39,9 +42,7 @@ buildPythonPackage rec {
pythonImportsCheck = [ "llm_anthropic" ];
passthru.tests = {
llm-plugin = callPackage ./tests/llm-plugin.nix { };
};
passthru.tests = llm.mkPluginTest llm-anthropic;
meta = {
description = "LLM access to models by Anthropic, including the Claude series";

View file

@ -1,22 +0,0 @@
{
runCommand,
python,
yq,
}:
let
venv = python.withPackages (ps: [
ps.llm
ps.llm-anthropic
]);
in
runCommand "llm-anthropic-test-llm-plugin"
{
nativeBuildInputs = [
venv
yq
];
}
''
llm plugins | yq --exit-status 'any(.name == "llm-anthropic")'
touch "$out"
''

View file

@ -1,6 +1,5 @@
{
lib,
callPackage,
buildPythonPackage,
fetchFromGitHub,
# build-system
@ -11,6 +10,7 @@
pygments,
# tests
pytestCheckHook,
llm-cmd,
}:
buildPythonPackage rec {
@ -27,13 +27,11 @@ buildPythonPackage rec {
# Only needed until https://github.com/simonw/llm-cmd/pull/18 is merged and released
patches = [ ./fix-test.patch ];
build-system = [
setuptools
# Follows the reasoning from https://github.com/NixOS/nixpkgs/pull/327800#discussion_r1681586659 about including llm in build-system
llm
];
build-system = [ setuptools ];
dependencies = [
llm
prompt-toolkit
pygments
];
@ -46,15 +44,16 @@ buildPythonPackage rec {
"llm_cmd"
];
passthru.tests = {
llm-plugin = callPackage ./tests/llm-plugin.nix { };
};
passthru.tests = llm.mkPluginTest llm-cmd;
meta = {
description = "Use LLM to generate and execute commands in your shell";
homepage = "https://github.com/simonw/llm-cmd";
changelog = "https://github.com/simonw/llm-cmd/releases/tag/${version}";
license = lib.licenses.asl20;
maintainers = with lib.maintainers; [ erethon ];
maintainers = with lib.maintainers; [
erethon
philiptaron
];
};
}

View file

@ -1,22 +0,0 @@
{
runCommand,
python,
yq,
}:
let
venv = python.withPackages (ps: [
ps.llm
ps.llm-cmd
]);
in
runCommand "llm-cmd-test-llm-plugin"
{
nativeBuildInputs = [
venv
yq
];
}
''
llm plugins | yq --exit-status 'any(.name == "llm-cmd")'
touch "$out"
''

View file

@ -0,0 +1,50 @@
{
lib,
buildPythonPackage,
fetchFromGitHub,
setuptools,
llm,
llm-command-r,
cohere,
pytestCheckHook,
pytest-recording,
writableTmpDirAsHomeHook,
}:
buildPythonPackage rec {
pname = "llm-command-r";
version = "0.3.1";
pyproject = true;
src = fetchFromGitHub {
owner = "simonw";
repo = "llm-command-r";
tag = version;
hash = "sha256-PxICRds9NJQP64HwoL7Oxd39yaIrMdAyQEbhaumJCgo=";
};
build-system = [ setuptools ];
dependencies = [
cohere
llm
];
nativeCheckInputs = [
pytestCheckHook
pytest-recording
writableTmpDirAsHomeHook
];
pythonImportsCheck = [ "llm_command_r" ];
passthru.tests = llm.mkPluginTest llm-command-r;
meta = {
description = "Access the Cohere Command R family of models";
homepage = "https://github.com/simonw/llm-command-r";
changelog = "https://github.com/simonw/llm-command-r/releases/tag/${version}/CHANGELOG.md";
license = lib.licenses.asl20;
maintainers = with lib.maintainers; [ philiptaron ];
};
}

View file

@ -0,0 +1,37 @@
{
lib,
buildPythonPackage,
fetchFromGitHub,
setuptools,
llm,
llm-deepseek,
}:
buildPythonPackage rec {
pname = "llm-deepseek";
version = "0.1.6";
pyproject = true;
src = fetchFromGitHub {
owner = "abrasumente233";
repo = "llm-deepseek";
tag = version;
hash = "sha256-yrNvIGnU9Q/0H786DsM0wGEwfxZYIk8IXhqC4mWaQAA=";
};
build-system = [ setuptools ];
dependencies = [ llm ];
pythonImportsCheck = [ "llm_deepseek" ];
passthru.tests = llm.mkPluginTest llm-deepseek;
meta = {
description = "LLM plugin providing access to Deepseek models.";
homepage = "https://github.com/abrasumente233/llm-deepseek";
changelog = "https://github.com/abrasumente233/llm-deepseek/releases/tag/${version}/CHANGELOG.md";
license = lib.licenses.asl20;
maintainers = with lib.maintainers; [ philiptaron ];
};
}

View file

@ -0,0 +1,37 @@
{
lib,
buildPythonPackage,
fetchFromGitHub,
setuptools,
llm,
llm-docs,
}:
buildPythonPackage rec {
pname = "llm-docs";
version = "0.2.1";
pyproject = true;
src = fetchFromGitHub {
owner = "simonw";
repo = "llm-docs";
tag = version;
hash = "sha256-+Ha6L2h8p/yA073MfO2Uvd6E4bKA2xAvaBWtvjqglOw=";
};
build-system = [ setuptools ];
dependencies = [ llm ];
pythonImportsCheck = [ "llm_docs" ];
passthru.tests = llm.mkPluginTest llm-docs;
meta = {
description = "Ask questions of LLM documentation using LLM";
homepage = "https://github.com/simonw/llm-docs";
changelog = "https://github.com/simonw/llm-docs/releases/tag/${version}/CHANGELOG.md";
license = lib.licenses.asl20;
maintainers = with lib.maintainers; [ philiptaron ];
};
}

View file

@ -0,0 +1,44 @@
{
lib,
buildPythonPackage,
fetchFromGitHub,
setuptools,
llm,
llm-echo,
pytestCheckHook,
writableTmpDirAsHomeHook,
}:
buildPythonPackage rec {
pname = "llm-echo";
version = "0.3a3";
pyproject = true;
src = fetchFromGitHub {
owner = "simonw";
repo = "llm-echo";
tag = version;
hash = "sha256-4345UIyaQx+mYYBAFD5AaX5YbjbnJQt8bKMD5Vl8VJc=";
};
build-system = [ setuptools ];
dependencies = [ llm ];
nativeCheckInputs = [
pytestCheckHook
writableTmpDirAsHomeHook
];
pythonImportsCheck = [ "llm_echo" ];
passthru.tests = llm.mkPluginTest llm-echo;
meta = {
description = "Debug plugin for LLM";
homepage = "https://github.com/simonw/llm-echo";
changelog = "https://github.com/simonw/llm-echo/releases/tag/${version}/CHANGELOG.md";
license = lib.licenses.asl20;
maintainers = with lib.maintainers; [ philiptaron ];
};
}

View file

@ -0,0 +1,37 @@
{
lib,
buildPythonPackage,
fetchFromGitHub,
setuptools,
llm,
llm-fragments-github,
}:
buildPythonPackage rec {
pname = "llm-fragments-github";
version = "0.4";
pyproject = true;
src = fetchFromGitHub {
owner = "simonw";
repo = "llm-fragments-github";
tag = version;
hash = "sha256-7i1WRix5AAEG5EXJqtaU+QY56aL0SePdqz84z+C+iYM=";
};
build-system = [ setuptools ];
dependencies = [ llm ];
pythonImportsCheck = [ "llm_fragments_github" ];
passthru.tests = llm.mkPluginTest llm-fragments-github;
meta = {
description = "Load GitHub repository contents as LLM fragments";
homepage = "https://github.com/simonw/llm-fragments-github";
changelog = "https://github.com/simonw/llm-fragments-github/releases/tag/${version}/CHANGELOG.md";
license = lib.licenses.asl20;
maintainers = with lib.maintainers; [ philiptaron ];
};
}

View file

@ -0,0 +1,41 @@
{
lib,
buildPythonPackage,
fetchFromGitHub,
hatchling,
llm,
llm-fragments-pypi,
httpx,
}:
buildPythonPackage rec {
pname = "llm-fragments-pypi";
version = "0.1.1";
pyproject = true;
src = fetchFromGitHub {
owner = "samueldg";
repo = "llm-fragments-pypi";
tag = version;
hash = "sha256-1XqAmuZ1WMHD6JbLbLsK9K4Uf3FvvKJD4mn1G2J/3C8=";
};
build-system = [ hatchling ];
dependencies = [
httpx
llm
];
pythonImportsCheck = [ "llm_fragments_pypi" ];
passthru.tests = llm.mkPluginTest llm-fragments-pypi;
meta = {
description = "LLM fragments plugin for PyPI packages metadata";
homepage = "https://github.com/samueldg/llm-fragments-pypi";
changelog = "https://github.com/samueldg/llm-fragments-pypi/releases/tag/${version}/CHANGELOG.md";
license = lib.licenses.asl20;
maintainers = with lib.maintainers; [ philiptaron ];
};
}

View file

@ -0,0 +1,49 @@
{
lib,
buildPythonPackage,
fetchFromGitHub,
setuptools,
httpx,
httpx-sse,
llm,
llm-fragments-reader,
pytestCheckHook,
pytest-asyncio,
pytest-httpx,
writableTmpDirAsHomeHook,
}:
buildPythonPackage rec {
pname = "llm-fragments-reader";
version = "0.1";
pyproject = true;
src = fetchFromGitHub {
owner = "simonw";
repo = "llm-fragments-reader";
tag = version;
hash = "sha256-2xdvOpMGsTtnerrlGiVSHoJrM+GQ7Zgv+zn2SAwYAL4=";
};
build-system = [ setuptools ];
dependencies = [ llm ];
nativeCheckInputs = [
pytestCheckHook
pytest-httpx
writableTmpDirAsHomeHook
];
pythonImportsCheck = [ "llm_fragments_reader" ];
passthru.tests = llm.mkPluginTest llm-fragments-reader;
meta = {
description = "Run URLs through the Jina Reader API";
homepage = "https://github.com/simonw/llm-fragments-reader";
changelog = "https://github.com/simonw/llm-fragments-reader/releases/tag/${version}/CHANGELOG.md";
license = lib.licenses.asl20;
maintainers = with lib.maintainers; [ philiptaron ];
};
}

View file

@ -0,0 +1,48 @@
{
lib,
buildPythonPackage,
fetchFromGitHub,
setuptools,
symbex,
llm,
llm-fragments-symbex,
pytestCheckHook,
writableTmpDirAsHomeHook,
}:
buildPythonPackage rec {
pname = "llm-fragments-symbex";
version = "0.1";
pyproject = true;
src = fetchFromGitHub {
owner = "simonw";
repo = "llm-fragments-symbex";
tag = version;
hash = "sha256-LECMHv4tGMCY60JU68y2Sfxp97Px7T/RJVhYVDSFCy4=";
};
build-system = [ setuptools ];
dependencies = [
llm
symbex
];
nativeCheckInputs = [
pytestCheckHook
writableTmpDirAsHomeHook
];
pythonImportsCheck = [ "llm_fragments_symbex" ];
passthru.tests = llm.mkPluginTest llm-fragments-symbex;
meta = {
description = "LLM fragment loader for Python symbols";
homepage = "https://github.com/simonw/llm-fragments-symbex";
changelog = "https://github.com/simonw/llm-fragments-symbex/releases/tag/${version}/CHANGELOG.md";
license = lib.licenses.asl20;
maintainers = with lib.maintainers; [ philiptaron ];
};
}

View file

@ -1,10 +1,10 @@
{
lib,
callPackage,
buildPythonPackage,
fetchFromGitHub,
setuptools,
llm,
llm-gemini,
httpx,
ijson,
pytestCheckHook,
@ -15,24 +15,22 @@
}:
buildPythonPackage rec {
pname = "llm-gemini";
version = "0.20";
version = "0.21";
pyproject = true;
src = fetchFromGitHub {
owner = "simonw";
repo = "llm-gemini";
tag = version;
hash = "sha256-haaJtJ9RqV5/n/j8PNXPS7zc332W+gU20x0wGPRdzOQ=";
hash = "sha256-aCP0YjcghzpgceuZRKGTN15wm7OIPCwcJAJJBxh78f4=";
};
build-system = [
setuptools
];
build-system = [ setuptools ];
dependencies = [
llm
httpx
ijson
llm
];
nativeCheckInputs = [
@ -45,9 +43,7 @@ buildPythonPackage rec {
pythonImportsCheck = [ "llm_gemini" ];
passthru.tests = {
llm-plugin = callPackage ./tests/llm-plugin.nix { };
};
passthru.tests = llm.mkPluginTest llm-gemini;
meta = {
description = "LLM plugin to access Google's Gemini family of models";

View file

@ -1,22 +0,0 @@
{
runCommand,
python,
yq,
}:
let
venv = python.withPackages (ps: [
ps.llm
ps.llm-gemini
]);
in
runCommand "llm-gemini-test-llm-plugin"
{
nativeBuildInputs = [
venv
yq
];
}
''
llm plugins | yq --exit-status 'any(.name == "llm-gemini")'
touch "$out"
''

View file

@ -1,6 +1,5 @@
{
lib,
callPackage,
buildPythonPackage,
fetchFromGitHub,
@ -11,6 +10,7 @@
httpx,
llama-cpp-python,
llm,
llm-gguf,
}:
buildPythonPackage rec {
@ -25,14 +25,12 @@ buildPythonPackage rec {
hash = "sha256-ihMOiQnTfgZKICVDoQHLOMahrd+GiB+HwWFBMyIcs0A=";
};
build-system = [
setuptools
];
build-system = [ setuptools ];
dependencies = [
httpx
llama-cpp-python
llm
llama-cpp-python
];
pythonImportsCheck = [ "llm_gguf" ];
@ -40,9 +38,7 @@ buildPythonPackage rec {
# Tests require internet access (downloading models)
doCheck = false;
passthru.tests = {
llm-plugin = callPackage ./tests/llm-plugin.nix { };
};
passthru.tests = llm.mkPluginTest llm-gguf;
meta = {
description = "Run models distributed as GGUF files using LLM";

View file

@ -1,22 +0,0 @@
{
runCommand,
python,
yq,
}:
let
venv = python.withPackages (ps: [
ps.llm
ps.llm-gguf
]);
in
runCommand "llm-gguf-test-llm-plugin"
{
nativeBuildInputs = [
venv
yq
];
}
''
llm plugins | yq --exit-status 'any(.name == "llm-gguf")'
touch "$out"
''

View file

@ -0,0 +1,62 @@
{
lib,
buildPythonPackage,
fetchFromGitHub,
setuptools,
click,
deepmerge,
pyyaml,
rich,
pygments,
llm,
llm-git,
pytestCheckHook,
pytest-cov-stub,
pytest-asyncio,
pytest-httpx,
writableTmpDirAsHomeHook,
}:
buildPythonPackage rec {
pname = "llm-git";
version = "0.2.2";
pyproject = true;
src = fetchFromGitHub {
owner = "OttoAllmendinger";
repo = "llm-git";
tag = "v${version}";
hash = "sha256-LcIsJPQgZ4gj2t7sSa0Wu35WHWYyquZZTS/UxojH+XU=";
};
build-system = [
setuptools
];
dependencies = [
click
deepmerge
llm
pyyaml
rich
pygments
];
nativeCheckInputs = [
pytestCheckHook
pytest-cov-stub
writableTmpDirAsHomeHook
];
pythonImportsCheck = [ "llm_git" ];
passthru.tests = llm.mkPluginTest llm-git;
meta = {
description = "AI-powered Git commands for the LLM CLI tool";
homepage = "https://github.com/OttoAllmendinger/llm-git";
changelog = "https://github.com/OttoAllmendinger/llm-git/releases/tag/${version}/CHANGELOG.md";
license = lib.licenses.asl20;
maintainers = with lib.maintainers; [ philiptaron ];
};
}

View file

@ -0,0 +1,54 @@
{
lib,
buildPythonPackage,
fetchFromGitHub,
setuptools,
llm,
llm-grok,
httpx,
httpx-sse,
rich,
pytestCheckHook,
pytest-httpx,
writableTmpDirAsHomeHook,
}:
buildPythonPackage rec {
pname = "llm-grok";
version = "1.0.1";
pyproject = true;
src = fetchFromGitHub {
owner = "Hiepler";
repo = "llm-grok";
tag = "v${version}";
hash = "sha256-OeeU/53XKucLCtGvnl5RWc/QqF0TprB/SO8pnnK5fdw=";
};
build-system = [ setuptools ];
dependencies = [
llm
httpx
httpx-sse
rich
];
nativeCheckInputs = [
pytestCheckHook
pytest-httpx
writableTmpDirAsHomeHook
];
pythonImportsCheck = [ "llm_grok" ];
passthru.tests = llm.mkPluginTest llm-grok;
meta = {
description = "LLM plugin providing access to Grok models using the xAI API";
homepage = "https://github.com/Hiepler/llm-grok";
changelog = "https://github.com/Hiepler/llm-grok/releases/tag/${src.tag}/CHANGELOG.md";
license = lib.licenses.asl20;
maintainers = with lib.maintainers; [ philiptaron ];
};
}

View file

@ -0,0 +1,43 @@
{
lib,
buildPythonPackage,
fetchFromGitHub,
setuptools,
llm,
llm-groq,
groq,
}:
buildPythonPackage rec {
pname = "llm-groq";
version = "0.8";
pyproject = true;
src = fetchFromGitHub {
owner = "angerman";
repo = "llm-groq";
tag = "v${version}";
hash = "sha256-sZ5d9w43NvypaPrebwZ5BLgRaCHAhd7gBU6uHEdUaF4=";
};
build-system = [
setuptools
];
dependencies = [
groq
llm
];
pythonImportsCheck = [ "llm_groq" ];
passthru.tests = llm.mkPluginTest llm-groq;
meta = {
description = "LLM plugin providing access to Groqcloud models.";
homepage = "https://github.com/angerman/llm-groq";
changelog = "https://github.com/angerman/llm-groq/releases/tag/${src.tag}/CHANGELOG.md";
license = lib.licenses.asl20;
maintainers = with lib.maintainers; [ philiptaron ];
};
}

View file

@ -0,0 +1,37 @@
{
lib,
buildPythonPackage,
fetchFromGitHub,
setuptools,
llm,
llm-hacker-news,
}:
buildPythonPackage rec {
pname = "llm-hacker-news";
version = "0.1.1";
pyproject = true;
src = fetchFromGitHub {
owner = "simonw";
repo = "llm-hacker-news";
tag = version;
hash = "sha256-pywx9TAN/mnGR6Vv6YsPhLO4R5Geagw/bcydQjvTH5s=";
};
build-system = [ setuptools ];
dependencies = [ llm ];
pythonImportsCheck = [ "llm_hacker_news" ];
passthru.tests = llm.mkPluginTest llm-hacker-news;
meta = {
description = "LLM plugin for pulling content from Hacker News";
homepage = "https://github.com/simonw/llm-hacker-news";
changelog = "https://github.com/simonw/llm-hacker-news/releases/tag/${version}/CHANGELOG.md";
license = lib.licenses.asl20;
maintainers = with lib.maintainers; [ philiptaron ];
};
}

View file

@ -1,11 +1,10 @@
{
lib,
callPackage,
buildPythonPackage,
fetchFromGitHub,
setuptools,
llm,
nix-update-script,
llm-jq,
}:
buildPythonPackage rec {
pname = "llm-jq";
@ -19,19 +18,13 @@ buildPythonPackage rec {
hash = "sha256-Mf/tbB9+UdmSRpulqv5Wagr8wjDcRrNs2741DNQZhO4=";
};
build-system = [
setuptools
];
build-system = [ setuptools ];
dependencies = [
llm
];
dependencies = [ llm ];
pythonImportsCheck = [ "llm_jq" ];
passthru.tests = {
llm-plugin = callPackage ./tests/llm-plugin.nix { };
};
passthru.tests = llm.mkPluginTest llm-jq;
meta = {
description = "Write and execute jq programs with the help of LLM";

View file

@ -1,23 +0,0 @@
{
runCommand,
python,
yq,
}:
let
venv = python.withPackages (ps: [
ps.llm
ps.llm-jq
]);
in
runCommand "llm-jq-test-llm-plugin"
{
nativeBuildInputs = [
venv
yq
];
}
''
llm plugins | yq --exit-status 'any(.name == "llm-jq")'
llm jq --help
touch "$out"
''

View file

@ -0,0 +1,44 @@
{
lib,
buildPythonPackage,
fetchFromGitHub,
setuptools,
llm,
llm-llama-server,
pytestCheckHook,
writableTmpDirAsHomeHook,
}:
buildPythonPackage rec {
pname = "llm-llama-server";
version = "0.2";
pyproject = true;
src = fetchFromGitHub {
owner = "simonw";
repo = "llm-llama-server";
tag = version;
hash = "sha256-jtFSfGu3JhNUfTsspY+OFLTMt9jQrh6R05sK9KBOKTE=";
};
build-system = [ setuptools ];
dependencies = [ llm ];
nativeCheckInputs = [
pytestCheckHook
writableTmpDirAsHomeHook
];
pythonImportsCheck = [ "llm_llama_server" ];
passthru.tests = llm.mkPluginTest llm-llama-server;
meta = {
description = "LLM plugin providing access to Mistral models using the Mistral API";
homepage = "https://github.com/simonw/llm-llama-server";
changelog = "https://github.com/simonw/llm-llama-server/releases/tag/${version}/CHANGELOG.md";
license = lib.licenses.asl20;
maintainers = with lib.maintainers; [ philiptaron ];
};
}

View file

@ -0,0 +1,56 @@
{
lib,
buildPythonPackage,
fetchFromGitHub,
setuptools,
httpx,
httpx-sse,
llm,
llm-mistral,
pytestCheckHook,
pytest-asyncio,
pytest-httpx,
writableTmpDirAsHomeHook,
}:
buildPythonPackage rec {
pname = "llm-mistral";
version = "0.14";
pyproject = true;
src = fetchFromGitHub {
owner = "simonw";
repo = "llm-mistral";
tag = version;
hash = "sha256-NuiqRA/SCjGq0hJsnHJ/vgdncIKu3oE9WqWGht7QRMc=";
};
build-system = [
setuptools
];
dependencies = [
httpx
httpx-sse
llm
];
nativeCheckInputs = [
pytestCheckHook
pytest-asyncio
pytest-httpx
writableTmpDirAsHomeHook
];
pythonImportsCheck = [ "llm_mistral" ];
passthru.tests = llm.mkPluginTest llm-mistral;
meta = {
description = "LLM plugin providing access to Mistral models using the Mistral API";
homepage = "https://github.com/simonw/llm-mistral";
changelog = "https://github.com/simonw/llm-mistral/releases/tag/${version}/CHANGELOG.md";
license = lib.licenses.asl20;
maintainers = with lib.maintainers; [ philiptaron ];
};
}

View file

@ -1,6 +1,5 @@
{
lib,
callPackage,
buildPythonPackage,
fetchFromGitHub,
@ -18,28 +17,26 @@
pytest-asyncio,
pytest-mock,
writableTmpDirAsHomeHook,
llm-ollama,
}:
buildPythonPackage rec {
pname = "llm-ollama";
version = "0.10.0";
version = "0.11.0";
pyproject = true;
src = fetchFromGitHub {
owner = "taketwo";
repo = "llm-ollama";
tag = version;
hash = "sha256-IA9Tb82XB+Gr6YwMVqzsw1dPtT3GWK2W/ZtuDVznF1A";
hash = "sha256-iwrDqrPt/zwXypBwD7zDAcen4fQq6PXl7Xj5VUL2KWA=";
};
build-system = [
setuptools
# Follows the reasoning from https://github.com/NixOS/nixpkgs/pull/327800#discussion_r1681586659 about including llm in build-system
llm
];
build-system = [ setuptools ];
dependencies = [
click
llm
ollama
pydantic
];
@ -55,9 +52,7 @@ buildPythonPackage rec {
"llm_ollama"
];
passthru.tests = {
llm-plugin = callPackage ./tests/llm-plugin.nix { };
};
passthru.tests = llm.mkPluginTest llm-ollama;
meta = {
description = "LLM plugin providing access to Ollama models using HTTP API";

View file

@ -1,24 +0,0 @@
{
runCommand,
python,
yq,
cacert,
}:
let
venv = python.withPackages (ps: [
ps.llm
ps.llm-ollama
]);
in
runCommand "llm-ollama-test-llm-plugin"
{
nativeBuildInputs = [
venv
yq
];
env.SSL_CERT_FILE = "${cacert}/etc/ssl/certs/ca-bundle.crt";
}
''
llm plugins | yq --exit-status 'any(.name == "llm-ollama")'
touch "$out"
''

View file

@ -1,10 +1,10 @@
{
lib,
callPackage,
buildPythonPackage,
fetchFromGitHub,
setuptools,
llm,
llm-openai-plugin,
openai,
pytestCheckHook,
pytest-asyncio,
@ -25,9 +25,7 @@ buildPythonPackage rec {
hash = "sha256-UoUxCwR+qOUufHuS0gw6A5Q7sB77VO4HYuMjFGN7mhA=";
};
build-system = [
setuptools
];
build-system = [ setuptools ];
dependencies = [
llm
@ -45,9 +43,7 @@ buildPythonPackage rec {
pythonImportsCheck = [ "llm_openai" ];
passthru.tests = {
llm-plugin = callPackage ./tests/llm-plugin.nix { };
};
passthru.tests = llm.mkPluginTest llm-openai-plugin;
meta = {
description = "OpenAI plugin for LLM";

View file

@ -1,22 +0,0 @@
{
runCommand,
python,
yq,
}:
let
venv = python.withPackages (ps: [
ps.llm
ps.llm-openai-plugin
]);
in
runCommand "llm-openai-plugin-test-llm-plugin"
{
nativeBuildInputs = [
venv
yq
];
}
''
llm plugins | yq --exit-status 'any(.name == "llm-openai-plugin")'
touch "$out"
''

View file

@ -0,0 +1,56 @@
{
lib,
buildPythonPackage,
fetchFromGitHub,
setuptools,
llm,
llm-openrouter,
httpx,
openai,
pytestCheckHook,
inline-snapshot,
pytest-recording,
writableTmpDirAsHomeHook,
}:
buildPythonPackage rec {
pname = "llm-openrouter";
version = "0.4.1";
pyproject = true;
src = fetchFromGitHub {
owner = "simonw";
repo = "llm-openrouter";
tag = version;
hash = "sha256-ojBkyXqEaqTcOv7mzTWL5Ihhb50zeVzeQZNA6DySuVg=";
};
build-system = [
setuptools
];
dependencies = [
httpx
llm
openai
];
nativeCheckInputs = [
pytestCheckHook
inline-snapshot
pytest-recording
writableTmpDirAsHomeHook
];
pythonImportsCheck = [ "llm_openrouter" ];
passthru.tests = llm.mkPluginTest llm-openrouter;
meta = {
description = "LLM plugin for models hosted by OpenRouter";
homepage = "https://github.com/simonw/llm-openrouter";
changelog = "https://github.com/simonw/llm-openrouter/releases/tag/${version}/CHANGELOG.md";
license = lib.licenses.asl20;
maintainers = with lib.maintainers; [ philiptaron ];
};
}

View file

@ -0,0 +1,49 @@
{
lib,
buildPythonPackage,
fetchFromGitHub,
setuptools,
pymupdf,
llm,
llm-pdf-to-images,
pytestCheckHook,
pytest-asyncio,
writableTmpDirAsHomeHook,
}:
buildPythonPackage rec {
pname = "llm-pdf-to-images";
version = "0.1";
pyproject = true;
src = fetchFromGitHub {
owner = "simonw";
repo = "llm-pdf-to-images";
tag = version;
hash = "sha256-UWtCPdKrGE93NNjCroct5fPhq1pWIkngXXtRb+BHm8k=";
};
build-system = [ setuptools ];
dependencies = [
llm
pymupdf
];
nativeCheckInputs = [
pytestCheckHook
writableTmpDirAsHomeHook
];
pythonImportsCheck = [ "llm_pdf_to_images" ];
passthru.tests = llm.mkPluginTest llm-pdf-to-images;
meta = {
description = "LLM fragment plugin to load a PDF as a sequence of images";
homepage = "https://github.com/simonw/llm-pdf-to-images";
changelog = "https://github.com/simonw/llm-pdf-to-images/releases/tag/${version}/CHANGELOG.md";
license = lib.licenses.asl20;
maintainers = with lib.maintainers; [ philiptaron ];
};
}

View file

@ -0,0 +1,56 @@
{
lib,
buildPythonPackage,
fetchFromGitHub,
setuptools,
llm,
llm-sentence-transformers,
einops,
sentence-transformers,
pytestCheckHook,
writableTmpDirAsHomeHook,
}:
buildPythonPackage rec {
pname = "llm-sentence-transformers";
version = "0.3.2";
pyproject = true;
src = fetchFromGitHub {
owner = "simonw";
repo = "llm-sentence-transformers";
tag = version;
hash = "sha256-FDDMItKFEYEptiL3EHKgKVxClqRU9RaM3uD3xP0F4OM=";
};
build-system = [ setuptools ];
dependencies = [
einops
llm
sentence-transformers
];
nativeCheckInputs = [
pytestCheckHook
writableTmpDirAsHomeHook
];
# Disabled because they access the network
disabledTests = [
"test_run_embedding"
"test_embed_multi_with_generator"
];
pythonImportsCheck = [ "llm_sentence_transformers" ];
passthru.tests = llm.mkPluginTest llm-sentence-transformers;
meta = {
description = "LLM plugin for embeddings using sentence-transformers";
homepage = "https://github.com/simonw/llm-sentence-transformers";
changelog = "https://github.com/simonw/llm-sentence-transformers/releases/tag/${version}/CHANGELOG.md";
license = lib.licenses.asl20;
maintainers = with lib.maintainers; [ philiptaron ];
};
}

View file

@ -0,0 +1,37 @@
{
lib,
buildPythonPackage,
fetchFromGitHub,
setuptools,
llm,
llm-templates-fabric,
}:
buildPythonPackage rec {
pname = "llm-templates-fabric";
version = "0.2";
pyproject = true;
src = fetchFromGitHub {
owner = "simonw";
repo = "llm-templates-fabric";
tag = version;
hash = "sha256-tfkSjeT9WstUsNCtVr3fMzqELFCtfYphqf3xFGvHaV0=";
};
build-system = [ setuptools ];
dependencies = [ llm ];
pythonImportsCheck = [ "llm_templates_fabric" ];
passthru.tests = llm.mkPluginTest llm-templates-fabric;
meta = {
description = "Load LLM templates from Fabric";
homepage = "https://github.com/simonw/llm-templates-fabric";
changelog = "https://github.com/simonw/llm-templates-fabric/releases/tag/${version}/CHANGELOG.md";
license = lib.licenses.asl20;
maintainers = with lib.maintainers; [ philiptaron ];
};
}

View file

@ -0,0 +1,37 @@
{
lib,
buildPythonPackage,
fetchFromGitHub,
setuptools,
llm,
llm-templates-github,
}:
buildPythonPackage rec {
pname = "llm-templates-github";
version = "0.1";
pyproject = true;
src = fetchFromGitHub {
owner = "simonw";
repo = "llm-templates-github";
tag = version;
hash = "sha256-SFXrvpKrvfIP0JmXQt6OZ52kne4AEtiggbshyac9XQc=";
};
build-system = [ setuptools ];
dependencies = [ llm ];
pythonImportsCheck = [ "llm_templates_github" ];
passthru.tests = llm.mkPluginTest llm-templates-github;
meta = {
description = "Load LLM templates from GitHub repositories";
homepage = "https://github.com/simonw/llm-templates-github";
changelog = "https://github.com/simonw/llm-templates-github/releases/tag/${version}/CHANGELOG.md";
license = lib.licenses.asl20;
maintainers = with lib.maintainers; [ philiptaron ];
};
}

View file

@ -0,0 +1,48 @@
{
lib,
buildPythonPackage,
fetchFromGitHub,
setuptools,
llm,
llm-tools-datasette,
llm-echo,
pytestCheckHook,
pytest-httpx,
writableTmpDirAsHomeHook,
}:
buildPythonPackage rec {
pname = "llm-tools-datasette";
version = "0.1";
pyproject = true;
src = fetchFromGitHub {
owner = "simonw";
repo = "llm-tools-datasette";
tag = version;
hash = "sha256-Us9bPk2qpTlgJqQ0Cl9QdeqW+h8j+pmnkriM0WXEyyA=";
};
build-system = [ setuptools ];
dependencies = [ llm ];
nativeCheckInputs = [
llm-echo
pytestCheckHook
pytest-httpx
writableTmpDirAsHomeHook
];
pythonImportsCheck = [ "llm_tools_datasette" ];
passthru.tests = llm.mkPluginTest llm-tools-datasette;
meta = {
description = "Expose Datasette instances to LLM as a tool";
homepage = "https://github.com/simonw/llm-tools-datasette";
changelog = "https://github.com/simonw/llm-tools-datasette/releases/tag/${version}/CHANGELOG.md";
license = lib.licenses.asl20;
maintainers = with lib.maintainers; [ philiptaron ];
};
}

View file

@ -0,0 +1,50 @@
{
lib,
buildPythonPackage,
fetchFromGitHub,
setuptools,
quickjs,
llm,
llm-tools-quickjs,
llm-echo,
pytestCheckHook,
writableTmpDirAsHomeHook,
}:
buildPythonPackage rec {
pname = "llm-tools-quickjs";
version = "0.1";
pyproject = true;
src = fetchFromGitHub {
owner = "simonw";
repo = "llm-tools-quickjs";
tag = version;
hash = "sha256-Si3VcHnRUj8Q/N8pRhltPOM6K64TX9DBH/u4WQxQJjQ=";
};
build-system = [ setuptools ];
dependencies = [
llm
quickjs
];
nativeCheckInputs = [
llm-echo
pytestCheckHook
writableTmpDirAsHomeHook
];
pythonImportsCheck = [ "llm_tools_quickjs" ];
passthru.tests = llm.mkPluginTest llm-tools-quickjs;
meta = {
description = "JavaScript execution as a tool for LLM";
homepage = "https://github.com/simonw/llm-tools-quickjs";
changelog = "https://github.com/simonw/llm-tools-quickjs/releases/tag/${version}/CHANGELOG.md";
license = lib.licenses.asl20;
maintainers = with lib.maintainers; [ philiptaron ];
};
}

View file

@ -0,0 +1,50 @@
{
lib,
buildPythonPackage,
fetchFromGitHub,
setuptools,
llm,
llm-tools-simpleeval,
llm-echo,
pytestCheckHook,
simpleeval,
writableTmpDirAsHomeHook,
}:
buildPythonPackage rec {
pname = "llm-tools-simpleeval";
version = "0.1.1";
pyproject = true;
src = fetchFromGitHub {
owner = "simonw";
repo = "llm-tools-simpleeval";
tag = version;
hash = "sha256-IOmYu7zoim7Co/xIm5VLaGkCPI0o+2Nb2Pu3U2fH0BU=";
};
build-system = [ setuptools ];
dependencies = [
llm
simpleeval
];
nativeCheckInputs = [
llm-echo
pytestCheckHook
writableTmpDirAsHomeHook
];
pythonImportsCheck = [ "llm_tools_simpleeval" ];
passthru.tests = llm.mkPluginTest llm-tools-simpleeval;
meta = {
description = "Make simple_eval available as an LLM tool";
homepage = "https://github.com/simonw/llm-tools-simpleeval";
changelog = "https://github.com/simonw/llm-tools-simpleeval/releases/tag/${version}/CHANGELOG.md";
license = lib.licenses.asl20;
maintainers = with lib.maintainers; [ philiptaron ];
};
}

View file

@ -0,0 +1,46 @@
{
lib,
buildPythonPackage,
fetchFromGitHub,
setuptools,
llm,
llm-tools-sqlite,
llm-echo,
pytestCheckHook,
writableTmpDirAsHomeHook,
}:
buildPythonPackage rec {
pname = "llm-tools-sqlite";
version = "0.1";
pyproject = true;
src = fetchFromGitHub {
owner = "simonw";
repo = "llm-tools-sqlite";
tag = version;
hash = "sha256-VAmK4cXzZWTWCU92TwMdhNJPvYPZ88t5BZe8vo60SZY=";
};
build-system = [ setuptools ];
dependencies = [ llm ];
nativeCheckInputs = [
llm-echo
pytestCheckHook
writableTmpDirAsHomeHook
];
pythonImportsCheck = [ "llm_tools_sqlite" ];
passthru.tests = llm.mkPluginTest llm-tools-sqlite;
meta = {
description = "LLM tools for running queries against SQLite";
homepage = "https://github.com/simonw/llm-tools-sqlite";
changelog = "https://github.com/simonw/llm-tools-sqlite/releases/tag/${version}/CHANGELOG.md";
license = lib.licenses.asl20;
maintainers = with lib.maintainers; [ philiptaron ];
};
}

View file

@ -0,0 +1,40 @@
{
lib,
buildPythonPackage,
fetchFromGitHub,
setuptools,
llm,
llm-venice,
}:
buildPythonPackage rec {
pname = "llm-venice";
version = "0.7.0";
pyproject = true;
src = fetchFromGitHub {
owner = "ar-jan";
repo = "llm-venice";
tag = version;
hash = "sha256-vsb3oXGr+2FDJnTwYomICfald1ptben28hAJ8ypKiBI=";
};
build-system = [ setuptools ];
dependencies = [ llm ];
# Reaches out to the real API
doCheck = false;
pythonImportsCheck = [ "llm_venice" ];
passthru.tests = llm.mkPluginTest llm-venice;
meta = {
description = "LLM plugin to access models available via the Venice API";
homepage = "https://github.com/ar-jan/llm-venice";
changelog = "https://github.com/ar-jan/llm-venice/releases/tag/${version}/CHANGELOG.md";
license = lib.licenses.asl20;
maintainers = with lib.maintainers; [ philiptaron ];
};
}

View file

@ -0,0 +1,37 @@
{
lib,
buildPythonPackage,
fetchFromGitHub,
setuptools,
llm,
llm-video-frames,
}:
buildPythonPackage rec {
pname = "llm-video-frames";
version = "0.1";
pyproject = true;
src = fetchFromGitHub {
owner = "simonw";
repo = "llm-video-frames";
tag = version;
hash = "sha256-brTyBymoFuvSQzsD/4aWzFGCrh3yEmWbpsUNGKT9dcU=";
};
build-system = [ setuptools ];
dependencies = [ llm ];
pythonImportsCheck = [ "llm_video_frames" ];
passthru.tests = llm.mkPluginTest llm-video-frames;
meta = {
description = "LLM plugin to turn a video into individual frames";
homepage = "https://github.com/simonw/llm-video-frames";
changelog = "https://github.com/simonw/llm-video-frames/releases/tag/${version}/CHANGELOG.md";
license = lib.licenses.asl20;
maintainers = with lib.maintainers; [ philiptaron ];
};
}

View file

@ -1,11 +1,12 @@
diff --git a/llm/cli.py b/llm/cli.py
index af37feb..18b078a 100644
index 5d53e74..c2b4707 100644
--- a/llm/cli.py
+++ b/llm/cli.py
@@ -1014,18 +1014,7 @@ def templates_path():
@@ -2895,30 +2895,38 @@ def display_truncated(text):
help="Include pre-release and development versions",
)
def install(packages, upgrade, editable, force_reinstall, no_cache_dir):
"""Install packages from PyPI into the same environment as LLM"""
def install(packages, upgrade, editable, force_reinstall, no_cache_dir, pre):
- """Install packages from PyPI into the same environment as LLM"""
- args = ["pip", "install"]
- if upgrade:
- args += ["--upgrade"]
@ -15,20 +16,49 @@ index af37feb..18b078a 100644
- args += ["--force-reinstall"]
- if no_cache_dir:
- args += ["--no-cache-dir"]
- if pre:
- args += ["--pre"]
- args += list(packages)
- sys.argv = args
- run_module("pip", run_name="__main__")
+ click.echo("Install command has been disabled for Nix. If you want to install extra llm plugins, use llm.withPlugins([]) expression.")
+ """Install packages from PyPI into the same environment as LLM. Disabled for nixpkgs."""
+ raise click.ClickException(
+"""Install command has been disabled for Nix. To install extra `llm` plugins, use the `llm.withPlugins` function.
+
+Example:
+
+```nix
+llm.withPlugins {
+ @listOfPackagedPlugins@
+}
+```
+"""
+ )
@cli.command()
@@ -1033,8 +1022,7 @@ def install(packages, upgrade, editable, force_reinstall, no_cache_dir):
@click.argument("packages", nargs=-1, required=True)
@click.option("-y", "--yes", is_flag=True, help="Don't ask for confirmation")
def uninstall(packages, yes):
"""Uninstall Python packages from the LLM environment"""
- """Uninstall Python packages from the LLM environment"""
- sys.argv = ["pip", "uninstall"] + list(packages) + (["-y"] if yes else [])
- run_module("pip", run_name="__main__")
+ click.echo("Uninstall command has been disabled for Nix. If you want to uninstall extra llm plugins, just remove them from llm.withPlugins([]) list expression.")
+ """Uninstall Python packages from the LLM environment. Disabled for nixpkgs."""
+ raise click.ClickException(
+"""Uninstall command has been disabled for Nix. To remove `llm` plugins, use the `llm.withPlugins` function with the desired set of plugins specified.
+
+Example:
+
+```nix
+llm.withPlugins {
+ @listOfPackagedPlugins@
+}
+```
+"""
+ )
@cli.command()
--
2.49.0

View file

@ -1,9 +1,12 @@
{
lib,
runCommand,
callPackage,
buildPythonPackage,
fetchFromGitHub,
pytestCheckHook,
pythonOlder,
replaceVars,
setuptools,
click-default-group,
condense-json,
@ -13,18 +16,154 @@
pluggy,
puremagic,
pydantic,
python,
python-ulid,
pyyaml,
sqlite-migrate,
cogapp,
pytest-asyncio,
pytest-httpx,
pytest-recording,
sqlite-utils,
syrupy,
llm-echo,
}:
let
/**
Make a derivation for `llm` that contains `llm` plus the relevant plugins.
The function signature of `withPlugins` is the list of all the plugins `llm` knows about.
Adding a parameter here requires that it be in `python3Packages` attrset.
# Type
```
withPlugins ::
{
llm-anthropic :: bool,
llm-gemini :: bool,
...
}
-> derivation
```
See `lib.attrNames (lib.functionArgs llm.withPlugins)` for the total list of plugins supported.
# Examples
:::{.example}
## `llm.withPlugins` usage example
```nix
llm.withPlugins { llm-gemini = true; llm-groq = true; }
=> «derivation /nix/store/<hash>-python3-3.12.10-llm-with-llm-gemini-llm-groq.drv»
```
:::
*/
withPlugins =
# Keep this list up to date with the plugins in python3Packages!
{
llm-anthropic ? false,
llm-cmd ? false,
llm-command-r ? false,
llm-deepseek ? false,
llm-docs ? false,
llm-echo ? false,
llm-fragments-github ? false,
llm-fragments-pypi ? false,
llm-fragments-reader ? false,
llm-fragments-symbex ? false,
llm-gemini ? false,
llm-gguf ? false,
llm-git ? false,
llm-grok ? false,
llm-groq ? false,
llm-hacker-news ? false,
llm-jq ? false,
llm-llama-server ? false,
llm-mistral ? false,
llm-ollama ? false,
llm-openai-plugin ? false,
llm-openrouter ? false,
llm-pdf-to-images ? false,
llm-sentence-transformers ? false,
llm-templates-fabric ? false,
llm-templates-github ? false,
llm-tools-datasette ? false,
llm-tools-quickjs ? false,
llm-tools-simpleeval ? false,
llm-tools-sqlite ? false,
llm-venice ? false,
llm-video-frames ? false,
...
}@args:
let
# Filter to just the attributes which are set to a true value.
setArgs = lib.filterAttrs (name: lib.id) args;
# Make the derivation name reflect what's inside it, up to a certain limit.
setArgNames = lib.attrNames setArgs;
drvName =
let
len = builtins.length setArgNames;
in
if len == 0 then
"llm-${llm.version}"
else if len > 20 then
"llm-${llm.version}-with-${toString len}-plugins"
else
# Make a string with those names separated with a dash.
"llm-${llm.version}-with-${lib.concatStringsSep "-" setArgNames}";
# Make a python environment with just those plugins.
python-environment = python.withPackages (
ps:
let
# Throw a diagnostic if this list gets out of sync with the names in python3Packages
allPluginsPresent = pluginNames == withPluginsArgNames;
pluginNames = lib.attrNames (lib.intersectAttrs ps withPluginsArgs);
missingNamesList = lib.attrNames (lib.removeAttrs withPluginsArgs pluginNames);
missingNames = lib.concatStringsSep ", " missingNamesList;
# The relevant plugins are the ones the user asked for.
plugins = lib.intersectAttrs setArgs ps;
in
assert lib.assertMsg allPluginsPresent "Missing these plugins: ${missingNames}";
([ ps.llm ] ++ lib.attrValues plugins)
);
in
# That Python environment produced above contains too many irrelevant binaries, due to how
# Python needs to use propagatedBuildInputs. Let's make one with just what's needed: `llm`.
# Since we include the `passthru` and `meta` information, it's as good as the original
# derivation.
runCommand "${python.name}-${drvName}" { inherit (llm) passthru meta; } ''
mkdir -p $out/bin
ln -s ${python-environment}/bin/llm $out/bin/llm
'';
# Uses the `withPlugins` names to make a Python environment with everything.
withAllPlugins = withPlugins (lib.genAttrs withPluginsArgNames (name: true));
# The function signature of `withPlugins` is the list of all the plugins `llm` knows about.
# The plugin directory is at <https://llm.datasette.io/en/stable/plugins/directory.html>
withPluginsArgs = lib.functionArgs withPlugins;
withPluginsArgNames = lib.attrNames withPluginsArgs;
# In order to help with usability, we patch `llm install` and `llm uninstall` to tell users how to
# customize `llm` with plugins in Nix, including the name of the plugin, its description, and
# where it's coming from.
listOfPackagedPlugins = builtins.toFile "plugins.txt" (
lib.concatStringsSep "\n " (
map (name: ''
# ${python.pkgs.${name}.meta.description} <${python.pkgs.${name}.meta.homepage}>
${name} = true;
'') withPluginsArgNames
)
);
llm = buildPythonPackage rec {
pname = "llm";
version = "0.25";
version = "0.26";
pyproject = true;
build-system = [ setuptools ];
@ -35,11 +174,16 @@ let
owner = "simonw";
repo = "llm";
tag = version;
hash = "sha256-iH1P0VdpwIItY1In7vlM0Sn44Db23TqFp8GZ79/GMJs=";
hash = "sha256-KTlNajuZrR0kBX3LatepsNM3PfRVsQn+evEfXTu6juE=";
};
patches = [ ./001-disable-install-uninstall-commands.patch ];
postPatch = ''
substituteInPlace llm/cli.py \
--replace-fail "@listOfPackagedPlugins@" "$(< ${listOfPackagedPlugins})"
'';
dependencies = [
click-default-group
condense-json
@ -61,11 +205,19 @@ let
numpy
pytest-asyncio
pytest-httpx
pytest-recording
syrupy
pytestCheckHook
];
doCheck = true;
# The tests make use of `llm_echo` but that would be a circular dependency.
# So we make a local copy in this derivation, as it's a super-simple package of one file.
preCheck = ''
cp ${llm-echo.src}/llm_echo.py llm_echo.py
'';
pytestFlagsArray = [
"-svv"
"tests/"
@ -74,27 +226,28 @@ let
pythonImportsCheck = [ "llm" ];
passthru = {
inherit withPlugins;
inherit withPlugins withAllPlugins;
mkPluginTest = plugin: {
${plugin.pname} = callPackage ./mk-plugin-test.nix { inherit llm plugin; };
};
# include tests for all the plugins
tests = lib.mergeAttrsList (map (name: python.pkgs.${name}.tests) withPluginsArgNames);
};
meta = with lib; {
meta = {
homepage = "https://github.com/simonw/llm";
description = "Access large language models from the command-line";
changelog = "https://github.com/simonw/llm/releases/tag/${src.tag}";
license = licenses.asl20;
license = lib.licenses.asl20;
mainProgram = "llm";
maintainers = with maintainers; [
maintainers = with lib.maintainers; [
aldoborrero
mccartykim
philiptaron
];
};
};
withPlugins = throw ''
llm.withPlugins was confusing to use and has been removed.
Please migrate to using python3.withPackages(ps: [ ps.llm ]) instead.
See https://nixos.org/manual/nixpkgs/stable/#python.withpackages-function for more usage examples.
'';
in
llm

View file

@ -0,0 +1,27 @@
{
cacert,
runCommand,
writableTmpDirAsHomeHook,
yq,
llm,
plugin,
}:
let
venv = llm.pythonModule.withPackages (_: [
llm
plugin
]);
in
runCommand "${plugin.pname}-test"
{
nativeBuildInputs = [
venv
writableTmpDirAsHomeHook
yq
];
env.SSL_CERT_FILE = "${cacert}/etc/ssl/certs/ca-bundle.crt";
}
''
llm plugins | yq --exit-status 'any(.name == "${plugin.pname}")'
touch "$out"
''

View file

@ -0,0 +1,52 @@
{
lib,
buildPythonPackage,
fetchFromGitHub,
setuptools,
icdiff,
pprintpp,
pytest,
pytestCheckHook,
writableTmpDirAsHomeHook,
}:
buildPythonPackage rec {
pname = "pytest-icdiff";
version = "0.5-unstable-2024-09-04";
pyproject = true;
src = fetchFromGitHub {
owner = "hjwp";
repo = "pytest-icdiff";
rev = "6e2fb8de35e37428a9f7a268c8abb57e9ee285e5";
hash = "sha256-kSeGz5IExldgi955XOEkQnc8uqxkbyvuDOdz9y3AFIY=";
};
build-system = [ setuptools ];
dependencies = [
pytest
icdiff
pprintpp
];
# These are failing on the main branch; disable for now
disabledTests = [
"test_long_dict"
"test_mutliline_strings_have_no_escaped_newlines"
];
nativeCheckInputs = [
pytestCheckHook
writableTmpDirAsHomeHook
];
pythonImportsCheck = [ "pytest_icdiff" ];
meta = {
description = "Better error messages in pytest assertions using icdiff";
homepage = "https://github.com/hjwp/pytest-icdiff";
license = lib.licenses.unlicense;
maintainers = with lib.maintainers; [ philiptaron ];
};
}

View file

@ -0,0 +1,66 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Philip Taron <philip.taron@gmail.com>
Date: Thu, 29 May 2025 17:16:43 -0700
Subject: [PATCH] Update for QuickJS 2025-04-26 release
Signed-off-by: Philip Taron <philip.taron@gmail.com>
---
setup.py | 6 +++---
test_quickjs.py | 6 +++---
2 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/setup.py b/setup.py
index 9d17af357dcadc40478789ef9c82ac82632967d3..d0b4ff2bd7f3450f6f055ee9e2eda6b591d70689 100644
--- a/setup.py
+++ b/setup.py
@@ -16,7 +16,7 @@ if sys.platform == "win32":
# system PATH when compiling.
# 3. The code below will moneky-patch distutils to work.
import distutils.cygwinccompiler
- distutils.cygwinccompiler.get_msvcr = lambda: []
+ distutils.cygwinccompiler.get_msvcr = lambda: []
# Make sure that pthreads is linked statically, otherwise we run into problems
# on computers where it is not installed.
extra_link_args = ["-static"]
@@ -26,7 +26,7 @@ def get_c_sources(include_headers=False):
sources = [
"module.c",
"upstream-quickjs/cutils.c",
- "upstream-quickjs/libbf.c",
+ "upstream-quickjs/dtoa.c",
"upstream-quickjs/libregexp.c",
"upstream-quickjs/libunicode.c",
"upstream-quickjs/quickjs.c",
@@ -34,7 +34,7 @@ def get_c_sources(include_headers=False):
if include_headers:
sources += [
"upstream-quickjs/cutils.h",
- "upstream-quickjs/libbf.h",
+ "upstream-quickjs/dtoa.h",
"upstream-quickjs/libregexp-opcode.h",
"upstream-quickjs/libregexp.h",
"upstream-quickjs/libunicode-table.h",
diff --git a/test_quickjs.py b/test_quickjs.py
index 1f6dec7ccd15092e98e80a9139ae2acff359b010..9444234655fba9d932ce92c82b9d8da8fe83ad5b 100644
--- a/test_quickjs.py
+++ b/test_quickjs.py
@@ -105,8 +105,8 @@ class Context(unittest.TestCase):
else:
self.fail("Expected exception.")
- self.assertIn("at funcA (<input>:3)\n", msg)
- self.assertIn("at funcB (<input>:6)\n", msg)
+ self.assertIn("at funcA (<input>:3:24)\n", msg)
+ self.assertIn("at funcB (<input>:6:26)\n", msg)
def test_memory_limit(self):
code = """
@@ -508,7 +508,7 @@ class FunctionTest(unittest.TestCase):
""")
self.assertEqual(f(100), 100)
- limit = 500
+ limit = 1500
with self.assertRaises(quickjs.StackOverflow):
f(limit)
f.set_max_stack_size(2000 * limit)

View file

@ -0,0 +1,58 @@
{
lib,
buildPythonPackage,
fetchFromGitHub,
setuptools,
poetry-core,
pytestCheckHook,
pkgs,
}:
let
inherit (pkgs) quickjs srcOnly;
in
buildPythonPackage rec {
pname = "quickjs";
version = "1.19.4";
pyproject = true;
src = fetchFromGitHub {
owner = "PetterS";
repo = "quickjs";
tag = version;
hash = "sha256-nLloXJWOuaK/enZfwXJI94IcsAMYrkBtG4i3gmxuhfw=";
};
patches = [ ./0001-Update-for-QuickJS-2025-04-26-release.patch ];
# Upstream uses Git submodules; let's de-vendor and use Nix, so that we gain security fixes like
# https://github.com/NixOS/nixpkgs/pull/407469
prePatch = ''
rmdir upstream-quickjs
ln -s ${srcOnly quickjs} upstream-quickjs
'';
postPatch = ''
substituteInPlace pyproject.toml \
--replace-fail poetry>=1.5.0 poetry \
--replace-fail poetry poetry-core \
--replace-fail 'version = "0"' 'version = "${version}"'
'';
build-system = [
poetry-core
setuptools
];
nativeCheckInputs = [ pytestCheckHook ];
pythonImportsCheck = [ "quickjs" ];
meta = {
description = "Python wrapper around the quickjs C library";
homepage = "https://github.com/PetterS/quickjs";
license = lib.licenses.mit;
maintainers = with lib.maintainers; [ philiptaron ];
};
}

View file

@ -0,0 +1,45 @@
{
lib,
buildPythonPackage,
fetchFromGitHub,
setuptools,
click,
pytestCheckHook,
pyyaml,
pytest-icdiff,
writableTmpDirAsHomeHook,
}:
buildPythonPackage rec {
pname = "symbex";
version = "2.0";
pyproject = true;
src = fetchFromGitHub {
owner = "simonw";
repo = "symbex";
tag = version;
hash = "sha256-swg98z4DpQJ5rq7tdsd3FofbYF7O5S+9ZR0weoM2DoI=";
};
build-system = [ setuptools ];
dependencies = [ click ];
pythonImportsCheck = [ "symbex" ];
nativeCheckInputs = [
pytestCheckHook
pyyaml
pytest-icdiff
writableTmpDirAsHomeHook
];
meta = {
description = "Find the Python code for specified symbols";
homepage = "https://github.com/simonw/symbex";
changelog = "https://github.com/simonw/symbex/releases/tag/${version}/CHANGELOG.md";
license = lib.licenses.asl20;
maintainers = with lib.maintainers; [ philiptaron ];
};
}

View file

@ -3502,8 +3502,6 @@ with pkgs;
ocamlPackages = ocaml-ng.ocamlPackages_4_14;
};
llm = with python3Packages; toPythonApplication llm;
loganalyzer = libsForQt5.callPackage ../development/tools/loganalyzer { };
logstash7 = callPackage ../tools/misc/logstash/7.x.nix {

View file

@ -4971,6 +4971,8 @@ self: super: with self; {
filelock = callPackage ../development/python-modules/filelock { };
files-to-prompt = callPackage ../development/python-modules/files-to-prompt { };
filetype = callPackage ../development/python-modules/filetype { };
filterpy = callPackage ../development/python-modules/filterpy { };
@ -6654,6 +6656,8 @@ self: super: with self; {
icalevents = callPackage ../development/python-modules/icalevents { };
icdiff = callPackage ../development/python-modules/icdiff { };
icecream = callPackage ../development/python-modules/icecream { };
iceportal = callPackage ../development/python-modules/iceportal { };
@ -8306,16 +8310,66 @@ self: super: with self; {
llm-cmd = callPackage ../development/python-modules/llm-cmd { };
llm-command-r = callPackage ../development/python-modules/llm-command-r { };
llm-deepseek = callPackage ../development/python-modules/llm-deepseek { };
llm-docs = callPackage ../development/python-modules/llm-docs { };
llm-echo = callPackage ../development/python-modules/llm-echo { };
llm-fragments-github = callPackage ../development/python-modules/llm-fragments-github { };
llm-fragments-pypi = callPackage ../development/python-modules/llm-fragments-pypi { };
llm-fragments-reader = callPackage ../development/python-modules/llm-fragments-reader { };
llm-fragments-symbex = callPackage ../development/python-modules/llm-fragments-symbex { };
llm-gemini = callPackage ../development/python-modules/llm-gemini { };
llm-gguf = callPackage ../development/python-modules/llm-gguf { };
llm-git = callPackage ../development/python-modules/llm-git { };
llm-grok = callPackage ../development/python-modules/llm-grok { };
llm-groq = callPackage ../development/python-modules/llm-groq { };
llm-hacker-news = callPackage ../development/python-modules/llm-hacker-news { };
llm-jq = callPackage ../development/python-modules/llm-jq { };
llm-llama-server = callPackage ../development/python-modules/llm-llama-server { };
llm-mistral = callPackage ../development/python-modules/llm-mistral { };
llm-ollama = callPackage ../development/python-modules/llm-ollama { };
llm-openai-plugin = callPackage ../development/python-modules/llm-openai-plugin { };
llm-openrouter = callPackage ../development/python-modules/llm-openrouter { };
llm-pdf-to-images = callPackage ../development/python-modules/llm-pdf-to-images { };
llm-sentence-transformers = callPackage ../development/python-modules/llm-sentence-transformers { };
llm-templates-fabric = callPackage ../development/python-modules/llm-templates-fabric { };
llm-templates-github = callPackage ../development/python-modules/llm-templates-github { };
llm-tools-datasette = callPackage ../development/python-modules/llm-tools-datasette { };
llm-tools-quickjs = callPackage ../development/python-modules/llm-tools-quickjs { };
llm-tools-simpleeval = callPackage ../development/python-modules/llm-tools-simpleeval { };
llm-tools-sqlite = callPackage ../development/python-modules/llm-tools-sqlite { };
llm-venice = callPackage ../development/python-modules/llm-venice { };
llm-video-frames = callPackage ../development/python-modules/llm-video-frames { };
llmx = callPackage ../development/python-modules/llmx { };
llvmlite = callPackage ../development/python-modules/llvmlite {
@ -13827,6 +13881,8 @@ self: super: with self; {
pytest-httpx = callPackage ../development/python-modules/pytest-httpx { };
pytest-icdiff = callPackage ../development/python-modules/pytest-icdiff { };
pytest-image-diff = callPackage ../development/python-modules/pytest-image-diff { };
pytest-instafail = callPackage ../development/python-modules/pytest-instafail { };
@ -14876,6 +14932,8 @@ self: super: with self; {
queuelib = callPackage ../development/python-modules/queuelib { };
quickjs = callPackage ../development/python-modules/quickjs { };
quil = callPackage ../development/python-modules/quil { };
quixote = callPackage ../development/python-modules/quixote { };
@ -17033,6 +17091,8 @@ self: super: with self; {
sybil = callPackage ../development/python-modules/sybil { };
symbex = callPackage ../development/python-modules/symbex { };
symbolic = callPackage ../development/python-modules/symbolic { };
symengine = callPackage ../development/python-modules/symengine { inherit (pkgs) symengine; };