현재 작업 전체 반영
This commit is contained in:
parent
5560638e54
commit
c0dddab594
85 changed files with 11322 additions and 539 deletions
3723
apps/web/src/lib/api.gen.ts
Normal file
3723
apps/web/src/lib/api.gen.ts
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -6,6 +6,10 @@
|
|||
- SSE: POST /sessions/{id}/stream 의 token/done/ping/error 이벤트를 콜백으로 전달.
|
||||
===================================================================== */
|
||||
|
||||
import type { components } from "./api.gen";
|
||||
|
||||
type ApiSchema<Name extends keyof components["schemas"]> = components["schemas"][Name];
|
||||
|
||||
// Vite 환경변수. 기본 "/api" (vite proxy 또는 nginx 가 백엔드로 라우팅).
|
||||
const PUBLIC_API_ORIGIN_BY_HOST: Record<string, string> = {
|
||||
"vignette.chanpaca.net": "https://api-vignette.chanpaca.net",
|
||||
|
|
@ -209,6 +213,9 @@ export interface PersonaReviewSummary {
|
|||
approved_at: string | null;
|
||||
}
|
||||
|
||||
export type PersonaDraftPayload = ApiSchema<"PersonaDraftPayload">;
|
||||
export type PersonaDraftDetail = ApiSchema<"PersonaDraftDetail">;
|
||||
|
||||
/** POST /sessions — sessions.py SessionStartResponse */
|
||||
export interface SessionStartResponse {
|
||||
session_id: string;
|
||||
|
|
@ -221,19 +228,15 @@ export interface SessionStartResponse {
|
|||
}
|
||||
|
||||
/** POST /sessions/{id}/turn — sessions.py TurnResponse */
|
||||
export interface TurnResponse {
|
||||
turn_seq: number;
|
||||
stage: SessionStage;
|
||||
effective_openness: number;
|
||||
client_reply: string | null;
|
||||
safety_flagged: boolean;
|
||||
}
|
||||
export type TurnResponse = ApiSchema<"TurnResponse">;
|
||||
|
||||
/** POST /sessions/{id}/end — sessions.py SessionEndResponse */
|
||||
export interface SessionEndResponse {
|
||||
session_id: string;
|
||||
session_no: number;
|
||||
digest_pending: boolean;
|
||||
export type SessionEndResponse = ApiSchema<"SessionEndResponse">;
|
||||
|
||||
export interface CrisisResource {
|
||||
title: string;
|
||||
number: string;
|
||||
message: string;
|
||||
}
|
||||
|
||||
export interface LearnerSessionSummary {
|
||||
|
|
@ -290,6 +293,12 @@ export interface ReviewTechnique {
|
|||
label: string;
|
||||
}
|
||||
|
||||
export interface ReviewNonverbalEvent {
|
||||
kind: "audio" | "silence" | "pace" | "barge_in";
|
||||
label: string;
|
||||
detail: string;
|
||||
}
|
||||
|
||||
export interface ReviewNote {
|
||||
author: "ai" | "instructor" | string;
|
||||
tone: "good" | "watch";
|
||||
|
|
@ -305,6 +314,7 @@ export interface ReviewTurn {
|
|||
who: string;
|
||||
text: string;
|
||||
techniques: ReviewTechnique[];
|
||||
nonverbal: ReviewNonverbalEvent[];
|
||||
note?: ReviewNote | null;
|
||||
}
|
||||
|
||||
|
|
@ -333,6 +343,34 @@ export interface ReviewPoint {
|
|||
jumpTo?: string | null;
|
||||
}
|
||||
|
||||
export interface ReviewWorksheetEvidence {
|
||||
turnId: string;
|
||||
speaker: "learner" | "client";
|
||||
quote: string;
|
||||
}
|
||||
|
||||
export interface ReviewWorksheetItem {
|
||||
key: string;
|
||||
label: string;
|
||||
value?: string | null;
|
||||
evidence: ReviewWorksheetEvidence[];
|
||||
confidence: "none" | "low" | "medium";
|
||||
emptyReason?: string | null;
|
||||
}
|
||||
|
||||
export interface ReviewWorksheetSection {
|
||||
key: string;
|
||||
title: string;
|
||||
items: ReviewWorksheetItem[];
|
||||
}
|
||||
|
||||
export interface ReviewCaseWorksheet {
|
||||
status: "empty" | "draft_from_transcript";
|
||||
generatedBy: string;
|
||||
sections: ReviewWorksheetSection[];
|
||||
limitations: string[];
|
||||
}
|
||||
|
||||
export interface SessionReviewResponse {
|
||||
session_id: string;
|
||||
client: ReviewClient;
|
||||
|
|
@ -353,6 +391,7 @@ export interface SessionReviewResponse {
|
|||
rubric: ReviewRubricRow[];
|
||||
goodMoments: ReviewPoint[];
|
||||
growthPoints: ReviewPoint[];
|
||||
caseWorksheet?: ReviewCaseWorksheet | null;
|
||||
nextLine?: string | null;
|
||||
clientFeedback?: string | null;
|
||||
audioUrl?: string | null;
|
||||
|
|
@ -388,6 +427,9 @@ export interface SessionStreamDone {
|
|||
effective_openness?: number;
|
||||
turn_seq?: number;
|
||||
safety_flagged?: boolean;
|
||||
crisis_kind?: string;
|
||||
crisis_resource?: CrisisResource | null;
|
||||
conversation_stopped?: boolean;
|
||||
}
|
||||
|
||||
function safeParse(data: string): unknown {
|
||||
|
|
@ -453,6 +495,9 @@ export async function openSessionStream(
|
|||
effective_openness: parsed.effective_openness,
|
||||
turn_seq: parsed.turn_seq,
|
||||
safety_flagged: parsed.safety_flagged,
|
||||
crisis_kind: parsed.crisis_kind,
|
||||
crisis_resource: parsed.crisis_resource,
|
||||
conversation_stopped: parsed.conversation_stopped,
|
||||
};
|
||||
handlers.onDone?.(donePayload);
|
||||
return;
|
||||
|
|
@ -520,6 +565,12 @@ export const personaReviewApi = {
|
|||
api.post<PersonaReviewSummary>(`/personas/review/${encodeURIComponent(personaId)}`, {
|
||||
action,
|
||||
}),
|
||||
createDraft: (payload: PersonaDraftPayload) =>
|
||||
api.post<PersonaReviewSummary>("/personas/drafts", payload),
|
||||
getDraft: (personaId: string) =>
|
||||
api.get<PersonaDraftDetail>(`/personas/drafts/${encodeURIComponent(personaId)}`),
|
||||
updateDraft: (personaId: string, payload: PersonaDraftPayload) =>
|
||||
api.put<PersonaReviewSummary>(`/personas/drafts/${encodeURIComponent(personaId)}`, payload),
|
||||
};
|
||||
|
||||
export const sessionApi = {
|
||||
|
|
@ -568,8 +619,39 @@ export interface AdminHealthResponse {
|
|||
services: AdminServiceHealth[];
|
||||
}
|
||||
|
||||
export interface AdminUsageBreakdown {
|
||||
provider: string;
|
||||
model: string;
|
||||
turns: number;
|
||||
tokens_in: number;
|
||||
tokens_out: number;
|
||||
cost_usd: number;
|
||||
}
|
||||
|
||||
export interface AdminUsageBudget {
|
||||
limit_usd: number;
|
||||
used_ratio: number;
|
||||
remaining_usd: number | null;
|
||||
status: "disabled" | "ok" | "warn" | "exceeded";
|
||||
}
|
||||
|
||||
export interface AdminUsageResponse {
|
||||
source: "database" | "server_session_registry";
|
||||
durable: boolean;
|
||||
window_days: number;
|
||||
generated_at: number;
|
||||
total_turns: number;
|
||||
metered_turns: number;
|
||||
tokens_in: number;
|
||||
tokens_out: number;
|
||||
cost_usd: number;
|
||||
budget: AdminUsageBudget;
|
||||
by_provider: AdminUsageBreakdown[];
|
||||
}
|
||||
|
||||
export const adminApi = {
|
||||
health: () => api.get<AdminHealthResponse>("/admin/health"),
|
||||
usage: (windowDays = 7) => api.get<AdminUsageResponse>(`/admin/usage?window_days=${windowDays}`),
|
||||
};
|
||||
|
||||
export interface AdminManagedUser {
|
||||
|
|
@ -629,12 +711,58 @@ export interface TeacherSessionSummary {
|
|||
ended_at: string | null;
|
||||
}
|
||||
|
||||
export interface TeacherSafetyAlert {
|
||||
id: string;
|
||||
session_id: string;
|
||||
learner_id: string;
|
||||
learner_label: string;
|
||||
persona_code: string;
|
||||
session_no: number;
|
||||
trigger_type: string;
|
||||
ko_risk_level: number;
|
||||
escalated: boolean;
|
||||
created_at: string;
|
||||
resource_title: string;
|
||||
resource_number: string;
|
||||
}
|
||||
|
||||
export interface TeacherGrowthPoint {
|
||||
session_id: string;
|
||||
session_no: number;
|
||||
persona_code: string;
|
||||
stage: string;
|
||||
started_at: string;
|
||||
ended_at: string | null;
|
||||
score: number | null;
|
||||
rapport: number | null;
|
||||
technique_count: number;
|
||||
watch_count: number;
|
||||
}
|
||||
|
||||
export interface TeacherLearnerGrowth {
|
||||
learner_id: string;
|
||||
learner_label: string;
|
||||
sessions: number;
|
||||
ended_sessions: number;
|
||||
latest_at: string;
|
||||
first_score: number | null;
|
||||
latest_score: number | null;
|
||||
score_delta: number | null;
|
||||
avg_score: number | null;
|
||||
avg_rapport: number | null;
|
||||
trend: "up" | "down" | "flat" | "insufficient" | string;
|
||||
top_techniques: string[];
|
||||
points: TeacherGrowthPoint[];
|
||||
}
|
||||
|
||||
export interface TeacherDashboardResponse {
|
||||
source: string;
|
||||
cohort_label: string;
|
||||
total_learners: number;
|
||||
active_sessions: number;
|
||||
ended_sessions: number;
|
||||
safety_alerts: TeacherSafetyAlert[];
|
||||
learner_growth: TeacherLearnerGrowth[];
|
||||
pending_reviews: TeacherSessionSummary[];
|
||||
recent_sessions: TeacherSessionSummary[];
|
||||
message: string;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue