mirror of
https://github.com/paperless-ngx/paperless-ngx.git
synced 2026-10-12 02:57:12 +00:00
Show still thinking for slow responses
This commit is contained in:
3 files changed
+36
-1
No files matched your search
@@ -12,7 +12,11 @@
|
||||
@if (message.isStreaming && !message.content) {
|
||||
<div class="d-flex align-items-center text-muted">
|
||||
<div class="spinner-border spinner-border-sm me-2" role="status"></div>
|
||||
<ng-container i18n>Thinking...</ng-container>
|
||||
@if (slowResponse()) {
|
||||
<ng-container i18n>Still thinking...</ng-container>
|
||||
} @else {
|
||||
<ng-container i18n>Thinking...</ng-container>
|
||||
}
|
||||
</div>
|
||||
} @else if (message.role === 'assistant') {
|
||||
<div class="chat-markdown text-break text-wrap" [innerHTML]="message.content | markdown"></div>
|
||||
|
||||
@@ -170,6 +170,21 @@ describe('ChatComponent', () => {
|
||||
expect(component.loading()).toBe(false)
|
||||
})
|
||||
|
||||
it('should show a slow response message while waiting', () => {
|
||||
component.input.set('Hello')
|
||||
component.sendMessage()
|
||||
fixture.detectChanges()
|
||||
const messagesEl = fixture.nativeElement.querySelector('.chat-messages')
|
||||
expect(messagesEl.textContent).not.toContain('Still thinking...')
|
||||
|
||||
jest.advanceTimersByTime(8000)
|
||||
fixture.detectChanges()
|
||||
expect(messagesEl.textContent).toContain('Still thinking...')
|
||||
|
||||
mockStream$.next('Hi')
|
||||
expect(component.slowResponse()).toBe(false)
|
||||
})
|
||||
|
||||
it('should enqueue typewriter chunks correctly', () => {
|
||||
const message = { content: '', role: 'assistant', isStreaming: true }
|
||||
component.enqueueTypewriter(null, message as any) // coverage for null
|
||||
|
||||
@@ -18,6 +18,8 @@ import {
|
||||
parseChatResponse,
|
||||
} from 'src/app/services/chat.service'
|
||||
|
||||
const SLOW_RESPONSE_DELAY_MS = 8000
|
||||
|
||||
@Component({
|
||||
selector: 'pngx-chat',
|
||||
imports: [
|
||||
@@ -36,6 +38,7 @@ export class ChatComponent implements OnInit {
|
||||
readonly loading = signal(false)
|
||||
readonly input = signal('')
|
||||
readonly documentId = signal<number>(undefined)
|
||||
readonly slowResponse = signal(false)
|
||||
|
||||
private chatService: ChatService = inject(ChatService)
|
||||
private router: Router = inject(Router)
|
||||
@@ -45,6 +48,7 @@ export class ChatComponent implements OnInit {
|
||||
|
||||
private typewriterBuffer: string[] = []
|
||||
private typewriterActive = false
|
||||
private slowResponseTimeout: ReturnType<typeof setTimeout>
|
||||
|
||||
public get placeholder(): string {
|
||||
return this.documentId()
|
||||
@@ -83,11 +87,16 @@ export class ChatComponent implements OnInit {
|
||||
}
|
||||
this.messages.update((messages) => [...messages, assistantMessage])
|
||||
this.loading.set(true)
|
||||
this.slowResponseTimeout = setTimeout(
|
||||
() => this.slowResponse.set(true),
|
||||
SLOW_RESPONSE_DELAY_MS
|
||||
)
|
||||
|
||||
let lastVisibleContent = ''
|
||||
|
||||
this.chatService.streamChat(this.documentId(), this.input()).subscribe({
|
||||
next: (chunk) => {
|
||||
this.clearSlowResponse()
|
||||
const nextResponse = parseChatResponse(chunk)
|
||||
|
||||
if (nextResponse.content.length < lastVisibleContent.length) {
|
||||
@@ -105,12 +114,14 @@ export class ChatComponent implements OnInit {
|
||||
this.notifyMessagesChanged()
|
||||
},
|
||||
error: () => {
|
||||
this.clearSlowResponse()
|
||||
assistantMessage.content += '\n\n⚠️ Error receiving response.'
|
||||
assistantMessage.isStreaming = false
|
||||
this.notifyMessagesChanged()
|
||||
this.loading.set(false)
|
||||
},
|
||||
complete: () => {
|
||||
this.clearSlowResponse()
|
||||
assistantMessage.isStreaming = false
|
||||
this.notifyMessagesChanged()
|
||||
this.loading.set(false)
|
||||
@@ -121,6 +132,11 @@ export class ChatComponent implements OnInit {
|
||||
this.input.set('')
|
||||
}
|
||||
|
||||
private clearSlowResponse(): void {
|
||||
clearTimeout(this.slowResponseTimeout)
|
||||
this.slowResponse.set(false)
|
||||
}
|
||||
|
||||
private resetTypewriter(message: ChatMessage, content: string): void {
|
||||
this.typewriterBuffer = []
|
||||
this.typewriterActive = false
|
||||
|
||||
Reference in new issue
Block a user