feat(capabilities): add write router factory and MCP composition (HUB-WP-0002)

Add create_capability_request_write_router with host workflow callbacks,
CapabilityRequestReroute schema, HubCoreMCPServer.attach_to() with CORE_TOOL_NAMES
exclude filtering, tests, and mark HUB-WP-0002 finished.
This commit is contained in:
2026-06-22 19:52:22 +02:00
parent b1be2ad788
commit af28282861
8 changed files with 428 additions and 225 deletions

View File

@@ -14,6 +14,7 @@ from hub_core.routers import (
create_capabilities_router,
create_capability_catalog_router,
create_capability_request_read_router,
create_capability_request_write_router,
create_domains_router,
create_messages_router,
create_policy_router,
@@ -297,6 +298,59 @@ def test_capability_catalog_router_accepts_host_model_injection() -> None:
}
def test_capability_request_write_router_registers_write_paths() -> None:
async def get_session():
raise AssertionError("router construction should not resolve sessions")
router = create_capability_request_write_router(get_session)
method_paths = {
(method, route.path)
for route in router.routes
for method in getattr(route, "methods", set())
}
assert method_paths == {
("POST", "/capability-requests/"),
("POST", "/capability-requests/{request_id}/accept"),
("PATCH", "/capability-requests/{request_id}/status"),
("PATCH", "/capability-requests/{request_id}"),
("POST", "/capability-requests/{request_id}/dispute"),
("POST", "/capability-requests/{request_id}/reroute"),
}
def test_capability_request_write_router_invokes_callbacks() -> None:
calls: list[str] = []
async def get_session():
raise AssertionError("router construction should not resolve sessions")
async def route_request(session, body):
calls.append("route")
return None, None, "routed"
def build_request(body, requesting_domain, fulfilling_domain_id, catalog_entry_id, routing_note):
calls.append("build")
return object()
async def on_request_persisted(session, req, body):
calls.append("persisted")
def check_transition(current, target):
calls.append(f"transition:{current}->{target}")
router = create_capability_request_write_router(
get_session,
route_request=route_request,
build_request=build_request,
on_request_persisted=on_request_persisted,
check_transition=check_transition,
)
assert router.routes
assert calls == []
def test_capability_request_read_router_accepts_host_model_injection() -> None:
async def get_session():
raise AssertionError("router construction should not resolve sessions")