Associate connector hello metadata with chat context
Store remote tool metadata through a dedicated hello path, bind a declared context id to the websocket SID, and return acknowledged remote tool state so clients can verify gated tools such as code_execution_remote are visible to the active chat.
Alessandro committed
May 7, 2026 at 03:47 UTC
bb86e5a7a9ba220c32bb00d52fc83fd1f70ddfa8
1 file changed
+54
-16
plugins/_a0_connector/api/ws_connector.py
+54
-16
@@ -15,10 +15,13 @@ from plugins._a0_connector.helpers.ws_runtime import (
15
clear_sid_computer_use_metadata,
16
clear_sid_remote_exec_metadata,
17
clear_sid_remote_file_metadata,
18
+ computer_use_metadata_for_sid,
19
fail_pending_computer_use_ops_for_sid,
19
- fail_pending_file_ops_for_sid,
20
fail_pending_exec_ops_for_sid,
21
+ fail_pending_file_ops_for_sid,
22
register_sid,
23
+ remote_exec_metadata_for_sid,
24
+ remote_file_metadata_for_sid,
25
resolve_pending_computer_use_op,
26
resolve_pending_exec_op,
27
resolve_pending_file_op,
@@ -96,25 +99,13 @@ class WsConnector(WsHandler):
99
sid: str,
100
) -> dict[str, Any] | WsResult | None:
101
if event == "connector_hello":
99
- computer_use = data.get("computer_use")
100
- remote_files = data.get("remote_files")
101
- remote_exec = data.get("remote_exec")
102
- if isinstance(computer_use, dict):
103
- store_sid_computer_use_metadata(sid, computer_use)
104
- else:
105
- clear_sid_computer_use_metadata(sid)
106
- if isinstance(remote_files, dict):
107
- store_sid_remote_file_metadata(sid, remote_files)
108
- else:
109
- clear_sid_remote_file_metadata(sid)
110
- if isinstance(remote_exec, dict):
111
- store_sid_remote_exec_metadata(sid, remote_exec)
112
- else:
113
- clear_sid_remote_exec_metadata(sid)
102
+ self._store_remote_tool_metadata(data, sid)
103
+ self._associate_declared_context(data, sid)
104
return {
105
"protocol": PROTOCOL_VERSION,
106
"features": WS_FEATURES,
107
"exec_config": build_exec_config(),
108
+ "remote_tools": self._remote_tool_state(sid),
109
}
110
111
if event == "connector_subscribe_context":
@@ -147,6 +138,53 @@ class WsConnector(WsHandler):
138
139
return None
140
141
+ def _store_remote_tool_metadata(self, data: dict[str, Any], sid: str) -> None:
142
+ computer_use = data.get("computer_use")
143
+ remote_files = data.get("remote_files")
144
+ remote_exec = data.get("remote_exec")
145
+ if isinstance(computer_use, dict):
146
+ store_sid_computer_use_metadata(sid, computer_use)
147
+ else:
148
+ clear_sid_computer_use_metadata(sid)
149
+ if isinstance(remote_files, dict):
150
+ store_sid_remote_file_metadata(sid, remote_files)
151
+ else:
152
+ clear_sid_remote_file_metadata(sid)
153
+ if isinstance(remote_exec, dict):
154
+ store_sid_remote_exec_metadata(sid, remote_exec)
155
+ else:
156
+ clear_sid_remote_exec_metadata(sid)
157
+
158
+ def _associate_declared_context(self, data: dict[str, Any], sid: str) -> str:
159
+ context_id = str(data.get("context_id", "") or "").strip()
160
+ if not context_id:
161
+ return ""
162
+
163
+ try:
164
+ from agent import AgentContext
165
+
166
+ if AgentContext.get(context_id) is None:
167
+ return ""
168
+ except Exception:
169
+ return ""
170
+
171
+ subscribe_sid_to_context(sid, context_id)
172
+ return context_id
173
+
174
+ def _remote_tool_state(self, sid: str) -> dict[str, Any]:
175
+ computer_use = computer_use_metadata_for_sid(sid) or {}
176
+ remote_files = remote_file_metadata_for_sid(sid) or {}
177
+ remote_exec = remote_exec_metadata_for_sid(sid) or {}
178
+ return {
179
+ "contexts": sorted(subscribed_contexts_for_sid(sid)),
180
+ "computer_use": bool(
181
+ computer_use.get("supported") and computer_use.get("enabled")
182
+ ),
183
+ "remote_files": bool(remote_files.get("enabled", False)),
184
+ "remote_file_writes": bool(remote_files.get("write_enabled", False)),
185
+ "remote_exec": bool(remote_exec.get("enabled", False)),
186
+ }
187
+
188
async def _handle_subscribe_context(
189
self,
190
data: dict[str, Any],