This repository has no description
0

Configure Feed

Select the types of activity you want to include in your feed.

superconfig / wrapperModules / pi / flake-module.nix
6.4 kB 170 lines
1{ self, ... }: 2{ 3 flake.wrapperModules.pi = 4 { 5 config, 6 lib, 7 ... 8 }: 9 let 10 pkgs = config.pkgs; 11 12 # Extract npm packages with hashes from settings.packages 13 npmPackages = lib.filter (p: builtins.isAttrs p && p ? hash) (config.settings.packages or [ ]); 14 15 # Fetch an npm tarball and unpack it into lib/node_modules/<name> 16 fetchPlugin = 17 pkg: 18 let 19 source = pkg.source or pkg; 20 name = lib.removePrefix "npm:" source; 21 tarball = pkgs.fetchurl { 22 url = "https://registry.npmjs.org/${name}/-/${name}-${pkg.version}.tgz"; 23 hash = pkg.hash; 24 }; 25 deps = map fetchPlugin (pkg.deps or [ ]); 26 in 27 pkgs.runCommand "pi-plugin-${name}" 28 { 29 nativeBuildInputs = [ 30 pkgs.gnutar 31 pkgs.gzip 32 ]; 33 } 34 '' 35 mkdir -p $out/lib/node_modules/${name} 36 tar xzf ${tarball} --strip-components=1 -C $out/lib/node_modules/${name} 37 ${lib.concatMapStringsSep "\n" ( 38 dep: 39 "mkdir -p $out/lib/node_modules/${name}/node_modules" 40 + "\ncp -a ${dep}/lib/node_modules/* $out/lib/node_modules/${name}/node_modules/" 41 + "\ncp -a ${dep}/lib/node_modules/* $out/lib/node_modules/" 42 ) deps} 43 ''; 44 45 fetchedPlugins = map fetchPlugin npmPackages; 46 47 # Strip hash and null-valued attrs from package entries before writing settings.json 48 cleanPackage = 49 p: 50 if builtins.isAttrs p then 51 let 52 cleaned = lib.filterAttrs (k: v: k != "hash" && k != "version" && k != "deps" && v != null) p; 53 # Embed version into source spec so pi treats it as pinned (e.g. npm:pi-hooks@1.0.3) 54 withVersion = 55 if p ? version && p ? source && !(lib.hasInfix "@" (lib.removePrefix "npm:" p.source)) then 56 cleaned // { source = "${p.source}@${p.version}"; } 57 else 58 cleaned; 59 in 60 withVersion 61 else 62 p; 63 64 cleanSettings = config.settings // { 65 packages = map cleanPackage (config.settings.packages or [ ]); 66 }; 67 68 settingsFile = pkgs.writeText "pi-settings.json" (builtins.toJSON cleanSettings); 69 in 70 { 71 _class = "wrapper"; 72 73 options = { 74 settings = lib.mkOption { 75 type = lib.types.submodule { 76 freeformType = (pkgs.formats.json { }).type; 77 options.packages = lib.mkOption { 78 type = lib.types.listOf ( 79 lib.types.either lib.types.str ( 80 lib.types.submodule { 81 freeformType = (pkgs.formats.json { }).type; 82 options.hash = lib.mkOption { 83 type = lib.types.str; 84 description = "Fixed-output hash for fetching this npm package."; 85 }; 86 options.source = lib.mkOption { 87 type = lib.types.str; 88 description = "Package source (e.g. npm:package-name)."; 89 }; 90 options.version = lib.mkOption { 91 type = lib.types.str; 92 description = "Exact version to pin (e.g. 1.0.3). Ensures reproducible fetching."; 93 }; 94 options.deps = lib.mkOption { 95 type = lib.types.listOf (lib.types.attrsOf lib.types.anything); 96 default = [ ]; 97 description = "Transitive npm dependencies as {source, version, hash} attrsets."; 98 }; 99 options.extensions = lib.mkOption { 100 type = lib.types.nullOr (lib.types.listOf lib.types.str); 101 default = null; 102 description = '' 103 Extension filter patterns following pi's native syntax. 104 When null (default), all extensions from the package are loaded. 105 An empty list explicitly disables all extensions. 106 Patterns use prefixes to control inclusion: 107 - `"!pattern"` — exclude matching extensions 108 - `"+pattern"` — force-include (overrides excludes) 109 - `"-pattern"` — force-exclude (overrides includes) 110 - `"path"` — plain path to include 111 ''; 112 example = [ 113 "!./extensions/resistance.ts" 114 ]; 115 }; 116 } 117 ) 118 ); 119 default = [ ]; 120 description = "Pi packages list. Object entries may include a `hash` for Nix fetching."; 121 }; 122 }; 123 default = { }; 124 description = "Pi settings.json content."; 125 }; 126 127 pluginOverrides = lib.mkOption { 128 type = lib.types.str; 129 default = ""; 130 description = '' 131 Shell commands to run after assembling the plugin prefix. 132 The variable `$out` points to the mutable copy. 133 ''; 134 }; 135 136 pluginPrefix = lib.mkOption { 137 type = lib.types.package; 138 description = "The final npm prefix with all plugins merged and overrides applied."; 139 default = pkgs.runCommand "pi-plugins" { } '' 140 mkdir -p $out 141 ${lib.concatMapStringsSep "\n" (p: "cp -a --no-preserve=mode ${p}/* $out/") fetchedPlugins} 142 ${lib.optionalString (config.pluginOverrides != "") config.pluginOverrides} 143 ''; 144 }; 145 }; 146 147 config.package = lib.mkDefault ( 148 self.legacyPackages.${pkgs.system}.llm.pi.overrideAttrs (old: { 149 postInstall = (old.postInstall or "") + '' 150 patch $out/lib/node_modules/@mariozechner/pi-coding-agent/dist/core/settings-manager.js \ 151 ${./settings-env.patch} 152 ''; 153 }) 154 ); 155 156 config.extraPackages = [ pkgs.nodejs ]; 157 158 config.env.npm_config_prefix = "${config.pluginPrefix}"; 159 config.env.PI_SETTINGS_FILE = "${settingsFile}"; 160 161 config.meta.maintainers = [ 162 { 163 name = "lassulus"; 164 github = "lassulus"; 165 githubId = 621375; 166 } 167 ]; 168 config.meta.platforms = lib.platforms.all; 169 }; 170}