diff --git a/.gitignore b/.gitignore index 7362628..78f436a 100644 --- a/.gitignore +++ b/.gitignore @@ -24,3 +24,19 @@ Thumbs.db # Opencode rules .opencode-rules opencode.json + +# Taskplane runtime artifacts (machine-specific, do not commit) +.pi/batch-state.json +.pi/batch-history.json +.pi/lane-state-* +.pi/merge-result-* +.pi/merge-request-* +.pi/worker-conversation-* +.pi/orch-logs/ +.pi/orch-abort-signal +.pi/settings.json +.worktrees/ +.taskplane-tasks/ + +# Pi project-local packages (if using pi install -l) +.pi/npm/ diff --git a/flake.lock b/flake.lock index b5239b4..5ce394e 100644 --- a/flake.lock +++ b/flake.lock @@ -268,11 +268,11 @@ "uv2nix": "uv2nix_2" }, "locked": { - "lastModified": 1775649585, - "narHash": "sha256-m1DICRvc4jc1Rar0zKrVA6TYXjef8QFRXjRc5/AU0rc=", + "lastModified": 1775750438, + "narHash": "sha256-8HoZTK49+dK26iBcaizanUpy37JH3nkPVrZHcPBVtUM=", "owner": "NousResearch", "repo": "hermes-agent", - "rev": "ff6a86cb529a372198b4b80d5e022e32a4a3f2cc", + "rev": "d9753720f366287d52be14386e8f1eabbbe89fe3", "type": "github" }, "original": { @@ -432,14 +432,17 @@ "openspec": "openspec" }, "locked": { - "lastModified": 1775658058, - "narHash": "sha256-CceoYh5lvS6CdqvsRk79XE6qTEuXEMtRzjEahsRlILo=", - "path": "/home/m3tam3re/p/NIX/nixpkgs", - "type": "path" + "lastModified": 1775663240, + "narHash": "sha256-W81Zj1C6Beuqgd2yKhW0no84H7FJhEh74hPvecO4bbU=", + "ref": "refs/heads/master", + "rev": "77833a7ecaa4b30999872c31b90cb023b4a348f3", + "revCount": 216, + "type": "git", + "url": "https://code.m3ta.dev/m3tam3re/nixpkgs" }, "original": { - "path": "/home/m3tam3re/p/NIX/nixpkgs", - "type": "path" + "type": "git", + "url": "https://code.m3ta.dev/m3tam3re/nixpkgs" } }, "nix-colors": { @@ -640,16 +643,16 @@ }, "nixpkgs_3": { "locked": { - "lastModified": 1751274312, - "narHash": "sha256-/bVBlRpECLVzjV19t5KMdMFWSwKLtb5RyXdjz3LJT+g=", + "lastModified": 1775036866, + "narHash": "sha256-ZojAnPuCdy657PbTq5V0Y+AHKhZAIwSIT2cb8UgAz/U=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "50ab793786d9de88ee30ec4e4c24fb4236fc2674", + "rev": "6201e203d09599479a3b3450ed24fa81537ebc4e", "type": "github" }, "original": { "owner": "NixOS", - "ref": "nixos-24.11", + "ref": "nixos-unstable", "repo": "nixpkgs", "type": "github" } diff --git a/flake.nix b/flake.nix index 34156bf..ef4f790 100644 --- a/flake.nix +++ b/flake.nix @@ -106,6 +106,7 @@ ./hosts/m3-ares agenix.nixosModules.default m3ta-nixpkgs.nixosModules.default + inputs.hermes-agent.nixosModules.default ]; }; m3-atlas = nixpkgs.lib.nixosSystem { diff --git a/home/features/cli/nushell.nix b/home/features/cli/nushell.nix index 9c0f350..9af5e45 100644 --- a/home/features/cli/nushell.nix +++ b/home/features/cli/nushell.nix @@ -24,7 +24,7 @@ in { $env.XDG_DATA_HOME = $"($env.HOME)/.local/share" $env.FZF_DEFAULT_COMMAND = "fd --type f --exclude .git --follow --hidden" $env.SSH_AUTH_SOCK = "/run/user/1000/gnupg/S.gpg-agent.ssh" - $env.PATH = ($env.PATH | split row (char esep) | append "/home/sascha.koenig/.cache/.bun/bin" | uniq) + $env.PATH = ($env.PATH | split row (char esep) | append $"($env.HOME)/.cache/.bun/bin" | append $"($env.HOME)/.npm-global/bin" | uniq) $env.FLAKE = $"($env.HOME)/p/NIX/nixos-config" # Load kestractl-env from agenix diff --git a/home/features/desktop/default.nix b/home/features/desktop/default.nix index 15ad082..33c3780 100644 --- a/home/features/desktop/default.nix +++ b/home/features/desktop/default.nix @@ -114,7 +114,9 @@ # clipman distrobox eigent - element-desktop + (element-desktop.override { + commandLineArgs = "--password-store=gnome-libsecret"; + }) launch-webapp # eww # firefox-devedition diff --git a/home/m3tam3re/home.nix b/home/m3tam3re/home.nix index 889e7a2..780abe3 100644 --- a/home/m3tam3re/home.nix +++ b/home/m3tam3re/home.nix @@ -205,7 +205,7 @@ "m3-hermes" = { hostname = "204.168.229.93"; user = "m3tam3re"; - identityFile = "~/.ssh/sascha.koenig"; + identityFile = "~/.ssh/m3tam3re"; }; "m3-zelda" = { hostname = "95.217.189.186"; diff --git a/hosts/m3-ares/secrets.nix b/hosts/m3-ares/secrets.nix index 1b58f4d..402d8a4 100644 --- a/hosts/m3-ares/secrets.nix +++ b/hosts/m3-ares/secrets.nix @@ -50,6 +50,10 @@ file = ../../secrets/m3tam3re-secrets.age; owner = "m3tam3re"; }; + hermes-env = { + file = ../../secrets/hermes-env.age; + owner = "m3tam3re"; + }; }; }; } diff --git a/hosts/m3-ares/services/default.nix b/hosts/m3-ares/services/default.nix index 1e89404..6869131 100644 --- a/hosts/m3-ares/services/default.nix +++ b/hosts/m3-ares/services/default.nix @@ -1,6 +1,7 @@ {pkgs, ...}: { imports = [ ./containers + ./hermes-agent.nix ./netbird.nix #./n8n.nix ./mem0.nix diff --git a/hosts/m3-ares/services/hermes-agent.nix b/hosts/m3-ares/services/hermes-agent.nix new file mode 100644 index 0000000..f7fc934 --- /dev/null +++ b/hosts/m3-ares/services/hermes-agent.nix @@ -0,0 +1,184 @@ +{config, ...}: let + # Default ElevenLabs voice: Bella (German-capable female) + elevenlabsVoiceId = "hpp4J3VqNfWAUOO0d1Us"; +in { + services.hermes-agent = { + enable = true; + addToSystemPackages = true; + + # Secrets via agenix + environmentFiles = [config.age.secrets."hermes-env".path]; + + # Non-secret environment variables + environment = { + GLM_BASE_URL = "https://api.z.ai/api/coding/paas/v4/"; + }; + + settings = { + # ── Model ────────────────────────────────────────────────────────── + model = { + default = "glm-5.1"; + provider = "zai"; + }; + + credential_pool_strategies = { + zai = "fill_first"; + }; + + toolsets = ["all"]; + + # ── Agent ────────────────────────────────────────────────────────── + agent = { + max_turns = 90; + gateway_timeout = 1800; + tool_use_enforcement = "auto"; + }; + + # ── Terminal ─────────────────────────────────────────────────────── + terminal = { + backend = "ssh"; + modal_mode = "auto"; + cwd = "."; + timeout = 180; + persistent_shell = true; + }; + + # ── Browser ──────────────────────────────────────────────────────── + browser = { + inactivity_timeout = 120; + command_timeout = 30; + cloud_provider = "local"; + }; + + # ── Checkpoints / Compression ────────────────────────────────────── + checkpoints = { + enabled = true; + max_snapshots = 50; + }; + + file_read_max_chars = 100000; + + compression = { + enabled = true; + threshold = 0.5; + target_ratio = 0.2; + protect_last_n = 20; + }; + + # ── Display ──────────────────────────────────────────────────────── + display = { + compact = false; + personality = "kawaii"; + resume_display = "full"; + busy_input_mode = "interrupt"; + inline_diffs = true; + skin = "default"; + tool_progress = "all"; + }; + + # ── TTS / STT / Voice ────────────────────────────────────────────── + tts = { + provider = "elevenlabs"; + elevenlabs = { + voice_id = elevenlabsVoiceId; + model_id = "eleven_multilingual_v2"; + }; + }; + + stt = { + enabled = true; + provider = "local"; + local = {model = "base";}; + }; + + voice = { + record_key = "ctrl+b"; + max_recording_seconds = 120; + silence_threshold = 200; + silence_duration = 3.0; + }; + + # ── Memory ───────────────────────────────────────────────────────── + memory = { + memory_enabled = true; + user_profile_enabled = true; + memory_char_limit = 2200; + user_char_limit = 1375; + }; + + # ── Delegation ───────────────────────────────────────────────────── + delegation = { + max_iterations = 50; + }; + + # ── Discord ──────────────────────────────────────────────────────── + discord = { + require_mention = true; + auto_thread = true; + reactions = true; + }; + + # ── Approvals / Security ─────────────────────────────────────────── + approvals = { + mode = "manual"; + timeout = 60; + }; + + security = { + redact_secrets = true; + tirith_enabled = true; + tirith_fail_open = true; + }; + + # ── Cron / Session ───────────────────────────────────────────────── + cron = {wrap_response = true;}; + + session_reset = { + mode = "both"; + idle_minutes = 1440; + at_hour = 4; + }; + + # ── Web ──────────────────────────────────────────────────────────── + web = {backend = "exa";}; + + # ── Platform Toolsets ────────────────────────────────────────────── + platform_toolsets = { + cli = [ + "browser" + "clarify" + "code_execution" + "cronjob" + "delegation" + "file" + "image_gen" + "memory" + "session_search" + "skills" + "terminal" + "todo" + "tts" + "vision" + "web" + ]; + telegram = [ + "browser" + "clarify" + "code_execution" + "cronjob" + "delegation" + "file" + "image_gen" + "memory" + "session_search" + "skills" + "terminal" + "todo" + "tts" + "vision" + "web" + ]; + }; + }; + }; +} diff --git a/hosts/m3-atlas/configuration.nix b/hosts/m3-atlas/configuration.nix index dddbfeb..baea3bb 100644 --- a/hosts/m3-atlas/configuration.nix +++ b/hosts/m3-atlas/configuration.nix @@ -59,7 +59,11 @@ # List packages installed in system profile. To search, run: # $ nix search wget - environment.systemPackages = with pkgs; [neovim git]; + environment.systemPackages = with pkgs; [ + neovim + git + ghostty.terminfo + ]; # Some programs need SUID wrappers, can be configured further or are # started in user sessions. diff --git a/hosts/m3-hermes/configuration.nix b/hosts/m3-hermes/configuration.nix index bde3173..63bac3f 100644 --- a/hosts/m3-hermes/configuration.nix +++ b/hosts/m3-hermes/configuration.nix @@ -16,7 +16,11 @@ time.timeZone = "Europe/Berlin"; i18n.defaultLocale = "en_US.UTF-8"; - environment.systemPackages = with pkgs; [neovim git]; + environment.systemPackages = with pkgs; [ + neovim + git + ghostty.terminfo + ]; services.openssh = { enable = true; diff --git a/secrets/hermes-cloud-env.age b/secrets/hermes-cloud-env.age index fe290cf..430608e 100644 Binary files a/secrets/hermes-cloud-env.age and b/secrets/hermes-cloud-env.age differ diff --git a/taskplane-tasks/CONTEXT.md b/taskplane-tasks/CONTEXT.md deleted file mode 100644 index f7e7d0a..0000000 --- a/taskplane-tasks/CONTEXT.md +++ /dev/null @@ -1,31 +0,0 @@ -# General — Context - -**Last Updated:** 2026-04-08 -**Status:** Active -**Next Task ID:** TP-002 - ---- - -## Current State - -This is the default task area for nixos-config. Tasks that don't belong -to a specific domain area are created here. - -Taskplane is configured and ready for task execution. Use `/task` for single -tasks or `/orch all` for parallel batch execution. - ---- - -## Key Files - -| Category | Path | -|----------|------| -| Tasks | `taskplane-tasks/` | -| Config | `.pi/task-runner.yaml` | -| Config | `.pi/task-orchestrator.yaml` | - ---- - -## Technical Debt / Future Work - -_Items discovered during task execution are logged here by agents._ diff --git a/taskplane-tasks/EXAMPLE-001-hello-world/PROMPT.md b/taskplane-tasks/EXAMPLE-001-hello-world/PROMPT.md deleted file mode 100644 index 00211ad..0000000 --- a/taskplane-tasks/EXAMPLE-001-hello-world/PROMPT.md +++ /dev/null @@ -1,98 +0,0 @@ -# Task: EXAMPLE-001 — Hello World - -**Created:** 2026-04-08 -**Size:** S - -## Review Level: 0 (None) - -**Assessment:** Trivial single-file task to verify Taskplane is working. -**Score:** 0/8 — Blast radius: 0, Pattern novelty: 0, Security: 0, Reversibility: 0 - -## Canonical Task Folder - -``` -taskplane-tasks/EXAMPLE-001-hello-world/ -├── PROMPT.md ← This file (immutable above --- divider) -├── STATUS.md ← Execution state (worker updates this) -├── .reviews/ ← Reviewer output (task-runner creates this) -└── .DONE ← Created when complete -``` - -## Mission - -Create a simple `hello-taskplane.md` file in the project root to verify that -Taskplane task execution is working correctly. This is a smoke test — if the -worker can read this prompt, create the file, checkpoint progress, and mark the -task done, the installation is healthy. - -## Expected File Content - -`hello-taskplane.md` should include: - -- A title line (for example: `# Hello from Taskplane`) -- A line containing the task ID: `EXAMPLE-001` -- A line containing today's date - -## Dependencies - -- **None** - -## Context to Read First - -_No additional context needed._ - -## Environment - -- **Workspace:** Project root -- **Services required:** None - -## File Scope - -- `hello-taskplane.md` - -## Steps - -### Step 0: Preflight - -- [ ] Verify this PROMPT.md is readable -- [ ] Verify STATUS.md exists in the same folder - -### Step 1: Create Hello File - -- [ ] Create `hello-taskplane.md` in the project root -- [ ] Add a title plus lines containing today's date and task ID `EXAMPLE-001` - -### Step 2: Verification - -- [ ] Verify `hello-taskplane.md` exists and matches the expected content - -### Step 3: Delivery - - - -## Documentation Requirements - -**Must Update:** None -**Check If Affected:** None - -## Completion Criteria - -- [ ] `hello-taskplane.md` exists in the project root -- [ ] `hello-taskplane.md` includes a title, task ID (`EXAMPLE-001`), and current date - -## Git Commit Convention - -- **Implementation:** `feat(EXAMPLE-001): description` -- **Checkpoints:** `checkpoint: EXAMPLE-001 description` - -## Do NOT - -- Modify any existing project files -- Create files outside the project root -- Over-engineer this — it's a smoke test - ---- - -## Amendments (Added During Execution) - - diff --git a/taskplane-tasks/EXAMPLE-001-hello-world/STATUS.md b/taskplane-tasks/EXAMPLE-001-hello-world/STATUS.md deleted file mode 100644 index 4e9c776..0000000 --- a/taskplane-tasks/EXAMPLE-001-hello-world/STATUS.md +++ /dev/null @@ -1,73 +0,0 @@ -# EXAMPLE-001: Hello World — Status - -**Current Step:** Not Started -**Status:** 🔵 Ready for Execution -**Last Updated:** 2026-04-08 -**Review Level:** 0 -**Review Counter:** 0 -**Iteration:** 0 -**Size:** S - ---- - -### Step 0: Preflight -**Status:** ⬜ Not Started - -- [ ] Verify PROMPT.md is readable -- [ ] Verify STATUS.md exists - ---- - -### Step 1: Create Hello File -**Status:** ⬜ Not Started - -- [ ] Create `hello-taskplane.md` in project root -- [ ] Add title, date, and task ID (EXAMPLE-001) - ---- - -### Step 2: Verification -**Status:** ⬜ Not Started - -- [ ] Verify file exists and matches expected content - ---- - -### Step 3: Delivery -**Status:** ⬜ Not Started - - - ---- - -## Reviews - -| # | Type | Step | Verdict | File | -|---|------|------|---------|------| - ---- - -## Discoveries - -| Discovery | Disposition | Location | -|-----------|-------------|----------| - ---- - -## Execution Log - -| Timestamp | Action | Outcome | -|-----------|--------|---------| -| 2026-04-08 | Task staged | PROMPT.md and STATUS.md created | - ---- - -## Blockers - -*None* - ---- - -## Notes - -*This is an example task created by `taskplane init`. Delete it after verifying your setup works.* diff --git a/taskplane-tasks/EXAMPLE-002-parallel-smoke/PROMPT.md b/taskplane-tasks/EXAMPLE-002-parallel-smoke/PROMPT.md deleted file mode 100644 index cab8917..0000000 --- a/taskplane-tasks/EXAMPLE-002-parallel-smoke/PROMPT.md +++ /dev/null @@ -1,97 +0,0 @@ -# Task: EXAMPLE-002 — Parallel Smoke - -**Created:** 2026-04-08 -**Size:** S - -## Review Level: 0 (None) - -**Assessment:** Trivial parallel-safe smoke task to demonstrate orchestrator lanes. -**Score:** 0/8 — Blast radius: 0, Pattern novelty: 0, Security: 0, Reversibility: 0 - -## Canonical Task Folder - -``` -taskplane-tasks/EXAMPLE-002-parallel-smoke/ -├── PROMPT.md ← This file (immutable above --- divider) -├── STATUS.md ← Execution state (worker updates this) -├── .reviews/ ← Reviewer output (task-runner creates this) -└── .DONE ← Created when complete -``` - -## Mission - -Create a simple `hello-taskplane-2.md` file in the project root. This task is -intentionally independent from EXAMPLE-001 so both can run in parallel when -using `/orch`. - -## Expected File Content - -`hello-taskplane-2.md` should include: - -- A title line (for example: `# Parallel Hello from Taskplane`) -- A line containing the task ID: `EXAMPLE-002` -- A short note that this task is parallel-safe - -## Dependencies - -- **None** - -## Context to Read First - -_No additional context needed._ - -## Environment - -- **Workspace:** Project root -- **Services required:** None - -## File Scope - -- `hello-taskplane-2.md` - -## Steps - -### Step 0: Preflight - -- [ ] Verify this PROMPT.md is readable -- [ ] Verify STATUS.md exists in the same folder - -### Step 1: Create Parallel Hello File - -- [ ] Create `hello-taskplane-2.md` in the project root -- [ ] Add title plus lines containing task ID `EXAMPLE-002` and a parallel-safe note - -### Step 2: Verification - -- [ ] Verify `hello-taskplane-2.md` exists and matches the expected content - -### Step 3: Delivery - - - -## Documentation Requirements - -**Must Update:** None -**Check If Affected:** None - -## Completion Criteria - -- [ ] `hello-taskplane-2.md` exists in the project root -- [ ] `hello-taskplane-2.md` includes a title, task ID (`EXAMPLE-002`), and a parallel-safe note - -## Git Commit Convention - -- **Implementation:** `feat(EXAMPLE-002): description` -- **Checkpoints:** `checkpoint: EXAMPLE-002 description` - -## Do NOT - -- Modify any existing project files -- Create files outside the project root -- Add dependencies between EXAMPLE-001 and EXAMPLE-002 - ---- - -## Amendments (Added During Execution) - - diff --git a/taskplane-tasks/EXAMPLE-002-parallel-smoke/STATUS.md b/taskplane-tasks/EXAMPLE-002-parallel-smoke/STATUS.md deleted file mode 100644 index f6064ba..0000000 --- a/taskplane-tasks/EXAMPLE-002-parallel-smoke/STATUS.md +++ /dev/null @@ -1,73 +0,0 @@ -# EXAMPLE-002: Parallel Smoke — Status - -**Current Step:** Not Started -**Status:** 🔵 Ready for Execution -**Last Updated:** 2026-04-08 -**Review Level:** 0 -**Review Counter:** 0 -**Iteration:** 0 -**Size:** S - ---- - -### Step 0: Preflight -**Status:** ⬜ Not Started - -- [ ] Verify PROMPT.md is readable -- [ ] Verify STATUS.md exists - ---- - -### Step 1: Create Parallel Hello File -**Status:** ⬜ Not Started - -- [ ] Create `hello-taskplane-2.md` in project root -- [ ] Add title, task ID (EXAMPLE-002), and parallel-safe note - ---- - -### Step 2: Verification -**Status:** ⬜ Not Started - -- [ ] Verify file exists and matches expected content - ---- - -### Step 3: Delivery -**Status:** ⬜ Not Started - - - ---- - -## Reviews - -| # | Type | Step | Verdict | File | -|---|------|------|---------|------| - ---- - -## Discoveries - -| Discovery | Disposition | Location | -|-----------|-------------|----------| - ---- - -## Execution Log - -| Timestamp | Action | Outcome | -|-----------|--------|---------| -| 2026-04-08 | Task staged | PROMPT.md and STATUS.md created | - ---- - -## Blockers - -*None* - ---- - -## Notes - -*This is an example task created by `taskplane init` to demonstrate orchestrator-first onboarding.*