File size: 2,807 Bytes
3c665d2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
import type { InitResponse, RLState, SchemaGraph, SSEEvent } from './types'

const BASE_URL: string = import.meta.env.VITE_API_URL ?? ''

async function* parseSSE(response: Response): AsyncGenerator<SSEEvent> {
  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 lines = buffer.split('\n')
    buffer = lines.pop() ?? ''

    for (const line of lines) {
      if (!line.startsWith('data: ')) continue
      const raw = line.slice(6).trim()
      if (raw === '[DONE]') return
      try {
        yield JSON.parse(raw) as SSEEvent
      } catch {
        // ignore malformed lines
      }
    }
  }
}

export async function* streamExecuteQuery(
  question: string,
  taskId: string
): AsyncGenerator<SSEEvent> {
  const res = await fetch(`${BASE_URL}/api/execute-query`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ question, task_id: taskId }),
  })
  if (!res.ok) {
    throw new Error(`HTTP ${res.status}: ${res.statusText}`)
  }
  yield* parseSSE(res)
}

export async function* streamBenchmark(
  taskId: string,
  queryIds?: string[]
): AsyncGenerator<SSEEvent> {
  const body: Record<string, unknown> = { task_id: taskId }
  if (queryIds) body.queryIds = queryIds

  const res = await fetch(`${BASE_URL}/api/benchmark`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify(body),
  })
  if (!res.ok) {
    throw new Error(`HTTP ${res.status}: ${res.statusText}`)
  }
  yield* parseSSE(res)
}

export async function fetchInit(): Promise<InitResponse> {
  const res = await fetch(`${BASE_URL}/api/init`)
  if (!res.ok) throw new Error(`HTTP ${res.status}`)
  return res.json() as Promise<InitResponse>
}

export async function fetchRLState(): Promise<RLState> {
  const res = await fetch(`${BASE_URL}/api/rl-state`)
  if (!res.ok) throw new Error(`HTTP ${res.status}`)
  return res.json() as Promise<RLState>
}

export async function fetchSchemaGraph(): Promise<SchemaGraph> {
  const res = await fetch(`${BASE_URL}/api/schema-graph`)
  if (!res.ok) throw new Error(`HTTP ${res.status}`)
  return res.json() as Promise<SchemaGraph>
}

export async function submitFeedback(
  question: string,
  sql: string,
  correct: boolean
): Promise<void> {
  await fetch(`${BASE_URL}/api/feedback`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ question, sql, correct }),
  })
}

export async function fetchPromptHistory() {
  const res = await fetch(`${BASE_URL}/api/prompt-history`)
  if (!res.ok) throw new Error(`HTTP ${res.status}`)
  return res.json()
}