feat(agents): add Pi and OMP

This commit is contained in:
Ryan Yin
2026-09-18 21:20:33 +08:00
committed by ryan4yin | 二花
parent 46266dd8ea
commit 23258a06d4
7 changed files with 42 additions and 4 deletions
+3 -1
View File
@@ -33,6 +33,8 @@ Current targets:
- Codex: `AGENTS.md` -> `${CODEX_HOME:-~/.codex}/AGENTS.md` - Codex: `AGENTS.md` -> `${CODEX_HOME:-~/.codex}/AGENTS.md`
- OpenCode: `AGENTS.md` -> `${XDG_CONFIG_HOME:-~/.config}/opencode/AGENTS.md` - OpenCode: `AGENTS.md` -> `${XDG_CONFIG_HOME:-~/.config}/opencode/AGENTS.md`
- Pi: `AGENTS.md` -> `~/.pi/agent/AGENTS.md`
- OMP: `AGENTS.md` -> `~/.omp/agent/AGENTS.md`
- Generic cross-tool (read by Kimi Code): `AGENTS.md` -> `~/.agents/AGENTS.md` - Generic cross-tool (read by Kimi Code): `AGENTS.md` -> `~/.agents/AGENTS.md`
Behavior: Behavior:
@@ -70,7 +72,7 @@ Ideas worth adopting once a concrete need appears; nothing here is implemented y
scripts above do not cover it. scripts above do not cover it.
- **Shared instructions and skills.** Deploy one rules body plus declared skills to every agent - **Shared instructions and skills.** Deploy one rules body plus declared skills to every agent
(Codex, OpenCode, Kimi Code) instead of maintaining a copy per agent. Reference: `mirkolenz/infra` instead of maintaining a copy per agent. Reference: `mirkolenz/infra`
`options/home-manager/agents.nix` (custom `programs.agents`, follows the Agent Skills spec) and `options/home-manager/agents.nix` (custom `programs.agents`, follows the Agent Skills spec) and
`khaneliman/khanelinix` `modules/common/ai-tools/`. `khaneliman/khanelinix` `modules/common/ai-tools/`.
- **Single-source permissions.** Keep allow/ask/deny command lists and agent role definitions in one - **Single-source permissions.** Keep allow/ask/deny command lists and agent role definitions in one
+2
View File
@@ -10,6 +10,8 @@ Installed via Nix:
- opencode - opencode
- cursor-agent(cli) - cursor-agent(cli)
- kimi-code - kimi-code
- pi
- omp
## Optional tooling ## Optional tooling
+4
View File
@@ -45,10 +45,14 @@ def main() -> int:
codex_dir = Path(os.environ.get("CODEX_HOME", "~/.codex")).expanduser() codex_dir = Path(os.environ.get("CODEX_HOME", "~/.codex")).expanduser()
xdg_config_home = Path(os.environ.get("XDG_CONFIG_HOME", "~/.config")).expanduser() xdg_config_home = Path(os.environ.get("XDG_CONFIG_HOME", "~/.config")).expanduser()
opencode_dir = xdg_config_home / "opencode" opencode_dir = xdg_config_home / "opencode"
pi_dir = Path("~/.pi/agent").expanduser()
omp_dir = Path("~/.omp/agent").expanduser()
agents_dir = Path("~/.agents").expanduser() agents_dir = Path("~/.agents").expanduser()
targets = ( targets = (
(codex_dir, "AGENTS.md"), (codex_dir, "AGENTS.md"),
(opencode_dir, "AGENTS.md"), (opencode_dir, "AGENTS.md"),
(pi_dir, "AGENTS.md"),
(omp_dir, "AGENTS.md"),
(agents_dir, "AGENTS.md"), (agents_dir, "AGENTS.md"),
) )
failed = False failed = False
+27 -3
View File
@@ -1,5 +1,6 @@
import importlib.util import importlib.util
import io import io
import os
import tempfile import tempfile
import unittest import unittest
from pathlib import Path from pathlib import Path
@@ -14,21 +15,44 @@ spec.loader.exec_module(installer)
class InstallRulesTests(unittest.TestCase): class InstallRulesTests(unittest.TestCase):
def test_main_links_all_supported_agent_targets(self):
with tempfile.TemporaryDirectory() as directory:
home = Path(directory)
target_names = (
(home / ".codex", "AGENTS.md"),
(home / ".config" / "opencode", "AGENTS.md"),
(home / ".pi" / "agent", "AGENTS.md"),
(home / ".omp" / "agent", "AGENTS.md"),
(home / ".agents", "AGENTS.md"),
)
for target_dir, _ in target_names:
target_dir.mkdir(parents=True)
with patch.dict(os.environ, {"HOME": str(home)}, clear=True):
self.assertEqual(installer.main(), 0)
for target_dir, target_name in target_names:
target = target_dir / target_name
self.assertTrue(target.is_symlink(), target)
self.assertEqual(target.resolve(), installer.Path(__file__).with_name("AGENTS.md"))
def test_target_failure_does_not_stop_remaining_targets(self): def test_target_failure_does_not_stop_remaining_targets(self):
with ( with (
patch.object( patch.object(
installer, "install_one", side_effect=[PermissionError("denied"), None, None] installer,
"install_one",
side_effect=[PermissionError("denied"), None, None, None, None],
) as install, ) as install,
patch("sys.stderr", new_callable=io.StringIO) as stderr, patch("sys.stderr", new_callable=io.StringIO) as stderr,
): ):
self.assertEqual(installer.main(), 1) self.assertEqual(installer.main(), 1)
self.assertEqual(install.call_count, 3) self.assertEqual(install.call_count, 5)
self.assertIn("denied", stderr.getvalue()) self.assertIn("denied", stderr.getvalue())
def test_successful_targets_return_success(self): def test_successful_targets_return_success(self):
with patch.object(installer, "install_one") as install: with patch.object(installer, "install_one") as install:
self.assertEqual(installer.main(), 0) self.assertEqual(installer.main(), 0)
self.assertEqual(install.call_count, 3) self.assertEqual(install.call_count, 5)
def test_existing_file_is_backed_up_without_overwriting_backup(self): def test_existing_file_is_backed_up_without_overwriting_backup(self):
with tempfile.TemporaryDirectory() as directory: with tempfile.TemporaryDirectory() as directory:
+2
View File
@@ -14,6 +14,8 @@
cursor-cli cursor-cli
opencode opencode
kimi-code kimi-code
pi
omp
# Utilities # Utilities
rtk # CLI proxy that reduces LLM token consumption rtk # CLI proxy that reduces LLM token consumption
+2
View File
@@ -159,6 +159,8 @@ in
".config/agents" ".config/agents"
".codex" ".codex"
".kimi-code" ".kimi-code"
".pi"
".omp"
".config/opencode" ".config/opencode"
".local/share/opencode" ".local/share/opencode"
".local/state/opencode" ".local/state/opencode"
+2
View File
@@ -86,6 +86,8 @@
cursor-cli cursor-cli
opencode opencode
kimi-code kimi-code
pi
omp
# Utilities # Utilities
rtk # CLI proxy that reduces LLM token consumption rtk # CLI proxy that reduces LLM token consumption