Skip to content

Commit 8784c56

Browse files
committed
error animation in cells for jupyter-ai
Co-authored-by: Andrew Fulton [email protected]
1 parent c07c182 commit 8784c56

File tree

3 files changed

+39
-4
lines changed

3 files changed

+39
-4
lines changed

packages/jupyter-ai-magics/jupyter_ai_magics/models/completion.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,15 @@ class InlineCompletionRequest(BaseModel):
2828
# previous cells and following cells can be used to learn the wider context
2929
cell_id: Optional[str]
3030

31+
class InlineCompletionError(BaseModel):
32+
message: str
3133

3234
class InlineCompletionItem(BaseModel):
3335
"""The inline completion suggestion to be displayed on the frontend.
3436
3537
See JupyterLab `InlineCompletionItem` documentation for the details.
3638
"""
37-
39+
error: Optional[InlineCompletionError]
3840
insertText: str
3941
filterText: Optional[str]
4042
isIncomplete: Optional[bool]

packages/jupyter-ai/jupyter_ai/completions/handlers/base.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ async def on_message(self, message):
118118
async def handle_request_and_catch():
119119
try:
120120
await handle_request
121+
# raise Exception("An error occured!")
121122
except Exception as e:
122123
await self.handle_exc(e, request)
123124

@@ -129,14 +130,15 @@ async def handle_exc(self, e: Exception, request: InlineCompletionRequest):
129130
`handle_stream_request()`. This base class provides a default
130131
implementation, which may be overridden by subclasses.
131132
"""
133+
title = e.args[0] if e.args else "Exception"
132134
error = CompletionError(
133135
type=e.__class__.__name__,
134-
title=e.args[0] if e.args else "Exception",
136+
title=title,
135137
traceback=traceback.format_exc(),
136138
)
137139
self.reply(
138140
InlineCompletionReply(
139-
list=InlineCompletionList(items=[]),
141+
list=InlineCompletionList(items=[{"error":{"message":title},"insertText":""}]),
140142
error=error,
141143
reply_to=request.number,
142144
)

packages/jupyter-ai/jupyter_ai/tests/completions/test_handlers.py

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,16 @@
11
import json
22
from types import SimpleNamespace
33
from typing import Union
4+
import traceback
45

56
import pytest
67
from jupyter_ai.completions.handlers.default import DefaultInlineCompletionHandler
78
from jupyter_ai.completions.models import (
89
InlineCompletionReply,
910
InlineCompletionRequest,
1011
InlineCompletionStreamChunk,
12+
CompletionError,
13+
InlineCompletionList,
1114
)
1215
from jupyter_ai_magics import BaseProvider
1316
from langchain_community.llms import FakeListLLM
@@ -52,7 +55,19 @@ def reply(
5255

5356
async def handle_exc(self, e: Exception, _request: InlineCompletionRequest):
5457
# raise all exceptions during testing rather
55-
raise e
58+
title = e.args[0] if e.args else "Exception"
59+
error = CompletionError(
60+
type=e.__class__.__name__,
61+
title=title,
62+
traceback=traceback.format_exc(),
63+
)
64+
self.reply(
65+
InlineCompletionReply(
66+
list=InlineCompletionList(items=[{"error":{"message":title},"insertText":""}]),
67+
error=error,
68+
reply_to=_request.number,
69+
)
70+
)
5671

5772

5873
@fixture
@@ -191,3 +206,19 @@ async def test_handle_stream_request():
191206
assert third.type == "stream"
192207
assert third.response.insertText == "test"
193208
assert third.done is True
209+
210+
async def test_handle_request_with_error(inline_handler):
211+
inline_handler = MockCompletionHandler(
212+
lm_provider=MockProvider,
213+
lm_provider_params={
214+
"model_id": "model",
215+
"responses": ["test"],
216+
},
217+
)
218+
dummy_request = InlineCompletionRequest(
219+
number=1, prefix="", suffix="", mime="", stream=True
220+
)
221+
await inline_handler.on_message(json.dumps(dict(dummy_request)))
222+
await inline_handler.tasks[0]
223+
error_message = inline_handler.messages[-1].dict().get('list', {}).get('items', [{}])[0].get('error', {}).get('message', None)
224+
assert error_message is not None

0 commit comments

Comments
 (0)