import type { EmotionTag, RelationshipStage } from "@kokorone/shared"; // Q-1:與 apps/web/lib/api.ts 共用同一套 @kokorone/shared 型別,API client 本身雖是各端各自實作 // (React Native 沒有 Next.js 的伺服器端環境變數機制),但契約(回應形狀)三端一致。 export const API_BASE_URL = process.env.EXPO_PUBLIC_API_URL ?? "http://localhost:3001"; export interface HealthResponse { status: string; } export async function fetchHealth(): Promise { const res = await fetch(`${API_BASE_URL}/health`); if (!res.ok) { throw new Error(`健康檢查失敗(${res.status})`); } return res.json(); } export interface ChatResponseStyle { tone: string; sentenceLength: "short" | "medium" | "long"; initiative: "low" | "medium" | "high"; } export interface ChatContext { emotion: { dominant: EmotionTag; style: ChatResponseStyle }; relationship: { intimacy: number; trust: number; stage: RelationshipStage }; } export type ChatAvailability = "NORMAL" | "BRIEF" | "DELAYED" | "NO_REPLY"; export interface ChatResult { text: string; actions: string[]; isFastChannel: boolean; availability: ChatAvailability; exceptionType: string | null; context: ChatContext | null; } export async function sendChatMessage( characterId: string, userId: string, sessionId: string, text: string, ): Promise { const res = await fetch(`${API_BASE_URL}/chat/${characterId}`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ userId, sessionId, text }), }); if (!res.ok) { throw new Error(`對話請求失敗(${res.status})`); } return res.json(); } export interface TachieExpressionResponse { emotionTag: EmotionTag; rawEmotionTag: EmotionTag; eyebrow: string; eye: string; mouth: string; effect: string | null; pose: string; magnitude: number; gaze: "UP" | "AWAY" | "DIRECT" | "NEUTRAL"; availableCostumes: string[]; lockedFallbackApplied: boolean; usedCryingVariant: boolean; } export async function fetchExpression(characterId: string, userId: string): Promise { const res = await fetch(`${API_BASE_URL}/tachie/${characterId}/${userId}/expression`); if (!res.ok) { throw new Error(`表情查詢失敗(${res.status})`); } return res.json(); } export async function registerPushToken(userId: string, token: string, platform: string): Promise { await fetch(`${API_BASE_URL}/push/register`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ userId, token, platform }), }); }