feat: add agent registry manifests and coverage

Introduce a manifest-backed agent registry surface and align graph tests with the new runtime prompt and tool indexing behavior.
This commit is contained in:
2026-04-02 14:34:26 +08:00
parent e9ba8597e9
commit 4251a79062
12 changed files with 1111 additions and 423 deletions

View File

@@ -0,0 +1,76 @@
from __future__ import annotations
from collections.abc import Mapping
from dataclasses import dataclass
from types import MappingProxyType
from app.agents.registry.loader import RegistryBundle
from app.agents.registry.models import (
AgentManifest,
CapabilityManifest,
SpecialistTemplateManifest,
SubCommanderManifest,
)
@dataclass(frozen=True)
class RegistryIndexes:
agent_by_id: Mapping[str, AgentManifest]
sub_commander_by_id: Mapping[str, SubCommanderManifest]
capability_by_id: Mapping[str, CapabilityManifest]
specialist_template_by_id: Mapping[str, SpecialistTemplateManifest]
agent_prompt_key_by_id: Mapping[str, str]
sub_commander_prompt_key_by_id: Mapping[str, str]
skill_context_key_by_agent_id: Mapping[str, str]
capability_id_by_tool_name: Mapping[str, str]
capability_ids_by_sub_commander_id: Mapping[str, tuple[str, ...]]
def summarize_registry_indexes(indexes: RegistryIndexes) -> dict[str, int]:
return {
"agent_count": len(indexes.agent_by_id),
"sub_commander_count": len(indexes.sub_commander_by_id),
"capability_count": len(indexes.capability_by_id),
"specialist_template_count": len(indexes.specialist_template_by_id),
}
def build_registry_indexes(bundle: RegistryBundle) -> RegistryIndexes:
agent_by_id = {agent.agent_id: agent for agent in bundle.agents}
sub_commander_by_id = {
sub_commander.sub_commander_id: sub_commander
for sub_commander in bundle.sub_commanders
}
capability_by_id = {
capability.capability_id: capability for capability in bundle.capabilities
}
specialist_template_by_id = {
template.template_id: template for template in bundle.specialist_templates
}
return RegistryIndexes(
agent_by_id=MappingProxyType(agent_by_id),
sub_commander_by_id=MappingProxyType(sub_commander_by_id),
capability_by_id=MappingProxyType(capability_by_id),
specialist_template_by_id=MappingProxyType(specialist_template_by_id),
agent_prompt_key_by_id=MappingProxyType({
agent.agent_id: agent.system_prompt_key for agent in bundle.agents
}),
sub_commander_prompt_key_by_id=MappingProxyType({
sub_commander.sub_commander_id: sub_commander.sub_commander_id
for sub_commander in bundle.sub_commanders
}),
skill_context_key_by_agent_id=MappingProxyType({
agent.agent_id: agent.skill_context_key
for agent in bundle.agents
if agent.skill_context_key is not None
}),
capability_id_by_tool_name=MappingProxyType({
capability.tool_name: capability.capability_id
for capability in bundle.capabilities
}),
capability_ids_by_sub_commander_id=MappingProxyType({
sub_commander.sub_commander_id: tuple(sub_commander.capability_ids)
for sub_commander in bundle.sub_commanders
}),
)