trinity-lite 0.2.0__tar.gz → 0.2.2__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.
- {trinity_lite-0.2.0 → trinity_lite-0.2.2}/PKG-INFO +3 -1
- {trinity_lite-0.2.0 → trinity_lite-0.2.2}/pyproject.toml +2 -1
- {trinity_lite-0.2.0 → trinity_lite-0.2.2}/tests/test_mcp_server.py +137 -3
- {trinity_lite-0.2.0 → trinity_lite-0.2.2}/trinity_lite/__init__.py +1 -1
- {trinity_lite-0.2.0 → trinity_lite-0.2.2}/trinity_lite/mcp_server.py +154 -1
- {trinity_lite-0.2.0 → trinity_lite-0.2.2}/trinity_lite.egg-info/PKG-INFO +3 -1
- trinity_lite-0.2.2/trinity_lite.egg-info/requires.txt +6 -0
- trinity_lite-0.2.0/trinity_lite.egg-info/requires.txt +0 -3
- {trinity_lite-0.2.0 → trinity_lite-0.2.2}/LICENSE +0 -0
- {trinity_lite-0.2.0 → trinity_lite-0.2.2}/README.md +0 -0
- {trinity_lite-0.2.0 → trinity_lite-0.2.2}/setup.cfg +0 -0
- {trinity_lite-0.2.0 → trinity_lite-0.2.2}/tests/test_bus.py +0 -0
- {trinity_lite-0.2.0 → trinity_lite-0.2.2}/tests/test_cli.py +0 -0
- {trinity_lite-0.2.0 → trinity_lite-0.2.2}/tests/test_doctor.py +0 -0
- {trinity_lite-0.2.0 → trinity_lite-0.2.2}/tests/test_guard.py +0 -0
- {trinity_lite-0.2.0 → trinity_lite-0.2.2}/tests/test_orchestrator.py +0 -0
- {trinity_lite-0.2.0 → trinity_lite-0.2.2}/tests/test_router.py +0 -0
- {trinity_lite-0.2.0 → trinity_lite-0.2.2}/tests/test_worker.py +0 -0
- {trinity_lite-0.2.0 → trinity_lite-0.2.2}/trinity_lite/__main__.py +0 -0
- {trinity_lite-0.2.0 → trinity_lite-0.2.2}/trinity_lite/adapters.py +0 -0
- {trinity_lite-0.2.0 → trinity_lite-0.2.2}/trinity_lite/bus.py +0 -0
- {trinity_lite-0.2.0 → trinity_lite-0.2.2}/trinity_lite/cli.py +0 -0
- {trinity_lite-0.2.0 → trinity_lite-0.2.2}/trinity_lite/config.py +0 -0
- {trinity_lite-0.2.0 → trinity_lite-0.2.2}/trinity_lite/doctor.py +0 -0
- {trinity_lite-0.2.0 → trinity_lite-0.2.2}/trinity_lite/guard.py +0 -0
- {trinity_lite-0.2.0 → trinity_lite-0.2.2}/trinity_lite/orchestrator.py +0 -0
- {trinity_lite-0.2.0 → trinity_lite-0.2.2}/trinity_lite/paths.py +0 -0
- {trinity_lite-0.2.0 → trinity_lite-0.2.2}/trinity_lite/py.typed +0 -0
- {trinity_lite-0.2.0 → trinity_lite-0.2.2}/trinity_lite/router.py +0 -0
- {trinity_lite-0.2.0 → trinity_lite-0.2.2}/trinity_lite/validation.py +0 -0
- {trinity_lite-0.2.0 → trinity_lite-0.2.2}/trinity_lite/worker.py +0 -0
- {trinity_lite-0.2.0 → trinity_lite-0.2.2}/trinity_lite.egg-info/SOURCES.txt +0 -0
- {trinity_lite-0.2.0 → trinity_lite-0.2.2}/trinity_lite.egg-info/dependency_links.txt +0 -0
- {trinity_lite-0.2.0 → trinity_lite-0.2.2}/trinity_lite.egg-info/entry_points.txt +0 -0
- {trinity_lite-0.2.0 → trinity_lite-0.2.2}/trinity_lite.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: trinity-lite
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.2
|
|
4
4
|
Summary: A minimal public multi-agent task bus with routing, workers, and safety checks.
|
|
5
5
|
Author: Yomiracle
|
|
6
6
|
License-Expression: MIT
|
|
@@ -19,6 +19,8 @@ Description-Content-Type: text/markdown
|
|
|
19
19
|
License-File: LICENSE
|
|
20
20
|
Provides-Extra: mcp
|
|
21
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"
|
|
22
24
|
Dynamic: license-file
|
|
23
25
|
|
|
24
26
|
# Trinity Lite
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "trinity-lite"
|
|
7
|
-
version = "0.2.
|
|
7
|
+
version = "0.2.2"
|
|
8
8
|
description = "A minimal public multi-agent task bus with routing, workers, and safety checks."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.10"
|
|
@@ -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.
|
|
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),
|
|
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"],
|
|
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()
|
|
@@ -20,10 +20,54 @@ from .guard import GuardError
|
|
|
20
20
|
from .router import resolve_route
|
|
21
21
|
from .worker import run_once as worker_run_once
|
|
22
22
|
|
|
23
|
+
# ---------------------------------------------------------------------------
|
|
24
|
+
# agent-skill-system integration (optional, graceful fallback)
|
|
25
|
+
# ---------------------------------------------------------------------------
|
|
26
|
+
|
|
27
|
+
_SKILL_ENGINE_AVAILABLE = False
|
|
28
|
+
_SKILL_BANK = None
|
|
29
|
+
_SKILL_BANK_DIR = None
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def _find_skills_dir() -> str:
|
|
33
|
+
"""Locate the agent-skill-system skills/ bank directory."""
|
|
34
|
+
# Env override
|
|
35
|
+
env_dir = os.environ.get("TRINITY_SKILLS_DIR", "")
|
|
36
|
+
if env_dir and Path(env_dir).is_dir():
|
|
37
|
+
return env_dir
|
|
38
|
+
# Check ~/.trinity/skills
|
|
39
|
+
home_skills = Path.home() / ".trinity" / "skills"
|
|
40
|
+
if home_skills.is_dir():
|
|
41
|
+
return str(home_skills)
|
|
42
|
+
# Check ~/agent-skill-system/skills (git-clone default)
|
|
43
|
+
dev_skills = Path.home() / "agent-skill-system" / "skills"
|
|
44
|
+
if dev_skills.is_dir():
|
|
45
|
+
return str(dev_skills)
|
|
46
|
+
# Default (will be auto-created by SkillBank)
|
|
47
|
+
return str(home_skills)
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def _init_skill_engine() -> bool:
|
|
51
|
+
"""Lazy-init the agent-skill-system engine. Cached after first call."""
|
|
52
|
+
global _SKILL_ENGINE_AVAILABLE, _SKILL_BANK, _SKILL_BANK_DIR
|
|
53
|
+
if _SKILL_ENGINE_AVAILABLE:
|
|
54
|
+
return True
|
|
55
|
+
try:
|
|
56
|
+
from engine.bank import SkillBank # type: ignore[import-untyped]
|
|
57
|
+
_SKILL_BANK_DIR = _find_skills_dir()
|
|
58
|
+
_SKILL_BANK = SkillBank(_SKILL_BANK_DIR)
|
|
59
|
+
_SKILL_BANK.scan_directory()
|
|
60
|
+
_SKILL_ENGINE_AVAILABLE = True
|
|
61
|
+
return True
|
|
62
|
+
except ImportError:
|
|
63
|
+
_SKILL_ENGINE_AVAILABLE = False
|
|
64
|
+
return False
|
|
65
|
+
|
|
66
|
+
|
|
23
67
|
JSONRPC_VERSION = "2.0"
|
|
24
68
|
PROTOCOL_VERSION = "2024-11-05"
|
|
25
69
|
SERVER_NAME = "trinity-lite-mcp"
|
|
26
|
-
SERVER_VERSION = "0.2.
|
|
70
|
+
SERVER_VERSION = "0.2.2"
|
|
27
71
|
|
|
28
72
|
# ---------------------------------------------------------------------------
|
|
29
73
|
# Tool definitions (MCP schema)
|
|
@@ -133,6 +177,23 @@ TOOL_DEFINITIONS = [
|
|
|
133
177
|
},
|
|
134
178
|
["target_agent", "message"],
|
|
135
179
|
),
|
|
180
|
+
_tool_def(
|
|
181
|
+
"trinity_skill_search",
|
|
182
|
+
"Search agent-skill-system for relevant skills matching a task description.",
|
|
183
|
+
{
|
|
184
|
+
"query": {"type": "string", "description": "Task description or keyword query"},
|
|
185
|
+
"limit": {"type": "integer", "description": "Maximum results (default: 5, max: 20)"},
|
|
186
|
+
},
|
|
187
|
+
["query"],
|
|
188
|
+
),
|
|
189
|
+
_tool_def(
|
|
190
|
+
"trinity_skill_load",
|
|
191
|
+
"Load the full content (SKILL.md + memory) of a named skill.",
|
|
192
|
+
{
|
|
193
|
+
"skill_name": {"type": "string", "description": "Exact name of the skill to load"},
|
|
194
|
+
},
|
|
195
|
+
["skill_name"],
|
|
196
|
+
),
|
|
136
197
|
]
|
|
137
198
|
|
|
138
199
|
TOOLS_BY_NAME = {t["name"]: t for t in TOOL_DEFINITIONS}
|
|
@@ -470,6 +531,96 @@ def _handle_trinity_send(params, bus, agents_path, routes_path):
|
|
|
470
531
|
return jsonrpc_response(1, msg)
|
|
471
532
|
|
|
472
533
|
|
|
534
|
+
def _handle_trinity_skill_search(params, bus, agents_path, routes_path):
|
|
535
|
+
query = _validate_text(params.get("query", ""), max_len=1000)
|
|
536
|
+
if not query.strip():
|
|
537
|
+
return jsonrpc_error(1, -32602, "query must not be empty")
|
|
538
|
+
limit = _validate_limit(params.get("limit"), default=5, maximum=20)
|
|
539
|
+
|
|
540
|
+
if not _init_skill_engine():
|
|
541
|
+
return jsonrpc_response(1, {
|
|
542
|
+
"error": "agent-skill-system not installed",
|
|
543
|
+
"hint": "pip install agent-skill-system",
|
|
544
|
+
"skills": [],
|
|
545
|
+
})
|
|
546
|
+
|
|
547
|
+
try:
|
|
548
|
+
from engine.searcher import SkillSearcher # type: ignore[import-untyped]
|
|
549
|
+
searcher = SkillSearcher(_SKILL_BANK_DIR)
|
|
550
|
+
results = searcher.search(query, _SKILL_BANK.index, top_n=limit)
|
|
551
|
+
except Exception as exc:
|
|
552
|
+
return jsonrpc_response(1, {
|
|
553
|
+
"error": "skill search failed: {}".format(exc),
|
|
554
|
+
"skills": [],
|
|
555
|
+
})
|
|
556
|
+
|
|
557
|
+
skills = []
|
|
558
|
+
for entry, cfg, score in results:
|
|
559
|
+
skills.append({
|
|
560
|
+
"name": entry.name,
|
|
561
|
+
"description": cfg.description,
|
|
562
|
+
"version": entry.version,
|
|
563
|
+
"success_rate": entry.success_rate,
|
|
564
|
+
"use_count": entry.use_count,
|
|
565
|
+
"score": score,
|
|
566
|
+
"tags": cfg.tags,
|
|
567
|
+
"trigger_keywords": cfg.trigger_keywords[:8],
|
|
568
|
+
})
|
|
569
|
+
|
|
570
|
+
return jsonrpc_response(1, {"skills": skills})
|
|
571
|
+
|
|
572
|
+
|
|
573
|
+
def _handle_trinity_skill_load(params, bus, agents_path, routes_path):
|
|
574
|
+
skill_name = _validate_text(params.get("skill_name", ""), max_len=128)
|
|
575
|
+
if not skill_name.strip():
|
|
576
|
+
return jsonrpc_error(1, -32602, "skill_name must not be empty")
|
|
577
|
+
|
|
578
|
+
if not _init_skill_engine():
|
|
579
|
+
return jsonrpc_response(1, {
|
|
580
|
+
"error": "agent-skill-system not installed",
|
|
581
|
+
"hint": "pip install agent-skill-system",
|
|
582
|
+
})
|
|
583
|
+
|
|
584
|
+
try:
|
|
585
|
+
from engine.loader import SkillLoader # type: ignore[import-untyped]
|
|
586
|
+
entry = _SKILL_BANK.get(skill_name)
|
|
587
|
+
if entry is None:
|
|
588
|
+
return jsonrpc_response(1, {
|
|
589
|
+
"error": "skill not found: {}".format(skill_name),
|
|
590
|
+
"available_skills": [s.name for s in _SKILL_BANK.list_active()],
|
|
591
|
+
})
|
|
592
|
+
loader = SkillLoader(_SKILL_BANK_DIR)
|
|
593
|
+
bundle = loader.load(entry)
|
|
594
|
+
if bundle is None:
|
|
595
|
+
return jsonrpc_error(1, -32002, "failed to load skill: {}".format(skill_name))
|
|
596
|
+
|
|
597
|
+
memory_entries_serialised = []
|
|
598
|
+
for mem in bundle.memory_entries:
|
|
599
|
+
memory_entries_serialised.append({
|
|
600
|
+
"date": mem.date,
|
|
601
|
+
"type": mem.type.value,
|
|
602
|
+
"title": mem.title,
|
|
603
|
+
"scene": mem.scene,
|
|
604
|
+
"detail": mem.detail,
|
|
605
|
+
})
|
|
606
|
+
|
|
607
|
+
return jsonrpc_response(1, {
|
|
608
|
+
"name": bundle.config.name,
|
|
609
|
+
"version": bundle.config.version,
|
|
610
|
+
"description": bundle.config.description,
|
|
611
|
+
"skill_md": bundle.skill_md,
|
|
612
|
+
"memory_md": bundle.memory_md,
|
|
613
|
+
"memory_entries": memory_entries_serialised,
|
|
614
|
+
"input_schema": bundle.config.input_schema,
|
|
615
|
+
"trigger_keywords": bundle.config.trigger_keywords,
|
|
616
|
+
"system_prompt": loader.build_system_prompt(bundle),
|
|
617
|
+
})
|
|
618
|
+
except Exception as exc:
|
|
619
|
+
return jsonrpc_response(1, {
|
|
620
|
+
"error": "skill load failed: {}".format(exc),
|
|
621
|
+
})
|
|
622
|
+
|
|
623
|
+
|
|
473
624
|
TOOL_HANDLERS = {
|
|
474
625
|
"trinity_dispatch": _handle_trinity_dispatch,
|
|
475
626
|
"trinity_dispatch_auto": _handle_trinity_dispatch_auto,
|
|
@@ -479,6 +630,8 @@ TOOL_HANDLERS = {
|
|
|
479
630
|
"trinity_doctor": _handle_trinity_doctor,
|
|
480
631
|
"trinity_inbox": _handle_trinity_inbox,
|
|
481
632
|
"trinity_send": _handle_trinity_send,
|
|
633
|
+
"trinity_skill_search": _handle_trinity_skill_search,
|
|
634
|
+
"trinity_skill_load": _handle_trinity_skill_load,
|
|
482
635
|
}
|
|
483
636
|
|
|
484
637
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: trinity-lite
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.2
|
|
4
4
|
Summary: A minimal public multi-agent task bus with routing, workers, and safety checks.
|
|
5
5
|
Author: Yomiracle
|
|
6
6
|
License-Expression: MIT
|
|
@@ -19,6 +19,8 @@ Description-Content-Type: text/markdown
|
|
|
19
19
|
License-File: LICENSE
|
|
20
20
|
Provides-Extra: mcp
|
|
21
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"
|
|
22
24
|
Dynamic: license-file
|
|
23
25
|
|
|
24
26
|
# Trinity Lite
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|