feat: tool schema optimization, keyword routing, aider_run coding agent
Tool schema optimization (PLAN__Tool_Schema_Optimization.md Phases 1-3): - model_registry.py: ROLE_DEFAULT_TOOLS — distill gets [], research/coder get narrow tool lists by default; applied in get_role_config() when user hasn't configured a custom list - openai_orchestrator.py: keyword routing via narrow_tools_by_keywords() — scans user message + last assistant turn; narrows active schemas to matched categories only (e.g. "weather" → 3 web tools instead of 69); zero tools sent for pure chat - openai_orchestrator.py: _get_cached_tools() — module-level schema cache keyed by (role, sorted_tool_list, risk_params); eliminates redundant schema rebuilds - openai_orchestrator.py: _TOOL_SCHEMA_OVERHEAD 3000 → 500 tokens (schemas now excluded from the per-call fixed estimate since they're cached separately) - tools/__init__.py: CATEGORY_TOOL_MAP + _KEYWORD_CATEGORY_MAP + classify_tool_categories() + narrow_tools_by_keywords() — the classifier logic lives here so both orchestrators can share it aider_run tool (cortex/tools/aider.py): - Invokes Aider as a subprocess with --message --yes-always --no-pretty --no-stream - Project aliases: cortex / aether_api / aether_frontend / aether_container - Auto-injects OpenRouter API key from Cortex model registry (no ~/.env needed) - background=True fires async + registers in agent_manager; notify=True sends push notification on completion - admin-only, confirm-required, TOOL_RISK=high - .gitignore: added .aider.chat.history.md / .aider.input.history / .aider.llm.history Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -81,6 +81,24 @@ from config import settings
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
# ── Role-level tool defaults ───────────────────────────────────────────────────
|
||||
# Applied when a user hasn't configured a custom tool list for a role.
|
||||
# None = no restriction (all accessible tools); [] = no tools (pure text processing).
|
||||
# "chat" is intentionally absent: the /chat endpoint never sends tool schemas anyway,
|
||||
# and the orchestrator uses chat_role="chat" as its default — restricting it here
|
||||
# would block all tools from every default orchestration request.
|
||||
# "orchestrator" is intentionally absent — Phase 2 keyword routing narrows it per message.
|
||||
ROLE_DEFAULT_TOOLS: dict[str, list[str] | None] = {
|
||||
"distill": [], # pure text processing — no tools needed
|
||||
"research": ["web_search", "web_read", "http_fetch"],
|
||||
"coder": [
|
||||
"project_file_read", "project_file_list", "file_stat", "file_grep",
|
||||
"file_diff", "file_syntax_check", "file_read", "file_list", "file_write",
|
||||
"git_status", "git_log", "git_diff", "shell_exec",
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
# ── Provider model catalogs ───────────────────────────────────────────────────
|
||||
# Server-side defaults. Update here when providers release new models.
|
||||
# Users can add entries via the settings UI (Phase 2).
|
||||
@@ -482,9 +500,16 @@ def get_role_config(username: str, role: str) -> dict:
|
||||
"""
|
||||
registry = _load(username)
|
||||
role_cfg = registry.get("roles", {}).get(role, {})
|
||||
user_tools = role_cfg.get("tools")
|
||||
if user_tools is None:
|
||||
# No user-configured list — fall back to system defaults for this role
|
||||
effective_tools: list[str] | None = ROLE_DEFAULT_TOOLS.get(role)
|
||||
else:
|
||||
# User has configured tools; preserve their setting (empty list → no restriction)
|
||||
effective_tools = user_tools or None
|
||||
return {
|
||||
"system_append": role_cfg.get("system_append", ""),
|
||||
"tools": role_cfg.get("tools") or None,
|
||||
"tools": effective_tools,
|
||||
"inject_datetime": role_cfg.get("inject_datetime", True),
|
||||
"inject_mode": role_cfg.get("inject_mode", True),
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user