Handle broadcast request events by executing local handlers and responding via RPC. Implements the protocol v3 broadcast model where tool calls and permission requests are broadcast as session events to all clients.
(self, event: SessionEvent)
| 1753 | ) |
| 1754 | |
| 1755 | def _handle_broadcast_event(self, event: SessionEvent) -> None: |
| 1756 | """Handle broadcast request events by executing local handlers and responding via RPC. |
| 1757 | |
| 1758 | Implements the protocol v3 broadcast model where tool calls and permission requests |
| 1759 | are broadcast as session events to all clients. |
| 1760 | """ |
| 1761 | match event.data: |
| 1762 | case ExternalToolRequestedData() as data: |
| 1763 | request_id = data.request_id |
| 1764 | tool_name = data.tool_name |
| 1765 | if not request_id or not tool_name: |
| 1766 | return |
| 1767 | |
| 1768 | handler = self._get_tool_handler(tool_name) |
| 1769 | if not handler: |
| 1770 | return # This client doesn't handle this tool; another client will. |
| 1771 | |
| 1772 | tool_call_id = data.tool_call_id or "" |
| 1773 | arguments = data.arguments |
| 1774 | tp = getattr(data, "traceparent", None) |
| 1775 | ts = getattr(data, "tracestate", None) |
| 1776 | asyncio.ensure_future( |
| 1777 | self._execute_tool_and_respond( |
| 1778 | request_id, tool_name, tool_call_id, arguments, handler, tp, ts |
| 1779 | ) |
| 1780 | ) |
| 1781 | |
| 1782 | case PermissionRequestedData() as data: |
| 1783 | if logger.isEnabledFor(logging.DEBUG): |
| 1784 | logger.debug( |
| 1785 | "CopilotSession._dispatch_event permission request received", |
| 1786 | extra={ |
| 1787 | "session_id": self.session_id, |
| 1788 | "event_type": event.type.value, |
| 1789 | }, |
| 1790 | ) |
| 1791 | request_id = data.request_id |
| 1792 | permission_request = data.permission_request |
| 1793 | if not request_id or not permission_request: |
| 1794 | return |
| 1795 | |
| 1796 | resolved_by_hook = getattr(data, "resolved_by_hook", None) |
| 1797 | if resolved_by_hook: |
| 1798 | return # Already resolved by a permissionRequest hook; no client action needed. |
| 1799 | |
| 1800 | with self._permission_handler_lock: |
| 1801 | perm_handler = self._permission_handler |
| 1802 | if not perm_handler: |
| 1803 | return # This client doesn't handle permissions; another client will. |
| 1804 | |
| 1805 | asyncio.ensure_future( |
| 1806 | self._execute_permission_and_respond( |
| 1807 | request_id, permission_request, perm_handler |
| 1808 | ) |
| 1809 | ) |
| 1810 | |
| 1811 | case McpOauthRequiredData() as data: |
| 1812 | with self._mcp_auth_handler_lock: |
no test coverage detected