feat(frontend): add per-sub-question types and stream state management
Add SubQuestionSources interface for grouped per-sub-question sources. Convert QueryStreamEvent from flat interface to discriminated union with 7 variants including generating_subquestion and completed with sub_question_sources. Add subQuestionSources to QueryStreamState. Update completed event handler to populate subQuestionSources. Make sub_question_sources optional for backward compatibility with old SSE format. Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
parent
3f50f81bfe
commit
098368bb42
|
|
@ -1,7 +1,7 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { QueryClient, QueryClientProvider, useMutation, useQuery, useQueryClient } from '@tanstack/react-query'
|
import { QueryClient, QueryClientProvider, useMutation, useQuery, useQueryClient } from '@tanstack/react-query'
|
||||||
import { queryDocument, queryDocumentStream, ingestDocument, listDocuments, listChunks, deleteDocument, deleteChunk, listPromptProfiles, getPromptProfile, activatePromptProfile, updatePrompt, updateAllPrompts, resetPrompts, listQueryHistory, getQueryHistoryDetail, deleteQueryHistory, clearQueryHistory, getHistoryStats } from './api'
|
import { queryDocument, queryDocumentStream, ingestDocument, listDocuments, listChunks, deleteDocument, deleteChunk, listPromptProfiles, getPromptProfile, activatePromptProfile, updatePrompt, updateAllPrompts, resetPrompts, listQueryHistory, getQueryHistoryDetail, deleteQueryHistory, clearQueryHistory, getHistoryStats } from './api'
|
||||||
import type { QueryRequest, QueryResponse, QueryStreamEvent, SourceMetadata, IngestResponse, DocumentListResponse, ChunkInfo, DeleteResponse, PromptProfileListResponse, PromptSetResponse, PromptUpdateRequest, PromptBatchUpdateRequest, PromptActivateResponse, PromptStatusResponse, QueryHistoryList, QueryHistoryDetail, HistoryStats, HistoryDeleteResponse } from '../types'
|
import type { QueryRequest, QueryResponse, QueryStreamEvent, SourceMetadata, SubQuestionSources, IngestResponse, DocumentListResponse, ChunkInfo, DeleteResponse, PromptProfileListResponse, PromptSetResponse, PromptUpdateRequest, PromptBatchUpdateRequest, PromptActivateResponse, PromptStatusResponse, QueryHistoryList, QueryHistoryDetail, HistoryStats, HistoryDeleteResponse } from '../types'
|
||||||
import { useState, useCallback, useRef } from 'react'
|
import { useState, useCallback, useRef } from 'react'
|
||||||
|
|
||||||
export const queryClient = new QueryClient()
|
export const queryClient = new QueryClient()
|
||||||
|
|
@ -16,6 +16,7 @@ export interface QueryStreamState {
|
||||||
extractedQuestions: string[] | null
|
extractedQuestions: string[] | null
|
||||||
answer: string | null
|
answer: string | null
|
||||||
sources: SourceMetadata[] | null
|
sources: SourceMetadata[] | null
|
||||||
|
subQuestionSources: SubQuestionSources[] | null
|
||||||
phase: 'idle' | 'decomposing' | 'retrieving' | 'filtering' | 'generating' | 'completed' | 'error'
|
phase: 'idle' | 'decomposing' | 'retrieving' | 'filtering' | 'generating' | 'completed' | 'error'
|
||||||
error: Error | null
|
error: Error | null
|
||||||
}
|
}
|
||||||
|
|
@ -25,6 +26,7 @@ export const useQueryDocumentStream = () => {
|
||||||
extractedQuestions: null,
|
extractedQuestions: null,
|
||||||
answer: null,
|
answer: null,
|
||||||
sources: null,
|
sources: null,
|
||||||
|
subQuestionSources: null,
|
||||||
phase: 'idle',
|
phase: 'idle',
|
||||||
error: null,
|
error: null,
|
||||||
})
|
})
|
||||||
|
|
@ -35,6 +37,7 @@ export const useQueryDocumentStream = () => {
|
||||||
extractedQuestions: null,
|
extractedQuestions: null,
|
||||||
answer: null,
|
answer: null,
|
||||||
sources: null,
|
sources: null,
|
||||||
|
subQuestionSources: null,
|
||||||
phase: 'decomposing',
|
phase: 'decomposing',
|
||||||
error: null,
|
error: null,
|
||||||
})
|
})
|
||||||
|
|
@ -60,11 +63,15 @@ export const useQueryDocumentStream = () => {
|
||||||
case 'generating':
|
case 'generating':
|
||||||
setState(prev => ({ ...prev, phase: 'generating' }))
|
setState(prev => ({ ...prev, phase: 'generating' }))
|
||||||
break
|
break
|
||||||
|
case 'generating_subquestion':
|
||||||
|
setState(prev => ({ ...prev, phase: 'generating' }))
|
||||||
|
break
|
||||||
case 'completed':
|
case 'completed':
|
||||||
setState(prev => ({
|
setState(prev => ({
|
||||||
...prev,
|
...prev,
|
||||||
answer: event.answer ?? null,
|
answer: event.answer ?? null,
|
||||||
sources: event.sources ?? null,
|
sources: event.sources ?? null,
|
||||||
|
subQuestionSources: event.sub_question_sources ?? null,
|
||||||
phase: 'completed',
|
phase: 'completed',
|
||||||
}))
|
}))
|
||||||
break
|
break
|
||||||
|
|
@ -96,6 +103,7 @@ export const useQueryDocumentStream = () => {
|
||||||
extractedQuestions: null,
|
extractedQuestions: null,
|
||||||
answer: null,
|
answer: null,
|
||||||
sources: null,
|
sources: null,
|
||||||
|
subQuestionSources: null,
|
||||||
phase: 'idle',
|
phase: 'idle',
|
||||||
error: null,
|
error: null,
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,12 @@ export interface SourceMetadata {
|
||||||
chunk_file_path: string | null
|
chunk_file_path: string | null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface SubQuestionSources {
|
||||||
|
sub_question_index: number
|
||||||
|
sub_question_text: string
|
||||||
|
sources: SourceMetadata[]
|
||||||
|
}
|
||||||
|
|
||||||
export interface QueryRequest {
|
export interface QueryRequest {
|
||||||
question: string
|
question: string
|
||||||
}
|
}
|
||||||
|
|
@ -14,16 +20,18 @@ export interface QueryRequest {
|
||||||
export interface QueryResponse {
|
export interface QueryResponse {
|
||||||
extracted_questions: string[]
|
extracted_questions: string[]
|
||||||
answer: string
|
answer: string
|
||||||
|
sub_question_sources?: SubQuestionSources[]
|
||||||
sources: SourceMetadata[]
|
sources: SourceMetadata[]
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface QueryStreamEvent {
|
export type QueryStreamEvent =
|
||||||
phase: 'decomposed' | 'retrieving' | 'filtering' | 'generating' | 'completed' | 'error'
|
| { phase: 'decomposed'; extracted_questions: string[] }
|
||||||
extracted_questions?: string[]
|
| { phase: 'retrieving' }
|
||||||
answer?: string
|
| { phase: 'filtering' }
|
||||||
sources?: SourceMetadata[]
|
| { phase: 'generating' }
|
||||||
message?: string
|
| { phase: 'generating_subquestion'; sub_question_index: number; sub_question_text: string }
|
||||||
}
|
| { phase: 'completed'; answer: string; sub_question_sources?: SubQuestionSources[]; sources?: SourceMetadata[] }
|
||||||
|
| { phase: 'error'; message: string }
|
||||||
|
|
||||||
export interface IngestResponse {
|
export interface IngestResponse {
|
||||||
document_id: string
|
document_id: string
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue