diff --git a/flake.lock b/flake.lock index 2e7dbfa..7f0c7e4 100644 --- a/flake.lock +++ b/flake.lock @@ -249,11 +249,11 @@ "treefmt-nix": "treefmt-nix" }, "locked": { - "lastModified": 1779687822, - "narHash": "sha256-WXKyZkAQqCXm+k+N5hIfnb7U67RD3S9eIwbOCiR3vCk=", + "lastModified": 1781849779, + "narHash": "sha256-Ihdla0v+oCO6dNN6iExgdGc9+JmKLmAnbiTneiJgZbE=", "owner": "numtide", "repo": "llm-agents.nix", - "rev": "ce517fef69b04f27e24dc1278f02c00ac7860f36", + "rev": "a1e67cc315b6bd924614d4232e09bab54df3ae39", "type": "github" }, "original": { @@ -355,11 +355,11 @@ }, "nixpkgs_2": { "locked": { - "lastModified": 1778869304, - "narHash": "sha256-30sZNZoA1cqF5JNO9fVX+wgiQYjB7HJqqJ4ztCDeBZE=", + "lastModified": 1781607440, + "narHash": "sha256-rxO+uc/KFbSJp+pgyXRuAX6QlG9hJdnt0BXpEQRXY+U=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "d233902339c02a9c334e7e593de68855ad26c4cb", + "rev": "3e41b24abd260e8f71dbe2f5737d24122f972158", "type": "github" }, "original": { @@ -493,11 +493,11 @@ ] }, "locked": { - "lastModified": 1775636079, - "narHash": "sha256-pc20NRoMdiar8oPQceQT47UUZMBTiMdUuWrYu2obUP0=", + "lastModified": 1780220602, + "narHash": "sha256-eynAfOmbmxJnkp7YewvCEbShNnnYJ9gLLqkzsYtBPeM=", "owner": "numtide", "repo": "treefmt-nix", - "rev": "790751ff7fd3801feeaf96d7dc416a8d581265ba", + "rev": "db947814a175b7ca6ded66e21383d938df01c227", "type": "github" }, "original": { diff --git a/modules/home/devtools/ai-tools.nix b/modules/home/devtools/ai-tools.nix index cc6a494..4ccac68 100644 --- a/modules/home/devtools/ai-tools.nix +++ b/modules/home/devtools/ai-tools.nix @@ -3,6 +3,7 @@ lib, pkgs, inputs, + customPkgs, ... }: let @@ -173,6 +174,24 @@ in description = "Configuration for the Claude wrapper that targets the Kimi Code API."; }; + piInstructions = mkOption { + type = types.submodule { + options = { + enable = mkEnableOption "Install the global pi AGENTS.md instructions file."; + source = mkOption { + type = types.path; + default = ../../../pi/AGENTS.md; + description = "Source file for global pi instructions."; + }; + }; + }; + default = { + enable = true; + source = ../../../pi/AGENTS.md; + }; + description = "Configuration for the global pi instructions file deployment."; + }; + piExtensions = mkOption { type = types.submodule { options = { @@ -266,7 +285,34 @@ in ++ kimiWrapperPackages ++ cfg.extraPackages; + home.activation.installPiFff = lib.hm.dag.entryAfter [ "writeBoundary" ] '' + if [ -x ${lib.getExe llmPkgs.pi} ]; then + export PI_SKIP_VERSION_CHECK=1 + export PI_TELEMETRY=0 + export PATH=${pkgs.nodejs}/bin:${pkgs.git}/bin:$PATH + + settings_file="$HOME/.pi/agent/settings.json" + mkdir -p "$(dirname "$settings_file")" + ${pkgs.nodejs}/bin/node -e "const fs=require('fs'); const path=process.env.HOME+'/.pi/agent/settings.json'; let settings={}; if (fs.existsSync(path)) settings=JSON.parse(fs.readFileSync(path,'utf8')); settings.theme='dark'; fs.writeFileSync(path, JSON.stringify(settings, null, 2)+String.fromCharCode(10));" + + ${lib.getExe llmPkgs.pi} list | ${pkgs.gnugrep}/bin/grep -q '@ff-labs/pi-fff' || \ + ${lib.getExe llmPkgs.pi} install npm:@ff-labs/pi-fff@0.9.4 + ${lib.getExe llmPkgs.pi} list | ${pkgs.gnugrep}/bin/grep -q '@juicesharp/rpiv-ask-user-question' || \ + ${lib.getExe llmPkgs.pi} install npm:@juicesharp/rpiv-ask-user-question@1.20.0 + fi + ''; + home.file = mkMerge [ + { + ".pi/agent/models.json" = { + source = ../../../pi/models.json; + }; + } + (mkIf cfg.piInstructions.enable { + ".pi/agent/AGENTS.md" = { + source = cfg.piInstructions.source; + }; + }) (mkIf cfg.piExtensions.enable { ".pi/agent/extensions" = { source = cfg.piExtensions.source; diff --git a/pi/AGENTS.md b/pi/AGENTS.md new file mode 100644 index 0000000..355a6c8 --- /dev/null +++ b/pi/AGENTS.md @@ -0,0 +1,14 @@ +# Global Pi Instructions + +## Version Control + +Prefer Jujutsu (`jj`) over Git for source-control operations. + +- Use `jj status` instead of `git status`. +- Use `jj diff` instead of `git diff`. +- Use `jj log` instead of `git log`. +- Use `jj describe` for change descriptions. +- Use `jj new`, `jj split`, and `jj squash` for change management. +- Avoid `git add`, `git commit`, and direct index/staging workflows unless explicitly requested. +- Git commands are acceptable only for operations that `jj` cannot perform or when the user asks for Git specifically. +- When reporting changes, mention the active `jj` change/workspace state rather than Git staging state. diff --git a/pi/models.json b/pi/models.json new file mode 100644 index 0000000..75816e7 --- /dev/null +++ b/pi/models.json @@ -0,0 +1,29 @@ +{ + "providers": { + "crofai": { + "baseUrl": "https://crof.ai/v1", + "api": "openai-completions", + "apiKey": "$CROF_API_KEY", + "authHeader": true, + "compat": { + "supportsDeveloperRole": false, + "supportsStore": false + }, + "models": [ + { + "id": "glm-5.2", + "name": "CrofAI GLM 5.2", + "reasoning": true, + "contextWindow": 1000000, + "maxTokens": 131072, + "cost": { + "input": 0.5, + "output": 2.2, + "cacheRead": 0.08, + "cacheWrite": 0 + } + } + ] + } + } +} diff --git a/secrets/global-env.sops.yaml b/secrets/global-env.sops.yaml index dbbf15a..a55c884 100644 --- a/secrets/global-env.sops.yaml +++ b/secrets/global-env.sops.yaml @@ -10,6 +10,7 @@ ANTHROPIC_API_KEY: ENC[AES256_GCM,data:aBgfgHQ8cyJ4TUq4O6y218flTgDWcAXatY0/xbaD3 OPENCODE_API_KEY: ENC[AES256_GCM,data:2aPaiODhpFObObRN+/HiEVsvMds1n6MhrmvQUWo2ozRzgRHQ1dGGZYFzOZoSbV4vpjmiqKW7VUFnVU5va1xlS8HrWg==,iv:DgCF9I+wT9xUjmenfUSDrDnKD5Ai4pJGw4qKmePpZOo=,tag:YD7nO4HbDKTa3zNbGtUCOg==,type:str] BRAVE_SEARCH_API_KEY: ENC[AES256_GCM,data:7Q+8sa2Xp4amEMkGzgEZzSLDCkstL71lu3sz1iGJdg==,iv:pY4NMgIUEEqwBUonAOAVoqP0EeqgON7h23221Yoa4aM=,tag:foyjDNIMsxrKvgYmu6FJNA==,type:str] KIMI_API_KEY: ENC[AES256_GCM,data:hkq/IY++1xGPmFMt5UMFlA/mVCOKDh+4V1Ip6Bv5ZSWTwdqwP1ghuL3HpF/r4Y+eO+PfzcZso1A8z+4SqVlXBjmiaORHIPut,iv:UWcdLW+ITk8jtc/UbprKz8zxI3mgAn1DP+tch0tse8M=,tag:brx5KyUzl1wg+fTagMUphQ==,type:str] +CROF_API_KEY: ENC[AES256_GCM,data:rCBZ3uDitVs6EVs9AOWGT7UZf0x6vQ4EU4fnyw==,iv:XwUxXgDxku8aAxMIMdxrVImhjNuuh+6kXoBo5RULhsc=,tag:WlIglF9cMOR33x4JbEmpnA==,type:str] sops: age: - recipient: age1qfgey5w87dresg99zed3d2yz62hv6c2c7u4gd5e880vjrngmx9ksgfv3sj @@ -21,7 +22,7 @@ sops: WHRrVWx2Y3FabWpBdjZ5VkpFY1BGeGsKSc4vxaHSj/6g7clPZDOPqCf3Zo+VGSRy HwLiHEohjk5/R3I5KWhFuO9aNQTNYYnUBwc6nOAcEhw+Mihq2gDtzg== -----END AGE ENCRYPTED FILE----- - lastmodified: "2026-02-03T07:35:18Z" - mac: ENC[AES256_GCM,data:MWrijOPL9whg++YKwmLWT1hFu98FIDuZgis7g77mXFCIPMHn2Lz9JV5wdkUJY4ZNAlFG/FwZDG2QZQDp3aD+syN0UGVdmJmRsNcn7JITyABvXWWwJIo3kyBJj5mJMpcFooJEZpTsNp4hYr4ozrBl8/v1QyIcnY7L5NeO5DdyaXw=,iv:dCoCan6mOwDDD3dpvdFJkUzNfOttVJo3hb6vLBWap68=,tag:dWGz6szFXp+IW8QgI7z2CA==,type:str] + lastmodified: "2026-06-19T08:19:30Z" + mac: ENC[AES256_GCM,data:FZ1W7dNanlxvkgn5Up3JzIQHyeXM+bAeEmBe3gd5+RlXMAOnUu2QvM5L5mHCbLGNmAefbGKYF9v5UDBk14SkgyL1lcDKaI/rgZ9cpc+fV+aHCK6y15zsA+Tyk17V21Kr0E3d23ZT87j7dLKVF9T50Mpd/xRSHsRilBZAQqM0oBE=,iv:aSW3Iv8cd+QaM+U9HI74QCgDU1ilTqCD8//GO2/jj5E=,tag:xqzpeYGO/m6ZRJFCkTPmSg==,type:str] unencrypted_suffix: _unencrypted version: 3.11.0