File tree Expand file tree Collapse file tree 5 files changed +93
-9
lines changed Expand file tree Collapse file tree 5 files changed +93
-9
lines changed Original file line number Diff line number Diff line change 5656 "watch:labextension" : " jupyter labextension watch ."
5757 },
5858 "dependencies" : {
59- "@jupyter/chat" : " ^0.8.1 " ,
59+ "@jupyter/chat" : " ^0.9.0 " ,
6060 "@jupyterlab/application" : " ^4.4.0-alpha.0" ,
6161 "@jupyterlab/apputils" : " ^4.5.0-alpha.0" ,
6262 "@jupyterlab/completer" : " ^4.4.0-alpha.0" ,
Original file line number Diff line number Diff line change @@ -139,9 +139,11 @@ export class ChatHandler extends ChatModel {
139139
140140 let content = '' ;
141141
142+ this . _controller = new AbortController ( ) ;
142143 try {
143144 for await ( const chunk of await this . _providerRegistry . currentChatModel . stream (
144- messages
145+ messages ,
146+ { signal : this . _controller . signal }
145147 ) ) {
146148 content += chunk . content ?? chunk ;
147149 botMsg . body = content ;
@@ -162,6 +164,7 @@ export class ChatHandler extends ChatModel {
162164 return false ;
163165 } finally {
164166 this . updateWriters ( [ ] ) ;
167+ this . _controller = null ;
165168 }
166169 }
167170
@@ -177,12 +180,17 @@ export class ChatHandler extends ChatModel {
177180 super . messageAdded ( message ) ;
178181 }
179182
183+ stopStreaming ( ) : void {
184+ this . _controller ?. abort ( ) ;
185+ }
186+
180187 private _providerRegistry : IAIProviderRegistry ;
181188 private _personaName = 'AI' ;
182189 private _prompt : string ;
183190 private _errorMessage : string = '' ;
184191 private _history : IChatHistory = { messages : [ ] } ;
185192 private _defaultErrorMessage = 'AI provider not configured' ;
193+ private _controller : AbortController | null = null ;
186194}
187195
188196export namespace ChatHandler {
Original file line number Diff line number Diff line change 1+ /*
2+ * Copyright (c) Jupyter Development Team.
3+ * Distributed under the terms of the Modified BSD License.
4+ */
5+
6+ import StopIcon from '@mui/icons-material/Stop' ;
7+ import React from 'react' ;
8+
9+ import { InputToolbarRegistry , TooltippedButton } from '@jupyter/chat' ;
10+
11+ /**
12+ * Properties of the stop button.
13+ */
14+ export interface IStopButtonProps
15+ extends InputToolbarRegistry . IToolbarItemProps {
16+ /**
17+ * The function to stop streaming.
18+ */
19+ stopStreaming : ( ) => void ;
20+ }
21+
22+ /**
23+ * The stop button.
24+ */
25+ export function StopButton ( props : IStopButtonProps ) : JSX . Element {
26+ const tooltip = 'Stop streaming' ;
27+ return (
28+ < TooltippedButton
29+ onClick = { props . stopStreaming }
30+ tooltip = { tooltip }
31+ buttonProps = { {
32+ size : 'small' ,
33+ variant : 'contained' ,
34+ title : tooltip
35+ } }
36+ >
37+ < StopIcon />
38+ </ TooltippedButton >
39+ ) ;
40+ }
41+
42+ /**
43+ * factory returning the toolbar item.
44+ */
45+ export function stopItem (
46+ stopStreaming : ( ) => void
47+ ) : InputToolbarRegistry . IToolbarItem {
48+ return {
49+ element : ( props : InputToolbarRegistry . IToolbarItemProps ) => {
50+ const stopProps : IStopButtonProps = { ...props , stopStreaming } ;
51+ return StopButton ( stopProps ) ;
52+ } ,
53+ position : 50 ,
54+ hidden : true /* hidden by default */
55+ } ;
56+ }
Original file line number Diff line number Diff line change 44 buildErrorWidget ,
55 ChatCommandRegistry ,
66 IActiveCellManager ,
7- IChatCommandRegistry
7+ IChatCommandRegistry ,
8+ InputToolbarRegistry
89} from '@jupyter/chat' ;
910import {
1011 JupyterFrontEnd ,
@@ -28,6 +29,7 @@ import { defaultProviderPlugins } from './default-providers';
2829import { AIProviderRegistry } from './provider' ;
2930import { aiSettingsRenderer , SettingConnector } from './settings' ;
3031import { IAIProviderRegistry } from './tokens' ;
32+ import { stopItem } from './components/stop-button' ;
3133
3234const chatCommandRegistryPlugin : JupyterFrontEndPlugin < IChatCommandRegistry > = {
3335 id : '@jupyterlite/ai:autocompletion-registry' ,
@@ -102,12 +104,30 @@ const chatPlugin: JupyterFrontEndPlugin<void> = {
102104 } ) ;
103105
104106 let chatWidget : ReactWidget | null = null ;
107+
108+ const inputToolbarRegistry = InputToolbarRegistry . defaultToolbarRegistry ( ) ;
109+ const stopButton = stopItem ( ( ) => chatHandler . stopStreaming ( ) ) ;
110+ inputToolbarRegistry . addItem ( 'stop' , stopButton ) ;
111+
112+ chatHandler . writersChanged . connect ( ( _ , users ) => {
113+ if (
114+ users . filter ( user => user . username === chatHandler . personaName ) . length
115+ ) {
116+ inputToolbarRegistry . hide ( 'send' ) ;
117+ inputToolbarRegistry . show ( 'stop' ) ;
118+ } else {
119+ inputToolbarRegistry . hide ( 'stop' ) ;
120+ inputToolbarRegistry . show ( 'send' ) ;
121+ }
122+ } ) ;
123+
105124 try {
106125 chatWidget = buildChatSidebar ( {
107126 model : chatHandler ,
108127 themeManager,
109128 rmRegistry,
110- chatCommandRegistry
129+ chatCommandRegistry,
130+ inputToolbarRegistry
111131 } ) ;
112132 chatWidget . title . caption = 'Jupyterlite AI Chat' ;
113133 } catch ( e ) {
Original file line number Diff line number Diff line change @@ -906,9 +906,9 @@ __metadata:
906906 languageName : node
907907 linkType : hard
908908
909- " @jupyter/chat@npm:^0.8.1 " :
910- version : 0.8.1
911- resolution : " @jupyter/chat@npm:0.8.1 "
909+ " @jupyter/chat@npm:^0.9.0 " :
910+ version : 0.9.0
911+ resolution : " @jupyter/chat@npm:0.9.0 "
912912 dependencies :
913913 " @emotion/react " : ^11.10.5
914914 " @emotion/styled " : ^11.10.5
@@ -930,7 +930,7 @@ __metadata:
930930 clsx : ^2.1.0
931931 react : ^18.2.0
932932 react-dom : ^18.2.0
933- checksum : d4a3635cd419642c62ca462ef9ec5327178bed7f898684e31a193246b081707685ba825ef0a83e3b6618316a7e7ffd68141194759cb1f2b107215cbe33ef5d59
933+ checksum : dee9a9e02ea8a6d25e1caebf4e9bece42c82fa40baa84dc655540bb64a676b4b1890373390c291f35eb1fe8f821d15935ec21fdd0e12063a497e575f4ddbcd78
934934 languageName : node
935935 linkType : hard
936936
@@ -2108,7 +2108,7 @@ __metadata:
21082108 version : 0.0.0-use.local
21092109 resolution : " @jupyterlite/ai@workspace:."
21102110 dependencies :
2111- " @jupyter/chat " : ^0.8.1
2111+ " @jupyter/chat " : ^0.9.0
21122112 " @jupyterlab/application " : ^4.4.0-alpha.0
21132113 " @jupyterlab/apputils " : ^4.5.0-alpha.0
21142114 " @jupyterlab/builder " : ^4.0.0
You can’t perform that action at this time.
0 commit comments