Add LLM token
This commit is contained in:
@@ -76,6 +76,27 @@ function parseSSEChunk(raw: string, onMessage: (data: SSEMessage) => void) {
|
||||
onMessage({ type: 'error', text: joined });
|
||||
} else if (eventName === 'status') {
|
||||
onMessage({ type: 'status', text: joined });
|
||||
} else if (eventName === 'thinking') {
|
||||
// P0-1: Agentic reasoning step events from /agent/agentic/stream
|
||||
try {
|
||||
const payload = JSON.parse(joined) as Record<string, unknown>;
|
||||
onMessage({
|
||||
type: 'thinking',
|
||||
step: payload.step as string | undefined,
|
||||
status: payload.status as string | undefined,
|
||||
intent_type: payload.intent_type as string | undefined,
|
||||
requires_decomposition: payload.requires_decomposition as boolean | undefined,
|
||||
reason: payload.reason as string | undefined,
|
||||
sub_queries: payload.sub_queries as string[] | undefined,
|
||||
query: payload.query as string | undefined,
|
||||
index: payload.index as number | undefined,
|
||||
total: payload.total as number | undefined,
|
||||
found: payload.found as number | undefined,
|
||||
retry: payload.retry as boolean | undefined,
|
||||
sufficient: payload.sufficient as boolean | undefined,
|
||||
confidence: payload.confidence as number | undefined,
|
||||
});
|
||||
} catch { /* ignore */ }
|
||||
} else if (eventName === 'message') {
|
||||
// /rag/chat format: event:message + JSON body with type field
|
||||
try {
|
||||
@@ -147,3 +168,73 @@ export async function ragChat(
|
||||
}
|
||||
|
||||
export type { QuickQuestionsResponse, SSEMessage };
|
||||
|
||||
/**
|
||||
* P0-1 Agentic RAG chat — calls /agent/agentic/stream which runs the full
|
||||
* intent-analysis → query-planning → retrieval → grounding-check → answer pipeline.
|
||||
*
|
||||
* The onMessage callback receives the same event types as ragChat plus
|
||||
* ``type: 'thinking'`` events that carry live reasoning-step progress.
|
||||
*/
|
||||
export async function agenticChat(
|
||||
query: string,
|
||||
topK: number = 5,
|
||||
onMessage: (data: SSEMessage) => void,
|
||||
onError?: (error: Error) => void,
|
||||
onComplete?: () => void,
|
||||
filters?: string,
|
||||
sessionId?: string,
|
||||
signal?: AbortSignal,
|
||||
contextText?: string,
|
||||
contextFilename?: string,
|
||||
): Promise<void> {
|
||||
try {
|
||||
const response = await fetch(`${AGENT_API_BASE}/agent/agentic/stream`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
Accept: 'text/event-stream',
|
||||
...(getToken() ? { Authorization: `Bearer ${getToken()}` } : {}),
|
||||
},
|
||||
body: JSON.stringify({
|
||||
query,
|
||||
top_k: topK,
|
||||
...(filters ? { filters } : {}),
|
||||
...(sessionId ? { session_id: sessionId } : {}),
|
||||
...(contextText ? { context_text: contextText, context_filename: contextFilename ?? '' } : {}),
|
||||
}),
|
||||
signal,
|
||||
});
|
||||
|
||||
if (!response.ok || !response.body) {
|
||||
throw new Error(`HTTP error! status: ${response.status}`);
|
||||
}
|
||||
|
||||
const reader = response.body.getReader();
|
||||
const decoder = new TextDecoder();
|
||||
let buffer = '';
|
||||
|
||||
while (true) {
|
||||
const { done, value } = await reader.read();
|
||||
if (done) break;
|
||||
|
||||
buffer += decoder.decode(value, { stream: true });
|
||||
const parts = buffer.split('\n\n');
|
||||
buffer = parts.pop() || '';
|
||||
parseSSEChunk(parts.join('\n\n'), onMessage);
|
||||
}
|
||||
|
||||
if (buffer.trim()) {
|
||||
parseSSEChunk(buffer, onMessage);
|
||||
}
|
||||
|
||||
if (onComplete) {
|
||||
onComplete();
|
||||
}
|
||||
} catch (error) {
|
||||
if (error instanceof DOMException && error.name === 'AbortError') return;
|
||||
if (onError) {
|
||||
onError(error instanceof Error ? error : new Error(String(error)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user