llm: customize the message on llm install and llm uninstall with the list of plugins possible

This way, users know what they can specify as far as plugins go. It serves as a plugin directory.
This commit is contained in:
Philip Taron 2025-05-10 14:55:55 -07:00
parent 0d50348b51
commit b06e408d0d
2 changed files with 59 additions and 16 deletions

View file

@ -1,8 +1,8 @@
diff --git a/llm/cli.py b/llm/cli.py
index af37feb..18b078a 100644
--- a/llm/cli.py
+++ b/llm/cli.py
@@ -1014,18 +1014,7 @@ def templates_path():
diff --git i/llm/cli.py w/llm/cli.py
index 09e4e2d..8424a5e 100644
--- i/llm/cli.py
+++ w/llm/cli.py
@@ -2383,18 +2383,18 @@ def display_truncated(text):
)
def install(packages, upgrade, editable, force_reinstall, no_cache_dir):
"""Install packages from PyPI into the same environment as LLM"""
@ -18,17 +18,39 @@ index af37feb..18b078a 100644
- 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.")
+ click.echo(
+"""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):
@@ -2402,8 +2402,18 @@ def install(packages, upgrade, editable, force_reinstall, no_cache_dir):
@click.option("-y", "--yes", is_flag=True, help="Don't ask for confirmation")
def uninstall(packages, yes):
"""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.")
+ click.echo(
+"""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()

View file

@ -6,6 +6,7 @@
fetchFromGitHub,
pytestCheckHook,
pythonOlder,
replaceVars,
setuptools,
click-default-group,
condense-json,
@ -25,12 +26,10 @@
sqlite-utils,
}:
let
# 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>
withPluginsArgNames = lib.functionArgs withPlugins;
/**
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
@ -81,6 +80,7 @@ let
llm-templates-github ? false,
llm-venice ? false,
llm-video-frames ? false,
...
}@args:
let
# Filter to just the attributes which are set to a true value.
@ -97,9 +97,9 @@ let
ps:
let
# Throw a diagnostic if this list gets out of sync with the names in python3Packages
allPluginsPresent = pluginNames == (lib.attrNames withPluginsArgNames);
pluginNames = lib.attrNames (lib.intersectAttrs ps withPluginsArgNames);
missingNamesList = lib.attrNames (lib.removeAttrs withPluginsArgNames pluginNames);
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.
@ -120,7 +120,24 @@ let
'';
# Uses the `withPlugins` names to make a Python environment with everything.
withAllPlugins = withPlugins (lib.genAttrs (lib.attrNames withPluginsArgNames) (name: true));
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";
@ -140,6 +157,10 @@ let
patches = [ ./001-disable-install-uninstall-commands.patch ];
postPatch = ''
substituteInPlace llm/cli.py --replace-fail "@listOfPackagedPlugins@" "$(< ${listOfPackagedPlugins})"
'';
dependencies = [
click-default-group
condense-json