[eric] agents: drop dead build_connected_tools_context (disabled in 27149eeb) + always-None param + write-only thinking.total_chars

This commit is contained in:
ciregenz
2026-06-23 14:50:15 -07:00
parent 8c0a5010e1
commit e1e25eb891
5 changed files with 5 additions and 92 deletions
@@ -7,7 +7,7 @@ from backend.apps.tools_lib.tools_lib import (
_load_all as load_all_tools,
_sanitize_server_name as sanitize_server_name,
)
from backend.apps.agents.manager.prompt.tool_catalog import get_denied_tool_names, is_fully_denied
from backend.apps.agents.manager.prompt.tool_catalog import is_fully_denied
@typechecked
@@ -20,88 +20,6 @@ def resolve_mode(mode_id: str, get_all_tool_names: Callable[[], List[str]]) -> T
return get_all_tool_names(), None, None
@typechecked
def build_connected_tools_context(allowed_tools: List[str], get_all_tool_names: Callable[[], List[str]]) -> Optional[str]:
"""Build a context block describing connected MCP tools and their accounts.
Tools set to 'deny' and fully-denied servers are excluded.
"""
all_tools = load_all_tools()
mcp_tools = [t for t in all_tools if t.mcp_config and t.enabled and t.auth_status in ("configured", "connected")]
sections = []
for tool in mcp_tools:
tool_ref = f"mcp:{tool.name}"
if tool_ref not in allowed_tools and allowed_tools != get_all_tool_names():
continue
if is_fully_denied(tool):
continue
server_name = sanitize_server_name(tool.name)
denied = get_denied_tool_names(tool)
tool_descs = {
k: v for k, v in tool.tool_permissions.get("_tool_descriptions", {}).items()
if k not in denied
}
if not tool_descs:
continue
lines = [f"MCP Server: {server_name}"]
lines.append(f" Status: {tool.auth_status}")
if tool.connected_account_email:
lines.append(f" Connected account: {tool.connected_account_email}")
lines.append(
f" IMPORTANT: When calling tools from this server that require an email "
f"parameter (e.g. user_google_email, user_email), always use "
f"\"{tool.connected_account_email}\" automatically, do NOT ask the user."
)
# Discord guild scoping, hard restriction. The bot may technically
# be in other servers (across other OpenSwarm users), but this
# specific user only authorized these guild IDs.
if tool.name.lower() == "discord":
guilds = tool.oauth_tokens.get("guilds") or []
if guilds:
guild_descriptions = ", ".join(
f"{g.get('name', 'Unknown')} ({g.get('id', '')})" for g in guilds
)
allowed_ids = [g.get("id", "") for g in guilds if g.get("id")]
lines.append(
f" AUTHORIZED DISCORD SERVERS (guild_ids): {guild_descriptions}"
)
lines.append(
f" HARD RESTRICTION: You MUST only call Discord tools that operate on "
f"these guild_ids: {allowed_ids}. NEVER call Discord tools on any other "
f"guild_id even if the bot has access to it. NEVER list, search, or "
f"enumerate servers outside this list. If a user asks about a server "
f"not in this list, refuse and tell them to authorize it via the Connect "
f"Discord button. This is a security boundary, not a preference."
)
else:
lines.append(
" No Discord servers authorized yet. Tell the user to click "
"'Connect Discord' to add a server before attempting any Discord actions."
)
tool_names = list(tool_descs.keys())
if tool_names:
lines.append(f" Available tools ({len(tool_names)}): {', '.join(tool_names)}")
sections.append("\n".join(lines))
if not sections:
return None
return (
"<connected_mcp_tools>\n"
"The following MCP tool servers are connected and available. "
"Use them directly when relevant to the user's request.\n\n"
+ "\n\n".join(sections)
+ "\n</connected_mcp_tools>"
)
# A run of this many ToolSearch calls with no other tool between them is the
# "looping on ToolSearch" wedge: the model hunts for a gated MCP server's tools,
# which ToolSearch can never see, gets empty results, and retries. Two free
@@ -421,10 +339,10 @@ AGENT_IDENTITY = (
@typechecked
def compose_system_prompt(default_prompt: Optional[str], mode_prompt: Optional[str], session_prompt: Optional[str], connected_tools_ctx: Optional[str] = None, browser_ctx: Optional[str] = None, mcp_registry_ctx: Optional[str] = None) -> Optional[str]:
def compose_system_prompt(default_prompt: Optional[str], mode_prompt: Optional[str], session_prompt: Optional[str], browser_ctx: Optional[str] = None, mcp_registry_ctx: Optional[str] = None) -> Optional[str]:
# Identity always leads so it overrides the preset's Claude Code persona, even
# when the user has no custom default/mode/session prompt of their own.
parts = [AGENT_IDENTITY] + [p for p in (default_prompt, mode_prompt, session_prompt, connected_tools_ctx, mcp_registry_ctx, browser_ctx) if p]
parts = [AGENT_IDENTITY] + [p for p in (default_prompt, mode_prompt, session_prompt, mcp_registry_ctx, browser_ctx) if p]
return "\n\n".join(parts)
@@ -32,16 +32,14 @@ def compose_turn_system_prompt(
# MCP servers and their tool inventories are intentionally NOT injected into the system
# prompt: the CLI's deferred-tool pool already exposes them by name via ToolSearch, and
# eagerly listing connected MCPs (account emails, full tool enumerations) here would defeat
# the deferral and leak every integration into every turn. So connected-tools context stays
# None; the model discovers MCPs only when it actively calls ToolSearch.
connected_tools_ctx = None
# the deferral and leak every integration into every turn. The model discovers MCPs only
# when it actively calls ToolSearch; only the gated registry summary goes in.
browser_ctx = build_browser_context(session.dashboard_id, selected_browser_ids=selected_browser_ids)
mcp_registry_ctx = build_mcp_registry_summary(session.allowed_tools, session.active_mcps, get_all_tool_names)
composed_prompt = compose_system_prompt(
default_system_prompt,
mode_sys_prompt,
session.system_prompt,
connected_tools_ctx,
browser_ctx,
mcp_registry_ctx,
)
@@ -132,7 +132,6 @@ async def handle_result_message(
turn.baseline_children_out = 0
turn.baseline_captured = False
thinking.total_ms = 0
thinking.total_chars = 0
thinking.block_starts = {}
session.sdk_session_id = getattr(message, "session_id", None)
@@ -18,7 +18,6 @@ class ThinkingState(BaseModel):
# block index -> wall-clock start (s); popped to accumulate total_ms when a block ends.
block_starts: Dict[int, float] = {}
total_ms: int = 0
total_chars: int = 0
# Stable id for the turn's single thinking message (frontend dedupe replaces in place).
msg_id: Optional[str] = None
text_parts: List[str] = []
@@ -127,7 +127,6 @@ async def handle_stream_event(
# Thinking content streams as thinking_delta
# with a "thinking" field (not "text")
think_chunk = delta.get("thinking", "")
thinking.total_chars += len(think_chunk)
await ws_manager.send_to_session(session_id, "agent:stream_delta", {
"session_id": session_id,
"message_id": msg_id,