-
Notifications
You must be signed in to change notification settings - Fork 34
No handling for 4xx response #262
Copy link
Copy link
Open
Labels
Description
Been testing a bit and used all my quota/tokens. Now the response is 402 Payment Required which is not communicated anywhere in the UI. The chat just doesn't reply with anything.
:: [22:33:24.346] --> LSP-copilot conversation/turn (7): {'conversationId': '7639ba5e-da11-4fcb-a8eb-6119adbd14c5', 'message': 'can python decorators use generic type arguments?', 'workDoneToken': 'copilot_chat://10', 'doc': {'source': 'from __future__ import annotations\nfrom .interface import ClientHandlerInterface\nfrom typing import Any, Callable, List, TypeVar, Union\nimport inspect\n\n__all__ = [\n "notification_handler",\n "request_handler",\n "register_decorated_handlers",\n]\n\nT = TypeVar(\'T\')\n# the first argument is always "self"\nNotificationHandler = Callable[[Any, Any], None]\nRequestHandler = Callable[[Any, Any, Callable[[Any], None]], None]\nMessageMethods = Union[str, List[str]]\n\n_HANDLER_MARKS = {\n "notification": "__handle_notification_message_methods",\n "request": "__handle_request_message_methods",\n}\n\nclass ApiWrapper(ApiWrapperInterface):\n def __init__(self, plugin: \'ref[AbstractPlugin]\'):\n self.__plugin = plugin\n\n def __session(self) -> Session | None:\n plugin = self.__plugin()\n return plugin.weaksession() if plugin else None\n\n # --- ApiWrapperInterface -----------------------------------------------------------------------------------------\n\n @override\n def on_notification(self, method: str, handler: ApiNotificationHandler) -> None:\n def handle_notification(weak_handler: WeakMethod[ApiNotificationHandler], params: Any) -> None:\n if handler := weak_handler():\n handler(params)\n\n plugin = self.__plugin()\n if plugin:\n setattr(plugin, method2attr(method), partial(handle_notification, WeakMethod(handler)))\n\n @override\n def on_request(self, method: str, handler: ApiRequestHandler) -> None:\n def send_response(request_id: Any, result: Any) -> None:\n session = self.__session()\n if session:\n session.send_response(Response(request_id, result))\n\n def on_response(weak_handler: WeakMethod[ApiRequestHandler], params: Any, request_id: Any) -> None:\n if handler := weak_handler():\n handler(params, lambda result: send_response(request_id, result))\n\n plugin = self.__plugin()\n if plugin:\n setattr(plugin, method2attr(method), partial(on_response, WeakMethod(handler)))\n\n @override\n def send_notification(self, method: str, params: Any) -> None:\n session = self.__session()\n if session:\n session.send_notification(Notification(method, params))\n\n @override\n def send_request(self, method: str, params: Any, handler: Callable[[Any, bool], None]) -> None:\n session = self.__session()\n if session:\n request: Request[Any, Any] = Request(method, params)\n session.send_request(request, lambda result: handler(result, False), lambda result: handler(result, True))\n else:\n handler(None, True)\n\n\ndef notification_handler(method: str) -> Callable[[NotificationHandler], NotificationHandler]:\n """\n Marks the decorated function as a "notification" message handler.\n\n On server sending the notification, the decorated function will be called with the `params` argument which contains\n the payload.\n """\n\n return _create_handler("notification", notification_methods)\n\n\ndef request_handler(method: str) -> Callable[[RequestHandler], RequestHandler]:\n """\n Marks the decorated function as a "request" message handler.\n\n On server sending the request, the decorated function will be called with two arguments (`params` and `respond`).\n The first argument (`params`) is the payload of the request and the second argument (`respond`) is the function that\n must be used to respond to the request. The `respond` function takes any data that should be sent back to the\n server.\n """\n\n return _create_handler("request", request_methods)\n\n\ndef _create_handler(client_event: str, message_methods: MessageMethods) -> Callable[[T], T]:\n """ Marks the decorated function as a message handler. """\n\n message_methods = [message_methods] if isinstance(message_methods, str) else message_methods\n\n def decorator(func: T) -> T:\n setattr(func, _HANDLER_MARKS[client_event], message_methods)\n return func\n\n return decorator\n\n\ndef register_decorated_handlers(client_handler: ClientHandlerInterface, api: ApiWrapperInterface) -> None:\n """\n Register decorator-style custom message handlers.\n\n This method works as following:\n\n 1. Scan through all methods of `client_handler`.\n 2. If a method is decorated, it will have a "handler mark" attribute which is set by the decorator.\n 3. Register the method with wanted message methods, which are stored in the "handler mark" attribute.\n\n :param client_handler: The instance of the client handler.\n :param api: The API instance for interacting with the server.\n """\n for _, func in inspect.getmembers(client_handler, predicate=inspect.isroutine):\n for client_event, handler_mark in _HANDLER_MARKS.items():\n message_methods: list[str] | None = getattr(func, handler_mark, None)\n if message_methods is None:\n continue\n event_registrator = getattr(api, "on_" + client_event, None)\n if callable(event_registrator):\n for message_method in message_methods:\n event_registrator(message_method, func)\n # it makes no sense that a handler handles both "notification" and "request"\n # so we do early break once we\'ve registered a handler\n break\n', 'tabSize': 4, 'indentSize': 1, 'insertSpaces': True, 'path': '/usr/local/workspace/sublime-packages/LSP/plugin/api_decorator.py', 'uri': 'file:///usr/local/workspace/sublime-packages/LSP/plugin/api_decorator.py', 'relativePath': 'plugin/api_decorator.py', 'languageId': 'python', 'position': {'line': 72, 'character': 0}, 'version': 0}, 'computeSuggestions': True, 'references': [], 'source': 'panel'}
:: [22:33:24.348] <- LSP-copilot $/progress: {'token': 'copilot_chat://10', 'value': {'kind': 'begin', 'title': 'Conversation 7639ba5e-da11-4fcb-a8eb-6119adbd14c5 Turn be587115-c5ff-405d-a7f4-8039d66dd8df', 'conversationId': '7639ba5e-da11-4fcb-a8eb-6119adbd14c5', 'turnId': 'be587115-c5ff-405d-a7f4-8039d66dd8df'}}
:: [22:33:24.373] <- LSP-copilot window/logMessage: {'type': 3, 'message': '[agentPrompt] Reusing cached global context from first turn for conversation/turn 7639ba5e-da11-4fcb-a8eb-6119adbd14c5/be587115-c5ff-405d-a7f4-8039d66dd8df'}
:: [22:33:24.501] <- LSP-copilot window/logMessage: {'type': 3, 'message': '[fetchChat] Request a12f47a1-2ee1-45a4-9d4f-1889f91a849a at <https://api.individual.githubcopilot.com/chat/completions> finished with 402 status after 140.4438749999972ms'}
:: [22:33:24.501] <- LSP-copilot window/logMessage: {'type': 1, 'message': '[toolCallingLoop] Fetch failed: {\n type: \'failed\',\n reason: "You\'ve reached your monthly chat messages quota. Upgrade to Copilot Pro (30-day free trial) or wait for your allowance to renew.",\n requestId: \'a12f47a1-2ee1-45a4-9d4f-1889f91a849a\',\n code: 402\n}'}
:: [22:33:24.501] <- LSP-copilot $/progress: {'token': 'copilot_chat://10', 'value': {'kind': 'end', 'conversationId': '7639ba5e-da11-4fcb-a8eb-6119adbd14c5', 'turnId': 'be587115-c5ff-405d-a7f4-8039d66dd8df', 'error': {'message': "You've reached your monthly chat messages quota. Upgrade to Copilot Pro (30-day free trial) or wait for your allowance to renew. Request ID: a12f47a1-2ee1-45a4-9d4f-1889f91a849a", 'code': 402}}}
:: [22:33:24.511] <<< LSP-copilot (7) (duration: 165ms): {'conversationId': '7639ba5e-da11-4fcb-a8eb-6119adbd14c5', 'turnId': 'be587115-c5ff-405d-a7f4-8039d66dd8df', 'modelName': 'GPT-4o', 'billingMultiplier': 1}
Reactions are currently unavailable