diff --git a/src/app/components/chat/chat.component.html b/src/app/components/chat/chat.component.html
index 7eb9b42a..c5f9ab90 100644
--- a/src/app/components/chat/chat.component.html
+++ b/src/app/components/chat/chat.component.html
@@ -348,7 +348,17 @@
}"
>
@if (message.isLoading) {
-
+
+
+
+
}
@if (message.attachments) {
diff --git a/src/app/components/chat/chat.component.scss b/src/app/components/chat/chat.component.scss
index 163dee3b..278f82cd 100644
--- a/src/app/components/chat/chat.component.scss
+++ b/src/app/components/chat/chat.component.scss
@@ -85,11 +85,31 @@
background-color: #131314;
}
+.loading-container {
+ display: flex;
+ align-items: center;
+ width: 150px;
+ justify-content: space-between;
+}
+
.loading-bar {
width: 100px;
margin: 15px;
}
+.stop-button {
+ width: 30px;
+ height: 30px;
+ background-color: #303030;
+
+ .mat-icon {
+ font-size: 18px;
+ color: white;
+ margin-left: -20px;
+ margin-top: -10px;
+ }
+}
+
.chat-messages {
flex-grow: 1;
overflow-y: auto;
diff --git a/src/app/components/chat/chat.component.ts b/src/app/components/chat/chat.component.ts
index e82008a0..064a8066 100644
--- a/src/app/components/chat/chat.component.ts
+++ b/src/app/components/chat/chat.component.ts
@@ -1389,6 +1389,10 @@ export class ChatComponent implements OnInit, AfterViewInit, OnDestroy {
this.currentSessionState = session.state;
}
+ stop() {
+ this.agentService.stopSse();
+ }
+
onNewSessionClick() {
this.createSession();
this.eventData.clear();
diff --git a/src/app/core/services/agent.service.ts b/src/app/core/services/agent.service.ts
index 0d0791a7..2cf672af 100644
--- a/src/app/core/services/agent.service.ts
+++ b/src/app/core/services/agent.service.ts
@@ -31,6 +31,7 @@ export class AgentService {
private _currentApp = new BehaviorSubject('');
currentApp = this._currentApp.asObservable();
private isLoading = new BehaviorSubject(false);
+ private abortController: AbortController | null = null;
constructor(
private http: HttpClient,
@@ -49,9 +50,19 @@ export class AgentService {
return this.isLoading;
}
+ stopSse() {
+ if (this.abortController) {
+ this.abortController.abort();
+ this.abortController = null;
+ }
+ }
+
runSse(req: AgentRunRequest) {
const url = this.apiServerDomain + `/run_sse`;
this.isLoading.next(true);
+ this.abortController = new AbortController();
+ const signal = this.abortController.signal;
+
return new Observable((observer) => {
const self = this;
fetch(url, {
@@ -61,6 +72,7 @@ export class AgentService {
'Accept': 'text/event-stream',
},
body: JSON.stringify(req),
+ signal,
})
.then((response) => {
const reader = response.body?.getReader();
@@ -97,13 +109,20 @@ export class AgentService {
})
.catch((err) => {
self.zone.run(() => observer.error(err));
+ this.isLoading.next(false);
});
};
read();
})
.catch((err) => {
- self.zone.run(() => observer.error(err));
+ if (err.name === 'AbortError') {
+ // Fetch was aborted
+ this.isLoading.next(false);
+ observer.complete();
+ } else {
+ self.zone.run(() => observer.error(err));
+ }
});
});
}