···
···
···
+
# 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.
+
See `lib.attrNames (lib.functionArgs llm.withPlugins)` for the total list of plugins supported.
+
## `llm.withPlugins` usage example
+
llm.withPlugins { llm-gemini = true; llm-groq = true; }
+
=> «derivation /nix/store/<hash>-python3-3.12.10-llm-with-llm-gemini-llm-groq.drv»
+
# Keep this list up to date with the plugins in python3Packages!
+
llm-fragments-github ? false,
+
llm-fragments-pypi ? false,
+
llm-hacker-news ? false,
+
llm-openai-plugin ? false,
+
llm-openrouter ? false,
+
llm-sentence-transformers ? false,
+
llm-templates-fabric ? false,
+
llm-templates-github ? false,
+
llm-video-frames ? false,
+
# Filter to just the attributes which are set to a true value.
+
setArgs = lib.filterAttrs (name: lib.id) args;
+
# Make a string with those names separated with a dash.
+
setArgsStr = lib.concatStringsSep "-" (lib.attrNames setArgs);
+
# Make the derivation name reflect what's inside it.
+
drvName = if lib.stringLength setArgsStr == 0 then "llm" else "llm-with-${setArgsStr}";
+
# Make a python environment with just those plugins.
+
python-environment = python.withPackages (
+
# 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);
+
missingNames = lib.concatStringsSep ", " missingNamesList;
+
# The relevant plugins are the ones the user asked for.
+
plugins = lib.intersectAttrs setArgs ps;
+
assert lib.assertMsg allPluginsPresent "Missing these plugins: ${missingNames}";
+
([ ps.llm ] ++ lib.attrValues plugins)
+
# 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
+
runCommand "${python.name}-${drvName}" { inherit (llm) passthru meta; } ''
+
ln -s ${python-environment}/bin/llm $out/bin/llm
+
# Uses the `withPlugins` names to make a Python environment with everything.
+
withAllPlugins = withPlugins (lib.genAttrs (lib.attrNames withPluginsArgNames) (name: true));
llm = buildPythonPackage rec {
···
pythonImportsCheck = [ "llm" ];
+
inherit withPlugins withAllPlugins;
${plugin.pname} = callPackage ./mk-plugin-test.nix { inherit llm plugin; };
···