File size: 4,243 Bytes
b1c84b5
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
/**
 * PhilVerify Frontend Type Definitions
 * Mirrors the Pydantic models defined in api/schemas.py
 */

// ── Input types ────────────────────────────────────────────────────────────────

export interface VerifyTextRequest {
  text: string
}

export interface VerifyUrlRequest {
  url: string
}

// ── Layer 1 (TF-IDF classifier) ────────────────────────────────────────────────

export interface Layer1Result {
  verdict: Verdict
  score: number          // 0–100 credibility score
  confidence: number     // 0–100%
  triggered_features: string[]
  explanation: string
}

// ── Layer 2 (Evidence retrieval) ───────────────────────────────────────────────

export interface SourceArticle {
  title: string
  url: string
  source_name: string
  similarity: number
  published_at?: string
  credibility_score?: number
}

export interface Layer2Result {
  sources: SourceArticle[]
  stance: 'supporting' | 'contradicting' | 'neutral' | string
  evidence_score: number     // 0–100
}

// ── Verification response ──────────────────────────────────────────────────────

export type Verdict = 'Credible' | 'Unverified' | 'Likely Fake'
export type InputType = 'text' | 'url' | 'image' | 'video'

export interface VerificationResponse {
  text_preview: string
  language: string
  verdict: Verdict
  final_score: number        // 0–100 final credibility score
  confidence: number         // 0–100%
  layer1: Layer1Result
  layer2: Layer2Result
  timestamp: string          // ISO 8601
  input_type?: InputType
  /** Present only in extension cached results */
  _fromCache?: boolean
}

// ── History ────────────────────────────────────────────────────────────────────

export interface HistoryEntry {
  id: string
  text_preview: string
  verdict: Verdict
  final_score: number
  language?: string
  timestamp: string          // ISO 8601
  input_type?: InputType
}

export interface HistoryParams {
  limit?: number
  offset?: number
  verdict?: Verdict
}

export interface HistoryResponse {
  items: HistoryEntry[]
  total: number
  limit: number
  offset: number
}

// ── Trends ─────────────────────────────────────────────────────────────────────

export interface TrendingEntity {
  entity: string
  count: number
}

export interface TrendingTopic {
  topic: string
  count: number
}

export interface VerdictDayPoint {
  date: string               // YYYY-MM-DD
  credible: number
  unverified: number
  fake: number
}

export interface TrendsResponse {
  top_entities: TrendingEntity[]
  top_topics: TrendingTopic[]
  verdict_distribution: Record<Verdict, number>
  verdict_by_day: VerdictDayPoint[]
}

// ── Health ─────────────────────────────────────────────────────────────────────

export interface HealthResponse {
  status: 'ok' | 'degraded' | 'error'
  version: string
  models_loaded: boolean
  firestore_connected: boolean
}

// ── API error ──────────────────────────────────────────────────────────────────

export class ApiError extends Error {
  /** True when the backend responded (HTTP error), false for network failures */
  readonly isBackendError: boolean

  constructor(message: string, isBackendError = false) {
    super(message)
    this.name = 'ApiError'
    this.isBackendError = isBackendError
  }
}