Files
hermes-agent/tools/connectors/dispatch.py
Siddharth Balyan 8c86e112f7 feat(connectors): connector results name the account they ran under
The gateway now reports the alias of the account each call used. Keep it
through the wire model, the result dict, both dispatch paths and the
model-facing entry, and show the chosen alias in the tool label.
2026-10-11 17:21:07 +05:30

63 lines
3.0 KiB
Python

"""Route connector calls through the normal dispatch policy pipeline."""
import json
from dataclasses import asdict
from tools.registry import tool_error
from tools.connectors.gateway.config import MAX_CALLS_PER_DISPATCH
from tools.connectors.gateway.merge import assemble_results, fill_remote_failure, partition_calls
def dispatch_connector_call(name, arguments, tool_call_id):
from tools.connectors.gateway.bridge import run_remote
partition = partition_calls([{"name": name, "arguments": arguments}])
entries = run_remote(partition.remote, tool_call_id, availability=None, client_factory=None)
entry = entries[0]
return json.dumps({key: value for key, value in entry.items() if key in {"response", "error", "account"}},
ensure_ascii=False)
def dispatch_connector_batch(calls, ids, *, user_task, enabled_tools,
middleware_trace, enabled_toolsets, disabled_toolsets):
from model_tools import handle_function_call
from tools.interrupt import is_interrupted
if len(calls) > MAX_CALLS_PER_DISPATCH:
return tool_error(f"too many calls: {len(calls)} > max {MAX_CALLS_PER_DISPATCH}. "
"Retry with fewer calls per batch.")
partition = partition_calls(calls)
if partition.local:
from tools.tool_search_validation import local_batch_error
return tool_error(local_batch_error(calls))
entries = list(partition.errors)
for offset, plan in enumerate(partition.remote):
if is_interrupted():
# Check before every entry so /stop prevents unstarted remote side effects.
entries.extend(fill_remote_failure(
partition.remote[offset:], "Stopped by the user before this call was made.",
code="INTERRUPTED"))
break
# Each entry must run its own policy and middleware.
payload = handle_function_call(
plan.name, plan.arguments, **asdict(ids), user_task=user_task,
enabled_tools=enabled_tools, tool_request_middleware_trace=list(middleware_trace),
skip_pre_tool_call_hook=False, skip_tool_request_middleware=False,
skip_tool_execution_middleware=False,
enabled_toolsets=enabled_toolsets, disabled_toolsets=disabled_toolsets,
)
try:
value = json.loads(payload) if isinstance(payload, str) else payload
except ValueError:
value = payload
entry = {"index": plan.position, "name": plan.name}
if isinstance(value, dict) and "error" in value:
error = value["error"]
entry["error"] = error if isinstance(error, dict) else {"code": "TOOL_ERROR", "message": str(error)}
else:
entry["response"] = value.get("response", value) if isinstance(value, dict) else value
if isinstance(value, dict) and value.get("account"):
entry["account"] = value["account"]
entries.append(entry)
return json.dumps(assemble_results(len(calls), entries), ensure_ascii=False)