mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-11-06 05:17:15 +00:00
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.
This commit is contained in:
1 parent
7adb97f22a
commit
8c86e112f7
5 files changed
+25
-8
No files matched your search
@@ -14,7 +14,7 @@ def dispatch_connector_call(name, arguments, tool_call_id):
|
||||
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"}},
|
||||
return json.dumps({key: value for key, value in entry.items() if key in {"response", "error", "account"}},
|
||||
ensure_ascii=False)
|
||||
|
||||
|
||||
@@ -56,5 +56,7 @@ def dispatch_connector_batch(calls, ids, *, user_task, enabled_tools,
|
||||
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)
|
||||
@@ -279,7 +279,10 @@ def _result_dict(result: wire.ConnectorExecuteResult) -> dict[str, Any]:
|
||||
error["connection_id"] = result.error.connection_id
|
||||
if result.error.hint:
|
||||
error["hint"] = result.error.hint
|
||||
return {"data": result.data, "error": error}
|
||||
entry = {"data": result.data, "error": error}
|
||||
if result.account:
|
||||
entry["account"] = result.account
|
||||
return entry
|
||||
|
||||
|
||||
def _safe_json(response: Any) -> Any:
|
||||
|
||||
@@ -82,9 +82,10 @@ def partition_calls(calls: Sequence[Any]) -> Partition:
|
||||
def render_remote_entry(planned: PlannedCall, remote: Mapping[str, Any]) -> dict[str, Any]:
|
||||
"""Use the shared CONNECTION_REQUIRED shape so links render consistently."""
|
||||
error = remote.get("error") if isinstance(remote, Mapping) else None
|
||||
account = _opt_str(remote.get("account")) if isinstance(remote, Mapping) else None
|
||||
if not isinstance(error, Mapping):
|
||||
data = remote.get("data") if isinstance(remote, Mapping) else None
|
||||
return {"index": planned.position, "name": planned.name, "response": data}
|
||||
return _with_account({"index": planned.position, "name": planned.name, "response": data}, account)
|
||||
|
||||
code = str(error.get("code") or "PROVIDER_ERROR")
|
||||
message = str(error.get("message") or "The gateway reported an error.")
|
||||
@@ -104,7 +105,13 @@ def render_remote_entry(planned: PlannedCall, remote: Mapping[str, Any]) -> dict
|
||||
hint = _opt_str(error.get("hint"))
|
||||
if hint:
|
||||
payload["hint"] = hint
|
||||
return {"index": planned.position, "name": planned.name, "error": payload}
|
||||
return _with_account({"index": planned.position, "name": planned.name, "error": payload}, account)
|
||||
|
||||
|
||||
def _with_account(entry: dict[str, Any], account: Optional[str]) -> dict[str, Any]:
|
||||
if account:
|
||||
entry["account"] = account
|
||||
return entry
|
||||
|
||||
|
||||
def splice_remote_results(
|
||||
|
||||
@@ -106,8 +106,8 @@ class ConnectorExecuteCall(_Wire):
|
||||
connector: str
|
||||
tool: str
|
||||
arguments: dict[str, Any] = Field(default_factory=dict)
|
||||
# On the wire for the multi-account switch; never sent by hermes today, because the vendor answers
|
||||
# 400 to any value while multi-account is off (contract probe F2).
|
||||
# Never sent by hermes: the model picks an account with the ``connector_alias`` argument, which
|
||||
# the gateway strips and resolves itself.
|
||||
account: Optional[str] = None
|
||||
|
||||
|
||||
@@ -125,6 +125,8 @@ class ConnectorExecuteResult(_Wire):
|
||||
tool: str = ""
|
||||
data: Any = None
|
||||
error: Optional[ConnectorToolError] = None
|
||||
# The alias of the account the call ran under; null when that account has no alias.
|
||||
account: Optional[str] = None
|
||||
|
||||
|
||||
class ConnectorExecuteResponse(_Wire):
|
||||
|
||||
@@ -116,8 +116,11 @@ def label_for_tool_name(name: str, arguments: Any = None) -> Optional[ToolLabel]
|
||||
return None
|
||||
connector = parse_connector_name(name)
|
||||
if connector is not None:
|
||||
return ToolLabel(kind="connector", app=app_title(connector.connector),
|
||||
action=_action_phrase(connector.tool, connector.connector),
|
||||
action = _action_phrase(connector.tool, connector.connector)
|
||||
alias = arguments.get("connector_alias") if isinstance(arguments, dict) else None
|
||||
if isinstance(alias, str) and alias.strip():
|
||||
action = f"{action} ({alias.strip()})"
|
||||
return ToolLabel(kind="connector", app=app_title(connector.connector), action=action,
|
||||
emoji=CONNECTOR_EMOJI, name=name, preview=_arg_preview(name, arguments))
|
||||
if name.startswith(MCP_TOOL_NAME_PREFIX):
|
||||
server, _, tool = name[len(MCP_TOOL_NAME_PREFIX):].partition("__")
|
||||
|
||||
Reference in new issue
Block a user