trinity-lite 0.2.0__tar.gz → 0.2.3__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. trinity_lite-0.2.3/PKG-INFO +167 -0
  2. trinity_lite-0.2.3/README.md +142 -0
  3. {trinity_lite-0.2.0 → trinity_lite-0.2.3}/pyproject.toml +3 -2
  4. {trinity_lite-0.2.0 → trinity_lite-0.2.3}/tests/test_mcp_server.py +137 -3
  5. {trinity_lite-0.2.0 → trinity_lite-0.2.3}/trinity_lite/__init__.py +1 -1
  6. {trinity_lite-0.2.0 → trinity_lite-0.2.3}/trinity_lite/mcp_server.py +154 -1
  7. trinity_lite-0.2.3/trinity_lite.egg-info/PKG-INFO +167 -0
  8. trinity_lite-0.2.3/trinity_lite.egg-info/requires.txt +6 -0
  9. trinity_lite-0.2.0/PKG-INFO +0 -267
  10. trinity_lite-0.2.0/README.md +0 -244
  11. trinity_lite-0.2.0/trinity_lite.egg-info/PKG-INFO +0 -267
  12. trinity_lite-0.2.0/trinity_lite.egg-info/requires.txt +0 -3
  13. {trinity_lite-0.2.0 → trinity_lite-0.2.3}/LICENSE +0 -0
  14. {trinity_lite-0.2.0 → trinity_lite-0.2.3}/setup.cfg +0 -0
  15. {trinity_lite-0.2.0 → trinity_lite-0.2.3}/tests/test_bus.py +0 -0
  16. {trinity_lite-0.2.0 → trinity_lite-0.2.3}/tests/test_cli.py +0 -0
  17. {trinity_lite-0.2.0 → trinity_lite-0.2.3}/tests/test_doctor.py +0 -0
  18. {trinity_lite-0.2.0 → trinity_lite-0.2.3}/tests/test_guard.py +0 -0
  19. {trinity_lite-0.2.0 → trinity_lite-0.2.3}/tests/test_orchestrator.py +0 -0
  20. {trinity_lite-0.2.0 → trinity_lite-0.2.3}/tests/test_router.py +0 -0
  21. {trinity_lite-0.2.0 → trinity_lite-0.2.3}/tests/test_worker.py +0 -0
  22. {trinity_lite-0.2.0 → trinity_lite-0.2.3}/trinity_lite/__main__.py +0 -0
  23. {trinity_lite-0.2.0 → trinity_lite-0.2.3}/trinity_lite/adapters.py +0 -0
  24. {trinity_lite-0.2.0 → trinity_lite-0.2.3}/trinity_lite/bus.py +0 -0
  25. {trinity_lite-0.2.0 → trinity_lite-0.2.3}/trinity_lite/cli.py +0 -0
  26. {trinity_lite-0.2.0 → trinity_lite-0.2.3}/trinity_lite/config.py +0 -0
  27. {trinity_lite-0.2.0 → trinity_lite-0.2.3}/trinity_lite/doctor.py +0 -0
  28. {trinity_lite-0.2.0 → trinity_lite-0.2.3}/trinity_lite/guard.py +0 -0
  29. {trinity_lite-0.2.0 → trinity_lite-0.2.3}/trinity_lite/orchestrator.py +0 -0
  30. {trinity_lite-0.2.0 → trinity_lite-0.2.3}/trinity_lite/paths.py +0 -0
  31. {trinity_lite-0.2.0 → trinity_lite-0.2.3}/trinity_lite/py.typed +0 -0
  32. {trinity_lite-0.2.0 → trinity_lite-0.2.3}/trinity_lite/router.py +0 -0
  33. {trinity_lite-0.2.0 → trinity_lite-0.2.3}/trinity_lite/validation.py +0 -0
  34. {trinity_lite-0.2.0 → trinity_lite-0.2.3}/trinity_lite/worker.py +0 -0
  35. {trinity_lite-0.2.0 → trinity_lite-0.2.3}/trinity_lite.egg-info/SOURCES.txt +0 -0
  36. {trinity_lite-0.2.0 → trinity_lite-0.2.3}/trinity_lite.egg-info/dependency_links.txt +0 -0
  37. {trinity_lite-0.2.0 → trinity_lite-0.2.3}/trinity_lite.egg-info/entry_points.txt +0 -0
  38. {trinity_lite-0.2.0 → trinity_lite-0.2.3}/trinity_lite.egg-info/top_level.txt +0 -0
@@ -0,0 +1,167 @@
1
+ Metadata-Version: 2.4
2
+ Name: trinity-lite
3
+ Version: 0.2.3
4
+ Summary: The bus that lets your AI agents talk to each other.
5
+ Author: Yomiracle
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/Yomiracle/trinity-lite
8
+ Project-URL: Repository, https://github.com/Yomiracle/trinity-lite
9
+ Project-URL: Issues, https://github.com/Yomiracle/trinity-lite/issues
10
+ Keywords: ai-agent,multi-agent,agent-orchestration,codex,claude-code
11
+ Classifier: Development Status :: 3 - Alpha
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Programming Language :: Python :: 3.10
15
+ Classifier: Programming Language :: Python :: 3.11
16
+ Classifier: Programming Language :: Python :: 3.12
17
+ Requires-Python: >=3.10
18
+ Description-Content-Type: text/markdown
19
+ License-File: LICENSE
20
+ Provides-Extra: mcp
21
+ Requires-Dist: mcp>=1.0; extra == "mcp"
22
+ Provides-Extra: agent-skill
23
+ Requires-Dist: agent-skill-system>=1.0.6; extra == "agent-skill"
24
+ Dynamic: license-file
25
+
26
+ # Trinity Lite
27
+
28
+ [![Tests](https://github.com/Yomiracle/trinity-lite/actions/workflows/test.yml/badge.svg)](https://github.com/Yomiracle/trinity-lite/actions/workflows/test.yml)
29
+ [![Python 3.10+](https://img.shields.io/badge/python-3.10%2B-blue.svg)](pyproject.toml)
30
+ [![License: MIT](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE)
31
+ [![PyPI](https://img.shields.io/pypi/v/trinity-lite.svg)](https://pypi.org/project/trinity-lite/)
32
+
33
+ **The bus that lets your AI agents talk to each other.**
34
+
35
+ [中文 README](README_zh.md)
36
+
37
+ ## The problem
38
+
39
+ You already use Claude Code. Maybe you just installed Codex. You want them to collaborate — but there's no built-in way to route tasks between them, remember who did what, or stop them from stepping on each other. Trinity Lite is the missing layer.
40
+
41
+ ## What it does
42
+
43
+ - **Route by capability, not name.** You describe the task. The router matches it to the right agent — no hardcoded agent names, no fragile dispatch logic. *"Implement a rate limiter" lands on the agent you tagged `implement`. "Review the auth module" goes to the agent tagged `review`.*
44
+ - **Give every agent a pull queue.** Workers read pending tasks from the shared bus, execute them via CLI, and write results back. Each agent polls on its own schedule. You never copy-paste an output between terminals again.
45
+ - **Remember every decision.** Every task, status change, result, error, and inter-agent message lands in a local SQLite database. Query who did what, when, and what happened — without setting up a logging pipeline.
46
+ - **Block footguns before they fire.** Self-delegation loops are rejected. Delegation depth has a hard cap. Working directories must be in the allowlist. You ship features, not incident reports.
47
+
48
+ ## Quick start
49
+
50
+ 30 seconds, no agents required:
51
+
52
+ ```bash
53
+ pip install trinity-lite
54
+ trinity-lite doctor
55
+ trinity-lite dispatch-auto "implement a hello-world function"
56
+ trinity-lite worker codex --once
57
+ trinity-lite tasks
58
+ ```
59
+
60
+ Mock agents are built in. You see the full dispatch → execute → result cycle before you wire up anything real.
61
+
62
+ ## Not another framework
63
+
64
+ Trinity Lite doesn't build agents. It connects the agents you already have.
65
+
66
+ LangGraph and CrewAI give you primitives for building agents from scratch — graph definitions, role abstractions, tool wrappers. Trinity Lite starts from the opposite end: Claude Code is running in one terminal, Codex is running in another, and they need a shared task bus, durable state, and safety boundaries. No SDK to learn. No new agent abstraction. Just a bus that works with the CLIs you already use.
67
+
68
+ ## Who this is for
69
+
70
+ | You are... | Trinity Lite helps you... |
71
+ |------------|---------------------------|
72
+ | Copy-pasting prompts and outputs between two agent terminals all day | Dispatch once to the bus and let agents pull their own work |
73
+ | Prototyping a multi-agent pipeline before committing infrastructure | Run the full flow with mock agents — no API keys, no provisioning |
74
+ | Running everything on a single machine with zero server setup | Keep your state in SQLite, your runtime in stdlib, your daemon count at zero |
75
+ | Showing a colleague how multi-agent collaboration works | `pip install` → five commands → they see it run. No explanation needed. |
76
+
77
+ ## Features
78
+
79
+ - **Route by capability.** Tag agents with `implement`, `review`, `audit` — the router matches tasks to the agent that can do them. No agent names in your dispatch logic.
80
+ - **Dispatch directly when you need control.** Bypass the router and send a task straight to `claude_code` or `codex`. Best of both worlds.
81
+ - **Persist everything in SQLite.** Tasks, statuses, results, errors, and messages in one local file. Query it with `sqlite3` or any tool that speaks SQL.
82
+ - **Run CLI workers on demand.** `trinity-lite worker codex --once` pulls one queued task, executes the agent's command, and writes the result. Run it in a loop, in cron, or by hand.
83
+ - **Execute safely, no shell injection.** Agent commands are JSON arrays run with `shell=False`. No string interpolation into a shell. No surprises.
84
+ - **Test with mock agents.** Mock agents simulate the full cycle without real CLIs. Prototype routing, persistence, and review handoffs first. Wire up real agents later.
85
+ - **Guard against runaway delegation.** Self-delegation is blocked. Delegation depth is capped. Working directories are allowlisted. Safe by default.
86
+ - **Check health in one pass.** `trinity-lite doctor` verifies Python, SQLite, route config, agent config, and publish readiness.
87
+ - **Zero dependencies.** Runtime is Python standard library only. Nothing to install but Python 3.10+.
88
+ - **109 tests guarding the surface area.** Mock workflows, safety checks, routing, persistence — all covered.
89
+
90
+ ## Install
91
+
92
+ ```bash
93
+ pip install trinity-lite
94
+ ```
95
+
96
+ Python 3.10+. Zero runtime dependencies. Standard library only.
97
+
98
+ ### Optional extras
99
+
100
+ ```bash
101
+ pip install trinity-lite[mcp] # MCP server — 10 tools + 3 resources
102
+ pip install trinity-lite[agent-skill] # agent-skill-system integration
103
+ ```
104
+
105
+ ## Workflow example
106
+
107
+ Hermes routes → Codex implements → Claude Code reviews. Five commands, one audit trail.
108
+
109
+ ```bash
110
+ # Hermes sends the task. The router picks Codex automatically.
111
+ trinity-lite dispatch-auto "implement a rate limiter for the API" --source-agent hermes
112
+
113
+ # Codex pulls the task and runs it.
114
+ trinity-lite worker codex --once --agents agents.local.json
115
+
116
+ # Claude Code reviews the result.
117
+ trinity-lite send claude_code "please review task <task_id>" --source-agent hermes
118
+ trinity-lite worker claude_code --once --agents agents.local.json
119
+
120
+ # Read the full trail.
121
+ trinity-lite status <task_id>
122
+ ```
123
+
124
+ Works immediately with mock agents. Ready for real CLIs when you are:
125
+
126
+ ```bash
127
+ cp examples/agents.command.example.json agents.local.json
128
+ ```
129
+
130
+ ## MCP server
131
+
132
+ Turn the task bus into an MCP server. Let any MCP client dispatch, query, and route tasks.
133
+
134
+ ```bash
135
+ pip install trinity-lite[mcp]
136
+ trinity-lite mcp serve
137
+ ```
138
+
139
+ **10 tools:**
140
+
141
+ | Tool | What it does |
142
+ |------|--------------|
143
+ | `trinity_dispatch` | Dispatch a task to a specific agent |
144
+ | `trinity_dispatch_auto` | Dispatch and let the capability router pick the agent |
145
+ | `trinity_status` | Get the state and result of any task by ID |
146
+ | `trinity_tasks` | List recent tasks, filterable by agent |
147
+ | `trinity_worker` | Run one worker cycle for an agent |
148
+ | `trinity_doctor` | Run health and diagnostic checks |
149
+ | `trinity_inbox` | Read durable messages for an agent |
150
+ | `trinity_send` | Send a message from one agent to another |
151
+ | `trinity_skill_search` | Search agent-skill-system for relevant skills |
152
+ | `trinity_skill_load` | Load the full content of a named skill |
153
+
154
+ **3 resources:** `trinity://health`, `trinity://tasks/recent`, `trinity://tasks/{task_id}`
155
+
156
+ ## Links
157
+
158
+ - [PyPI](https://pypi.org/project/trinity-lite/)
159
+ - [Documentation](docs/)
160
+ - [Changelog](CHANGELOG.md)
161
+ - [Contributing](CONTRIBUTING.md)
162
+ - [Architecture](docs/ARCHITECTURE.md)
163
+ - [Real agent setup](docs/REAL_AGENTS.md)
164
+
165
+ ## License
166
+
167
+ MIT
@@ -0,0 +1,142 @@
1
+ # Trinity Lite
2
+
3
+ [![Tests](https://github.com/Yomiracle/trinity-lite/actions/workflows/test.yml/badge.svg)](https://github.com/Yomiracle/trinity-lite/actions/workflows/test.yml)
4
+ [![Python 3.10+](https://img.shields.io/badge/python-3.10%2B-blue.svg)](pyproject.toml)
5
+ [![License: MIT](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE)
6
+ [![PyPI](https://img.shields.io/pypi/v/trinity-lite.svg)](https://pypi.org/project/trinity-lite/)
7
+
8
+ **The bus that lets your AI agents talk to each other.**
9
+
10
+ [中文 README](README_zh.md)
11
+
12
+ ## The problem
13
+
14
+ You already use Claude Code. Maybe you just installed Codex. You want them to collaborate — but there's no built-in way to route tasks between them, remember who did what, or stop them from stepping on each other. Trinity Lite is the missing layer.
15
+
16
+ ## What it does
17
+
18
+ - **Route by capability, not name.** You describe the task. The router matches it to the right agent — no hardcoded agent names, no fragile dispatch logic. *"Implement a rate limiter" lands on the agent you tagged `implement`. "Review the auth module" goes to the agent tagged `review`.*
19
+ - **Give every agent a pull queue.** Workers read pending tasks from the shared bus, execute them via CLI, and write results back. Each agent polls on its own schedule. You never copy-paste an output between terminals again.
20
+ - **Remember every decision.** Every task, status change, result, error, and inter-agent message lands in a local SQLite database. Query who did what, when, and what happened — without setting up a logging pipeline.
21
+ - **Block footguns before they fire.** Self-delegation loops are rejected. Delegation depth has a hard cap. Working directories must be in the allowlist. You ship features, not incident reports.
22
+
23
+ ## Quick start
24
+
25
+ 30 seconds, no agents required:
26
+
27
+ ```bash
28
+ pip install trinity-lite
29
+ trinity-lite doctor
30
+ trinity-lite dispatch-auto "implement a hello-world function"
31
+ trinity-lite worker codex --once
32
+ trinity-lite tasks
33
+ ```
34
+
35
+ Mock agents are built in. You see the full dispatch → execute → result cycle before you wire up anything real.
36
+
37
+ ## Not another framework
38
+
39
+ Trinity Lite doesn't build agents. It connects the agents you already have.
40
+
41
+ LangGraph and CrewAI give you primitives for building agents from scratch — graph definitions, role abstractions, tool wrappers. Trinity Lite starts from the opposite end: Claude Code is running in one terminal, Codex is running in another, and they need a shared task bus, durable state, and safety boundaries. No SDK to learn. No new agent abstraction. Just a bus that works with the CLIs you already use.
42
+
43
+ ## Who this is for
44
+
45
+ | You are... | Trinity Lite helps you... |
46
+ |------------|---------------------------|
47
+ | Copy-pasting prompts and outputs between two agent terminals all day | Dispatch once to the bus and let agents pull their own work |
48
+ | Prototyping a multi-agent pipeline before committing infrastructure | Run the full flow with mock agents — no API keys, no provisioning |
49
+ | Running everything on a single machine with zero server setup | Keep your state in SQLite, your runtime in stdlib, your daemon count at zero |
50
+ | Showing a colleague how multi-agent collaboration works | `pip install` → five commands → they see it run. No explanation needed. |
51
+
52
+ ## Features
53
+
54
+ - **Route by capability.** Tag agents with `implement`, `review`, `audit` — the router matches tasks to the agent that can do them. No agent names in your dispatch logic.
55
+ - **Dispatch directly when you need control.** Bypass the router and send a task straight to `claude_code` or `codex`. Best of both worlds.
56
+ - **Persist everything in SQLite.** Tasks, statuses, results, errors, and messages in one local file. Query it with `sqlite3` or any tool that speaks SQL.
57
+ - **Run CLI workers on demand.** `trinity-lite worker codex --once` pulls one queued task, executes the agent's command, and writes the result. Run it in a loop, in cron, or by hand.
58
+ - **Execute safely, no shell injection.** Agent commands are JSON arrays run with `shell=False`. No string interpolation into a shell. No surprises.
59
+ - **Test with mock agents.** Mock agents simulate the full cycle without real CLIs. Prototype routing, persistence, and review handoffs first. Wire up real agents later.
60
+ - **Guard against runaway delegation.** Self-delegation is blocked. Delegation depth is capped. Working directories are allowlisted. Safe by default.
61
+ - **Check health in one pass.** `trinity-lite doctor` verifies Python, SQLite, route config, agent config, and publish readiness.
62
+ - **Zero dependencies.** Runtime is Python standard library only. Nothing to install but Python 3.10+.
63
+ - **109 tests guarding the surface area.** Mock workflows, safety checks, routing, persistence — all covered.
64
+
65
+ ## Install
66
+
67
+ ```bash
68
+ pip install trinity-lite
69
+ ```
70
+
71
+ Python 3.10+. Zero runtime dependencies. Standard library only.
72
+
73
+ ### Optional extras
74
+
75
+ ```bash
76
+ pip install trinity-lite[mcp] # MCP server — 10 tools + 3 resources
77
+ pip install trinity-lite[agent-skill] # agent-skill-system integration
78
+ ```
79
+
80
+ ## Workflow example
81
+
82
+ Hermes routes → Codex implements → Claude Code reviews. Five commands, one audit trail.
83
+
84
+ ```bash
85
+ # Hermes sends the task. The router picks Codex automatically.
86
+ trinity-lite dispatch-auto "implement a rate limiter for the API" --source-agent hermes
87
+
88
+ # Codex pulls the task and runs it.
89
+ trinity-lite worker codex --once --agents agents.local.json
90
+
91
+ # Claude Code reviews the result.
92
+ trinity-lite send claude_code "please review task <task_id>" --source-agent hermes
93
+ trinity-lite worker claude_code --once --agents agents.local.json
94
+
95
+ # Read the full trail.
96
+ trinity-lite status <task_id>
97
+ ```
98
+
99
+ Works immediately with mock agents. Ready for real CLIs when you are:
100
+
101
+ ```bash
102
+ cp examples/agents.command.example.json agents.local.json
103
+ ```
104
+
105
+ ## MCP server
106
+
107
+ Turn the task bus into an MCP server. Let any MCP client dispatch, query, and route tasks.
108
+
109
+ ```bash
110
+ pip install trinity-lite[mcp]
111
+ trinity-lite mcp serve
112
+ ```
113
+
114
+ **10 tools:**
115
+
116
+ | Tool | What it does |
117
+ |------|--------------|
118
+ | `trinity_dispatch` | Dispatch a task to a specific agent |
119
+ | `trinity_dispatch_auto` | Dispatch and let the capability router pick the agent |
120
+ | `trinity_status` | Get the state and result of any task by ID |
121
+ | `trinity_tasks` | List recent tasks, filterable by agent |
122
+ | `trinity_worker` | Run one worker cycle for an agent |
123
+ | `trinity_doctor` | Run health and diagnostic checks |
124
+ | `trinity_inbox` | Read durable messages for an agent |
125
+ | `trinity_send` | Send a message from one agent to another |
126
+ | `trinity_skill_search` | Search agent-skill-system for relevant skills |
127
+ | `trinity_skill_load` | Load the full content of a named skill |
128
+
129
+ **3 resources:** `trinity://health`, `trinity://tasks/recent`, `trinity://tasks/{task_id}`
130
+
131
+ ## Links
132
+
133
+ - [PyPI](https://pypi.org/project/trinity-lite/)
134
+ - [Documentation](docs/)
135
+ - [Changelog](CHANGELOG.md)
136
+ - [Contributing](CONTRIBUTING.md)
137
+ - [Architecture](docs/ARCHITECTURE.md)
138
+ - [Real agent setup](docs/REAL_AGENTS.md)
139
+
140
+ ## License
141
+
142
+ MIT
@@ -4,8 +4,8 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "trinity-lite"
7
- version = "0.2.0"
8
- description = "A minimal public multi-agent task bus with routing, workers, and safety checks."
7
+ version = "0.2.3"
8
+ description = "The bus that lets your AI agents talk to each other."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
11
11
  license = "MIT"
@@ -26,6 +26,7 @@ dependencies = []
26
26
 
27
27
  [project.optional-dependencies]
28
28
  mcp = ["mcp>=1.0"]
29
+ agent-skill = ["agent-skill-system>=1.0.6"]
29
30
 
30
31
  [project.scripts]
31
32
  trinity-lite = "trinity_lite.cli:main"
@@ -1,5 +1,6 @@
1
1
  import io
2
2
  import json
3
+ import os
3
4
  import sys
4
5
  import tempfile
5
6
  import unittest
@@ -22,6 +23,19 @@ from trinity_lite.mcp_server import (
22
23
  _get_known_agents,
23
24
  )
24
25
 
26
+ try:
27
+ from engine.bank import SkillBank # noqa: F401
28
+
29
+ HAS_AGENT_SKILL = True
30
+ except ImportError:
31
+ HAS_AGENT_SKILL = False
32
+
33
+ # Detect agent-skill-system skills directory
34
+ SKILLS_DIR = os.environ.get(
35
+ "TRINITY_SKILLS_DIR",
36
+ os.path.expanduser("~/agent-skill-system/skills"),
37
+ )
38
+
25
39
 
26
40
  class McpServerTest(unittest.TestCase):
27
41
  def setUp(self):
@@ -54,7 +68,7 @@ class McpServerTest(unittest.TestCase):
54
68
  self.assertIn("resources", resp["result"]["capabilities"])
55
69
  self.assertIn("serverInfo", resp["result"])
56
70
  self.assertEqual(resp["result"]["serverInfo"]["name"], "trinity-lite-mcp")
57
- self.assertEqual(resp["result"]["serverInfo"]["version"], "0.2.0")
71
+ self.assertEqual(resp["result"]["serverInfo"]["version"], "0.2.2")
58
72
 
59
73
  def test_initialized_returns_none(self):
60
74
  resp = self._call(self._msg("initialized"))
@@ -76,7 +90,7 @@ class McpServerTest(unittest.TestCase):
76
90
  resp = self._call(self._msg("tools/list", 1))
77
91
  tools = resp["result"]["tools"]
78
92
  self.assertIsInstance(tools, list)
79
- self.assertEqual(len(tools), 8)
93
+ self.assertEqual(len(tools), 10)
80
94
  names = [t["name"] for t in tools]
81
95
  self.assertIn("trinity_dispatch", names)
82
96
  self.assertIn("trinity_dispatch_auto", names)
@@ -86,6 +100,8 @@ class McpServerTest(unittest.TestCase):
86
100
  self.assertIn("trinity_doctor", names)
87
101
  self.assertIn("trinity_inbox", names)
88
102
  self.assertIn("trinity_send", names)
103
+ self.assertIn("trinity_skill_search", names)
104
+ self.assertIn("trinity_skill_load", names)
89
105
  # Check schema structure
90
106
  for t in tools:
91
107
  self.assertIn("name", t)
@@ -117,7 +133,7 @@ class McpServerTest(unittest.TestCase):
117
133
  data = json.loads(contents[0]["text"])
118
134
  self.assertEqual(data["status"], "ok")
119
135
  self.assertEqual(data["bus"], "connected")
120
- self.assertEqual(data["tools"], 8)
136
+ self.assertEqual(data["tools"], 10)
121
137
  self.assertEqual(data["resources"], 3)
122
138
 
123
139
  def test_resource_health_degraded(self):
@@ -451,5 +467,123 @@ class McpServerTest(unittest.TestCase):
451
467
  self.assertEqual(compact["id"], "abc123def456")
452
468
 
453
469
 
470
+ # ---- Skills: agent-skill-system integration ----
471
+
472
+ def test_skill_search_without_agent_skill_system(self):
473
+ """Graceful error when agent-skill-system not installed."""
474
+ import trinity_lite.mcp_server as mcp
475
+ from unittest.mock import patch
476
+
477
+ with patch.object(mcp, "_init_skill_engine", return_value=False):
478
+ params = {
479
+ "name": "trinity_skill_search",
480
+ "arguments": {"query": "parse a contract"},
481
+ }
482
+ resp = self._call(self._msg("tools/call", 1, params))
483
+ self.assertIn("result", resp)
484
+ self.assertIn("error", resp["result"])
485
+ self.assertEqual(resp["result"]["error"], "agent-skill-system not installed")
486
+ self.assertIn("hint", resp["result"])
487
+
488
+ @unittest.skipUnless(HAS_AGENT_SKILL and Path(SKILLS_DIR).exists(),
489
+ "agent-skill-system not installed or skills dir not found")
490
+ def test_skill_search_returns_matching_skills(self):
491
+ """Search returns matching skills when engine is available."""
492
+ import trinity_lite.mcp_server as mcp
493
+
494
+ old_available = mcp._SKILL_ENGINE_AVAILABLE
495
+ old_bank = mcp._SKILL_BANK
496
+ old_bank_dir = mcp._SKILL_BANK_DIR
497
+ try:
498
+ from engine.bank import SkillBank
499
+ mcp._SKILL_ENGINE_AVAILABLE = True
500
+ mcp._SKILL_BANK_DIR = SKILLS_DIR
501
+ mcp._SKILL_BANK = SkillBank(mcp._SKILL_BANK_DIR)
502
+ mcp._SKILL_BANK.scan_directory()
503
+
504
+ params = {
505
+ "name": "trinity_skill_search",
506
+ "arguments": {"query": "generate a weekly report", "limit": 3},
507
+ }
508
+ resp = self._call(self._msg("tools/call", 1, params))
509
+ self.assertIn("result", resp)
510
+ self.assertIn("skills", resp["result"])
511
+ skills = resp["result"]["skills"]
512
+ self.assertIsInstance(skills, list)
513
+ if skills:
514
+ self.assertIn("name", skills[0])
515
+ self.assertIn("description", skills[0])
516
+ self.assertIn("score", skills[0])
517
+ finally:
518
+ mcp._SKILL_ENGINE_AVAILABLE = old_available
519
+ mcp._SKILL_BANK = old_bank
520
+ mcp._SKILL_BANK_DIR = old_bank_dir
521
+
522
+ @unittest.skipUnless(HAS_AGENT_SKILL and Path(SKILLS_DIR).exists(),
523
+ "agent-skill-system not installed or skills dir not found")
524
+ def test_skill_load_returns_content(self):
525
+ """Load a skill's full content."""
526
+ import trinity_lite.mcp_server as mcp
527
+
528
+ old_available = mcp._SKILL_ENGINE_AVAILABLE
529
+ old_bank = mcp._SKILL_BANK
530
+ old_bank_dir = mcp._SKILL_BANK_DIR
531
+ try:
532
+ from engine.bank import SkillBank
533
+ mcp._SKILL_ENGINE_AVAILABLE = True
534
+ mcp._SKILL_BANK_DIR = SKILLS_DIR
535
+ mcp._SKILL_BANK = SkillBank(mcp._SKILL_BANK_DIR)
536
+ mcp._SKILL_BANK.scan_directory()
537
+
538
+ # Pick an active skill from the bank
539
+ active = mcp._SKILL_BANK.list_active()
540
+ if active:
541
+ skill_name = active[0].name
542
+ params = {
543
+ "name": "trinity_skill_load",
544
+ "arguments": {"skill_name": skill_name},
545
+ }
546
+ resp = self._call(self._msg("tools/call", 1, params))
547
+ self.assertIn("result", resp)
548
+ result = resp["result"]
549
+ self.assertIn("name", result)
550
+ self.assertIn("skill_md", result)
551
+ self.assertIn("system_prompt", result)
552
+ finally:
553
+ mcp._SKILL_ENGINE_AVAILABLE = old_available
554
+ mcp._SKILL_BANK = old_bank
555
+ mcp._SKILL_BANK_DIR = old_bank_dir
556
+
557
+ @unittest.skipUnless(HAS_AGENT_SKILL and Path(SKILLS_DIR).exists(),
558
+ "agent-skill-system not installed or skills dir not found")
559
+ def test_skill_load_not_found(self):
560
+ """Graceful error when skill name is not in the bank."""
561
+ import trinity_lite.mcp_server as mcp
562
+
563
+ old_available = mcp._SKILL_ENGINE_AVAILABLE
564
+ old_bank = mcp._SKILL_BANK
565
+ old_bank_dir = mcp._SKILL_BANK_DIR
566
+ try:
567
+ from engine.bank import SkillBank
568
+ mcp._SKILL_ENGINE_AVAILABLE = True
569
+ mcp._SKILL_BANK_DIR = SKILLS_DIR
570
+ mcp._SKILL_BANK = SkillBank(mcp._SKILL_BANK_DIR)
571
+ mcp._SKILL_BANK.scan_directory()
572
+
573
+ params = {
574
+ "name": "trinity_skill_load",
575
+ "arguments": {"skill_name": "nonexistent-skill-xyz"},
576
+ }
577
+ resp = self._call(self._msg("tools/call", 1, params))
578
+ self.assertIn("result", resp)
579
+ self.assertIn("error", resp["result"])
580
+ self.assertIn("skill not found", resp["result"]["error"])
581
+ self.assertIn("available_skills", resp["result"])
582
+ finally:
583
+ mcp._SKILL_ENGINE_AVAILABLE = old_available
584
+ mcp._SKILL_BANK = old_bank
585
+ mcp._SKILL_BANK_DIR = old_bank_dir
586
+
587
+
454
588
  if __name__ == "__main__":
455
589
  unittest.main()
@@ -1,3 +1,3 @@
1
1
  """Trinity Lite: a minimal public multi-agent task bus."""
2
2
 
3
- __version__ = "0.2.0"
3
+ __version__ = "0.2.2"