|
31 | 31 | replace_whole_floats_with_ints, |
32 | 32 | ) |
33 | 33 | from reboot.protobuf import as_dict, from_model |
| 34 | +from rebootdev.aio.backoff import Backoff |
34 | 35 |
|
35 | 36 | logger = get_logger(__name__) |
36 | 37 |
|
@@ -233,16 +234,33 @@ async def send_and_receive(): |
233 | 234 | related_request_id=related_request_id, |
234 | 235 | ) |
235 | 236 |
|
236 | | - async def is_visual_studio_code(): |
237 | | - response = await self.ref().per_workflow( |
238 | | - "Check if client is Visual Studio Code", |
239 | | - ).get(context) |
240 | | - assert response.HasField("client_info") |
241 | | - if response.HasField("client_info"): |
242 | | - return response.client_info.name == "Visual Studio Code" |
243 | | - return False |
| 237 | + async def check_is_vscode(): |
| 238 | + backoff = Backoff(max_backoff_seconds=2) |
| 239 | + while True: |
| 240 | + response = await self.ref().always().get( |
| 241 | + context |
| 242 | + ) |
| 243 | + if not response.HasField("client_info"): |
| 244 | + await backoff() |
| 245 | + continue |
| 246 | + # Technically `name` is required but |
| 247 | + # at least the MCP SDK doesn't |
| 248 | + # validate it via Pydantic, but Visual |
| 249 | + # Studio Code always seems to include |
| 250 | + # its name, so if we don't have a name |
| 251 | + # it is not Visual Studio Code. |
| 252 | + if response.client_info.HasField("name"): |
| 253 | + return response.client_info.name == "Visual Studio Code" |
| 254 | + return False |
| 255 | + |
| 256 | + is_vscode = await at_least_once( |
| 257 | + "Check if client is Visual Studio Code", |
| 258 | + context, |
| 259 | + check_is_vscode, |
| 260 | + type=bool, |
| 261 | + ) |
244 | 262 |
|
245 | | - if await is_visual_studio_code(): |
| 263 | + if is_vscode: |
246 | 264 | # For Visual Studio Code, also store the |
247 | 265 | # _outgoing_ message, i.e., event, on the |
248 | 266 | # aggregated stream. |
|
0 commit comments