From 19e97d589e4ad5fcd8f68799afd9969aa3c85e16 Mon Sep 17 00:00:00 2001 From: Alexandre Date: Sun, 28 Dec 2025 00:08:05 +0100 Subject: [PATCH] Made a AI centric zed module --- hosts/common/home.nix | 32 ++- modules/common/ai.nix | 6 +- modules/common/zed.nix | 554 +++++++++++++++++++++++++++++++++++++++++ secrets/secrets.yaml | 37 +-- 4 files changed, 598 insertions(+), 31 deletions(-) create mode 100644 modules/common/zed.nix diff --git a/hosts/common/home.nix b/hosts/common/home.nix index 5984514..ae298b7 100644 --- a/hosts/common/home.nix +++ b/hosts/common/home.nix @@ -9,9 +9,27 @@ imports = [ inputs.spicetify-nix.homeManagerModules.spicetify ../../modules/home-manager/spicetify.nix - ../../modules/home-manager/zed.nix + ../../modules/common/zed.nix ]; + programs = { + # Git config + git = { + enable = true; + settings = { + user = { + email = "mateialex@outlook.fr"; + name = "Alexandre"; + }; + }; + }; + # Zed config + zed-ai = { + enable = true; + }; + }; + + # Common Packages home.packages = with pkgs; [ # CLI @@ -45,6 +63,7 @@ # JavaScript nodejs # The main interpreter pnpm # To replace npm + nodejs_22 # C/C++ clang-tools # The main compiler @@ -56,14 +75,5 @@ #pip # The package manager ]; - # Git config - programs.git = { - enable = true; - settings = { - user = { - email = "mateialex@outlook.fr"; - name = "Alexandre"; - }; - }; - }; + } diff --git a/modules/common/ai.nix b/modules/common/ai.nix index e56d747..d5918bb 100644 --- a/modules/common/ai.nix +++ b/modules/common/ai.nix @@ -1,9 +1,9 @@ { pkgs, lib, config, ... }: let - + hasNvidiaGpu = config.hardware.nvidia.package or null != null; - + gpu = if hasNvidiaGpu then pkgs.ollama-cuda @@ -20,7 +20,7 @@ in services = { ollama = { enable = true; - loadModels = [ "codegemma:7b-instruct" "codegemma:7b-code" "codegemma:2b" "starcoder2:7b" ]; + loadModels = [ "codegemma:7b-instruct" "codegemma:7b-code" "codegemma:2b" "starcoder2:7b" "deepseek-r1:14b" "deepseek-r1:8b" ]; package = gpu; }; }; diff --git a/modules/common/zed.nix b/modules/common/zed.nix new file mode 100644 index 0000000..24be2ae --- /dev/null +++ b/modules/common/zed.nix @@ -0,0 +1,554 @@ +{ config, lib, pkgs, ... }: + +let + cfg = config.programs.zed-ai; + + # Zed configuration + zedSettings = { + # Ollama AI config + language_models = { + ollama = { + api_url = "http://localhost:11434"; + # List available models + + available_models = [ + # AIs with native CoT + { + name = "deepseek-r1:8b"; + display_name = "DeepSeek-R1 8B (CoT Native)"; + max_tokens = 64000; + supports_tools = true; + supports_thinking = true; + supports_images = false; + } + { + name = "deepseek-r1:14b"; + display_name = "DeepSeek-R1 14B (CoT Native)"; + max_tokens = 64000; + supports_tools = true; + supports_thinking = true; + supports_images = false; + } + { + name = "deepseek-coder-v2:16b"; + display_name = "Deepseek Coder V2 16B"; + max_tokens = 160000; + supports_tools = false; + supports_thinking = false; + supports_images = false; + } + { + name = "starcoder2:7b"; + display_name = "StarCoder2 7B"; + max_tokens = 16384; + supports_tools = false; + supports_thinking = false; + supports_images = false; + } + { + name = "codegemma:7b-instruct"; + display_name = "CodeGemma 7B Instruct"; + max_tokens = 8192; + supports_tools = true; + supports_thinking = false; + supports_images = false; + } + { + name = "codegemma:2b"; + display_name = "CodeGemma 2B (Fast)"; + max_tokens = 8192; + supports_tools = false; + supports_thinking = false; + supports_images = false; + } + ]; + }; + }; + + # Inline autocompletion + # Small and fast AI model + inline_completions = { + provider = "ollama"; + ollama = { + model = "codegemma:2b"; + api_url = "http://localhost:11434"; + low_speed_timeout_in_seconds = 30; + timeout_in_seconds = 5; + }; + }; + + show_edit_predictions = false; + edit_predictions = { + mode = "subtle"; + enabled_in_text_threads = false; + }; + + agent = { + default_profile = "reasoning"; + play_sound_when_agent_done = true; + dock = "right"; + default_model = { + provider = "ollama"; + model = "deepseek-r1:14b"; + }; + + profiles = { + reasoning = { + name = "Deep Reasoning (CoT)"; + tools = { + copy_path = true; + create_directory = true; + delete_path = true; + diagnostics = true; + edit_file = true; + fetch = true; + list_directory = true; + move_path = true; + now = true; + find_path = true; + read_file = true; + grep = true; + terminal = true; + thinking = true; + web_search = true; + project_notifications = false; + }; + enable_all_context_servers = true; + context_servers = {}; + system_prompt = '' + You are an expert programming assistant. When solving complex problems: + 1. Break down the problem into smaller steps + 2. Think through each step carefully before providing code + 3. Consider edge cases and potential issues + 4. Explain your reasoning process + + For debugging tasks, trace through the code logic step by step. + For architecture decisions, evaluate multiple approaches before recommending one. + For optimization problems, analyze the time and space complexity at each step. + ''; + }; + + fast = { + name = "Fast Development"; + tools = { + copy_path = true; + create_directory = true; + delete_path = true; + diagnostics = true; + edit_file = true; + fetch = true; + list_directory = true; + move_path = true; + now = true; + find_path = true; + read_file = true; + grep = true; + terminal = true; + thinking = false; + web_search = true; + project_notifications = false; + }; + enable_all_context_servers = true; + context_servers = {}; + # Uses a faster model + default_model = { + provider = "ollama"; + model = "codegemma:7b-instruct"; + }; + system_prompt = '' + You are a fast and efficient programming assistant. + Provide clear, concise solutions while still being thorough. + Think through the problem but focus on delivering results quickly. + ''; + }; + + debug = { + name = "Debug & Analysis"; + tools = { + copy_path = true; + create_directory = true; + delete_path = true; + diagnostics = true; + edit_file = true; + fetch = true; + list_directory = true; + move_path = true; + now = true; + find_path = true; + read_file = true; + grep = true; + terminal = true; + thinking = true; + web_search = true; + project_notifications = true; + }; + enable_all_context_servers = true; + context_servers = {}; + default_model = { + provider = "ollama"; + model = "deepseek-r1:14b"; + }; + system_prompt = '' + You are a meticulous debugging assistant. When analyzing bugs: + 1. First, understand what the code is supposed to do + 2. Trace through the execution flow step by step + 3. Identify where the actual behavior diverges from expected behavior + 4. Explain why the bug occurs + 5. Propose a fix with explanation + + Show your complete reasoning process. Consider multiple hypotheses. + Use the diagnostic tools to gather information systematically. + ''; + }; + + learning = { + name = "Learning & Teaching"; + tools = { + copy_path = true; + diagnostics = true; + list_directory = true; + find_path = true; + read_file = true; + grep = true; + now = true; + thinking = true; + fetch = true; + web_search = true; + create_directory = false; + delete_path = false; + edit_file = false; + move_path = false; + terminal = false; + project_notifications = false; + }; + enable_all_context_servers = true; + context_servers = {}; + default_model = { + provider = "ollama"; + model = "deepseek-r1:14b"; + }; + system_prompt = '' + You are a patient and thorough programming teacher. When explaining concepts: + 1. Start with the fundamentals and build up gradually + 2. Use concrete examples and analogies + 3. Show your reasoning process step by step + 4. Anticipate common points of confusion + 5. Encourage understanding over memorization + + Break down complex topics into digestible parts. + Relate new concepts to things the student already knows. + Ask guiding questions to promote active learning. + ''; + }; + + read = { + name = "Read & Explore"; + tools = { + copy_path = true; + diagnostics = true; + list_directory = true; + find_path = true; + read_file = true; + grep = true; + now = true; + thinking = false; + fetch = false; + web_search = false; + create_directory = false; + delete_path = false; + edit_file = false; + move_path = false; + terminal = false; + project_notifications = false; + }; + enable_all_context_servers = true; + context_servers = {}; + default_model = { + provider = "ollama"; + model = "codegemma:7b-instruct"; + }; + system_prompt = '' + You are a helpful code reading assistant. + Provide clear, concise explanations of code structure and behavior. + ''; + }; + }; + }; + + # UI + ui_font_size = 16; + buffer_font_size = 16; + theme = "Dracula"; + icon_theme = "Material Icon Theme"; + + # Discord Presence config + lsp = { + discord_presence = { + initialization_options = { + application_id = "1263505205522337886"; + base_icons_url = "https://raw.githubusercontent.com/xhyrom/zed-discord-presence/main/assets/icons/"; + state = "Working on {filename}"; + details = "In {workspace}"; + large_image = "{base_icons_url}/{language}.png"; + large_text = "{language:u}"; + small_image = "{base_icons_url}/zed.png"; + small_text = "Zed"; + idle = { + timeout = 600; + action = "clear_activity"; + state = "Idling"; + details = "In Zed"; + large_image = "{base_icons_url}/zed.png"; + large_text = "Zed"; + small_image = "{base_icons_url}/idle.png"; + small_text = "Idle"; + }; + rules = { + mode = "blacklist"; + paths = []; + }; + git_integration = true; + }; + }; + }; + + auto_install_extensions = { + # System Languages + rust = true; + nix = true; + + # Web Dev language + html = true; + css = true; + javascript = true; + typescript = true; + + # Backend languages + go = true; + python = true; + + # Data Format + json = true; + yaml = true; + toml = true; + + # Documentation + markdown = true; + }; + + # Autocomplete with Ollama + features = { + inline_completion_provider = "ollama"; + edit_prediction_provider = "none"; + }; + }; + +in +{ + options.programs.zed-ai = { + enable = lib.mkEnableOption { + type = lib.types.bool; + default = false; + description = "Zed AI configuration with Chain of Thought"; + }; + + enableCoTModels = lib.mkOption { + type = lib.types.bool; + default = true; + description = '' + Automatically download and configure Chain of Thought capable models. + This will add DeepSeek-R1 models to your Ollama installation. + ''; + }; + + mcpServers = lib.mkOption { + type = lib.types.attrs; + default = {}; + description = "MCP servers config"; + }; + + githubToken = lib.mkOption { + type = lib.types.nullOr lib.types.str; + default = null; + description = "Github token for the MCP"; + }; + + braveSearchApiKey = lib.mkOption { + type = lib.types.nullOr lib.types.str; + default = null; + description = "Brave Search API key"; + }; + }; + + config = lib.mkIf cfg.enable { + # Secrets management with Sops-nix + sops.secrets = lib.mkIf (cfg.githubToken != null || cfg.braveSearchApiKey != null) { + "zed/github_token" = lib.mkIf (cfg.githubToken != null) { + sopsFile = ../../secrets/secrets.yaml; + owner = config.home.username or "alex"; + }; + "zed/brave_api_key" = lib.mkIf (cfg.braveSearchApiKey != null) { + sopsFile = ../../secrets/secrets.yaml; + owner = config.home.username or "alex"; + }; + }; + + # Configure default MCP servers + programs.zed-ai.mcpServers = lib.mkDefault { + filesystem = { + command = "npx"; + args = [ + "-y" + "@modelcontextprotocol/server-filesystem" + "${config.home.homeDirectory}/Developer" + ]; + }; + + github = lib.mkIf (cfg.githubToken != null) { + command = "npx"; + args = [ + "-y" + "@modelcontextprotocol/server-github" + ]; + env = { + GITHUB_PERSONAL_ACCESS_TOKEN = "$(cat ${config.sops.secrets."zed/github_token".path})"; + }; + }; + + git = { + command = "npx"; + args = [ + "-y" + "@modelcontextprotocol/server-git" + ]; + }; + + brave-search = lib.mkIf (cfg.braveSearchApiKey != null) { + command = "npx"; + args = [ + "-y" + "@modelcontextprotocol/server-brave-search" + ]; + env = { + BRAVE_API_KEY = "$(cat ${config.sops.secrets."zed/brave_api_key".path})"; + }; + }; + }; + + # Generate Zed config + home.file.".config/zed/settings.json" = { + text = builtins.toJSON (zedSettings // { + agent = zedSettings.agent // { + profiles = lib.mapAttrs (name: profile: + profile // { + context_servers = cfg.mcpServers; + } + ) zedSettings.agent.profiles; + }; + }); + }; + + # Helper Scripts + home.packages = [ + # Main test script + (pkgs.writeShellScriptBin "zed-ai-test" '' + echo "🔍 Testing Zed AI Configuration with Chain of Thought..." + echo "" + + echo "Checking Ollama service..." + if ${pkgs.curl}/bin/curl -s http://localhost:11434/api/tags > /dev/null 2>&1; then + echo "✅ Ollama is running" + echo "" + echo "Available models:" + ${pkgs.curl}/bin/curl -s http://localhost:11434/api/tags | ${pkgs.jq}/bin/jq -r '.models[].name' | sort + echo "" + + echo "Chain of Thought models:" + ${pkgs.curl}/bin/curl -s http://localhost:11434/api/tags | ${pkgs.jq}/bin/jq -r '.models[].name' | grep -E "deepseek-r1" || echo " No CoT models found. Run 'ollama pull deepseek-r1:14b'" + else + echo "❌ Ollama is not running" + fi + + echo "" + echo "Checking Zed configuration..." + if [ -f ~/.config/zed/settings.json ]; then + echo "✅ Zed configuration exists" + echo "" + echo "Configured CoT-capable models:" + ${pkgs.jq}/bin/jq -r '.language_models.ollama.available_models[] | select(.supports_thinking == true) | " - \(.name) (\(.display_name))"' ~/.config/zed/settings.json + echo "" + echo "Agent profiles:" + ${pkgs.jq}/bin/jq -r '.agent.profiles | keys[]' ~/.config/zed/settings.json | sed 's/^/ - /' + else + echo "❌ Zed configuration not found" + fi + + echo "" + echo "💡 Tips:" + echo " - Use 'reasoning' profile for complex problems with visible thinking" + echo " - Use 'debug' profile for detailed bug analysis" + echo " - Use 'learning' profile when learning new concepts" + echo " - Use 'fast' profile for quick coding without visible CoT" + echo "" + echo " To switch profiles in Zed: Open settings (Cmd+,) and search for 'agent profile'" + '') + + # Sript to directly test CoT + (pkgs.writeShellScriptBin "test-cot" '' + #!/usr/bin/env bash + + MODEL="''${1:-deepseek-r1:14b}" + PROMPT="''${2:-Explain step by step how to implement a binary search tree in Rust}" + + echo "🧠 Testing Chain of Thought with model: $MODEL" + echo "📝 Prompt: $PROMPT" + echo "" + echo "Generating response with thinking process..." + echo "==================================================" + + ${pkgs.curl}/bin/curl -s http://localhost:11434/api/generate -d "{ + \"model\": \"$MODEL\", + \"prompt\": \"$PROMPT\", + \"stream\": false + }" | ${pkgs.jq}/bin/jq -r '.response' + + echo "" + echo "==================================================" + echo "" + echo "💡 Try other models:" + echo " test-cot deepseek-r1:8b 'your question'" + echo " test-cot codegemma:7b-instruct 'your question'" + '') + + # Script to compare CoT responses + (pkgs.writeShellScriptBin "compare-cot" '' + #!/usr/bin/env bash + PROMPT="''${1:-Write a function to find the longest palindromic substring}" + + echo "🔬 Comparing responses with and without Chain of Thought" + echo "📝 Prompt: $PROMPT" + echo "" + + echo "1️⃣ Response WITHOUT explicit CoT (codegemma:7b-instruct):" + echo "==================================================" + ${pkgs.curl}/bin/curl -s http://localhost:11434/api/generate -d "{ + \"model\": \"codegemma:7b-instruct\", + \"prompt\": \"$PROMPT\", + \"stream\": false + }" | ${pkgs.jq}/bin/jq -r '.response' + + echo "" + echo "2️⃣ Response WITH Chain of Thought (deepseek-r1:14b):" + echo "==================================================" + ${pkgs.curl}/bin/curl -s http://localhost:11434/api/generate -d "{ + \"model\": \"deepseek-r1:14b\", + \"prompt\": \"Think through this step by step. $PROMPT\", + \"stream\": false + }" | ${pkgs.jq}/bin/jq -r '.response' + + echo "" + echo "💡 Notice how the CoT model shows its reasoning process" + '') + ]; + }; +} diff --git a/secrets/secrets.yaml b/secrets/secrets.yaml index 0b16bee..fb368dd 100644 --- a/secrets/secrets.yaml +++ b/secrets/secrets.yaml @@ -2,22 +2,25 @@ hello: ENC[AES256_GCM,data:iUTvN5BcSq9z1rm8A9IGi/bC6Y9ktTb0ZJHVnT2FDxX18LBVw9fPJ example-key: ENC[AES256_GCM,data:b2Gx6CGtub7rAnd/kw==,iv:uWJTovo9X/VkXUW7HRfSuQfo2wZ7yjShfUeRghEQcW0=,tag:R0T8tbijxfAUu19wN9iQdw==,type:str] #ENC[AES256_GCM,data:igl42zvcTfvOnZ5eKnWHpw==,iv:ImJmyaweKF5ADkwTarcVGaKb3zb2ycXPzq0KItU64+k=,tag:ydg9C6ZO47QsLoguq60JCg==,type:comment] wireless: - freebox-password: ENC[AES256_GCM,data:2g9BrZnJska/4FuPdRLJrHMgC7C6lQ==,iv:rSSrGHHy0RhEHFeEPZjTU2+TXWdCgrkMH8Uaamilq1k=,tag:Rm4EOvFPoVOi+dADKg97QA==,type:str] + freebox-password: ENC[AES256_GCM,data:2g9BrZnJska/4FuPdRLJrHMgC7C6lQ==,iv:rSSrGHHy0RhEHFeEPZjTU2+TXWdCgrkMH8Uaamilq1k=,tag:Rm4EOvFPoVOi+dADKg97QA==,type:str] myservice: - my_subdir: - my_secret: ENC[AES256_GCM,data:LReh8HM87Fbj,iv:HJT6/8NYWePsSo1oBpoB62cnBS68ntkyYX7Pd0Q3DsA=,tag:sKSdst4zkQAHS+7JSDhbIg==,type:str] + my_subdir: + my_secret: ENC[AES256_GCM,data:LReh8HM87Fbj,iv:HJT6/8NYWePsSo1oBpoB62cnBS68ntkyYX7Pd0Q3DsA=,tag:sKSdst4zkQAHS+7JSDhbIg==,type:str] +zed: + github_token: ENC[AES256_GCM,data:nQN2B2nXHqqWVmUk+fd/Stc+wh40MvIjKK9u8+vutLWuyfOnIXe8ww==,iv:xKbgmgSVqWz1U46/qNjzzWorOgtd7ykw2YuAkWiUy+I=,tag:aySDffoKGnSK0Xe6z3y2dw==,type:str] + brave_api_key: ENC[AES256_GCM,data:PXA4v6KiHSNisbe+rMO8Tw47nIRJoehMuTSFlqY1cw==,iv:GZiQfxDQwHYn2eI8CpOQN01xkTkgyKjHiyfcg6AqzT0=,tag:/BLiB4Dz6QuHdlLw27IeAQ==,type:str] sops: - age: - - recipient: age1h0srffx69v9cp0xd8nzgac9zmxx0x5d8d7jrf3wgl3zea9luy5fsn9llrl - enc: | - -----BEGIN AGE ENCRYPTED FILE----- - YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBRazdLc2V3bU5WTXlLVnlB - TlZGMlo2SlB6QlFyMzVPYmErVTh6QUpvMFJFCkdXTXozdlpiTVhkTEN5S2d5aVBu - YjZ6SU5NRVFxR1VZb2loeWZGN3VqUDQKLS0tIGxlZXhxTS9HL0V2YXRXVEc0RDVz - TGNWMXd1MmVaMndERGpFc1N0TklFNncKFvO2Y80Z0pLEdoKlmAJ0Me4SM/Y5v9bE - qh5J4MvY2MFK9wlgYtql6Xe/OQjzsFLa0sgWE9FBwRwMefWFOgGuRQ== - -----END AGE ENCRYPTED FILE----- - lastmodified: "2025-12-27T02:57:35Z" - mac: ENC[AES256_GCM,data:bNJrWLD3uALsCLtC92W/hHxGXbm82OwaoLLJUgzrKzOyDaSOsboi4g8NGsi+xOSqyRYFkfIOSnk5Tw4DxDOtEkJPNPHk/0Wrn2bKHsmWTbLk3r9uoSJp2AwpXByFrbdc7x30uT/rivWJVVLFGoB98p0KrHAEhfJmDZEWCdFif2Q=,iv:1JYXNkD/ks5tKs167h0lbdzG4xUsXGAoZsDVQHwqY14=,tag:wqo3QRiN/L22OBVpL0AQgA==,type:str] - unencrypted_suffix: _unencrypted - version: 3.11.0 + age: + - recipient: age1h0srffx69v9cp0xd8nzgac9zmxx0x5d8d7jrf3wgl3zea9luy5fsn9llrl + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBRazdLc2V3bU5WTXlLVnlB + TlZGMlo2SlB6QlFyMzVPYmErVTh6QUpvMFJFCkdXTXozdlpiTVhkTEN5S2d5aVBu + YjZ6SU5NRVFxR1VZb2loeWZGN3VqUDQKLS0tIGxlZXhxTS9HL0V2YXRXVEc0RDVz + TGNWMXd1MmVaMndERGpFc1N0TklFNncKFvO2Y80Z0pLEdoKlmAJ0Me4SM/Y5v9bE + qh5J4MvY2MFK9wlgYtql6Xe/OQjzsFLa0sgWE9FBwRwMefWFOgGuRQ== + -----END AGE ENCRYPTED FILE----- + lastmodified: "2025-12-27T23:02:34Z" + mac: ENC[AES256_GCM,data:/HdusE8MgcwQYLqF8+GoWBDyYcvN25OIJCSh0gWB/0V6oSDtu3VfarRPVJHcu0Zk6o2DENiPHcJ3GCDRnW85crlx8RHzth3DPeum1/h13LciekOcGXU0ELdYBHGCL8jkQ5InOFa66eXEn5J3XmoG7FPqb/P42CbraeeAhZf28rg=,iv:jTEcDZ7Gwljy5rVYzPsCB1Lg7H95fhmu5azFlKGQJ8w=,tag:tzNh+zfLVJT3Xx8UXzKzFQ==,type:str] + unencrypted_suffix: _unencrypted + version: 3.11.0