feat: 完成 H 群組 — 網頁對話介面(第一個可實際使用的垂直切片)
- POST /chat/:characterId:正式對外對話端點,DialogueService 補上情緒標記與親密度 累積(每輪對話走完整管線:標記情緒→檢索記憶→組裝→生成→過濾) - POST /session/:sessionId/end:觸發睡眠固化 - NestJS 啟用 CORS(WEB_ORIGIN,預設 http://localhost:3100),本清單第一次有瀏覽器直接呼叫 api - apps/web/app/chat:對話頁面(ChatView 用戶端元件),電腦雙欄/行動單欄同一份 RWD 程式, 立繪半身像置頂佔 40% 為行動版背景層 - 情緒晶片+親密度數字顯示,跟著每輪回應即時更新 - 動作描寫標記(*…*)以暮空紫小字獨立呈現,與台詞區分 - HeartbeatWave 元件:載入時由左至右畫出、親密度決定振幅、通知紅點心跳脈動, 皆尊重 prefers-reduced-motion;首頁與對話頁共用同一元件 - 色票換成 wiki 主視覺提案頁的完整 token 組(含官方深色模式數值) - scripts/smoke/H.mjs:端到端驗證對話 API 狀態變化、session 結束固化、頁面結構標記; 另以 Playwright + headless Chromium 實際開瀏覽器驗證桌面/行動版面、送出訊息、 動作標記渲染,過程無 console 錯誤 npm run restart && npm run smoke -- H 皆通過(H-V),A~G 群組冒煙測試無回歸。
This commit is contained in:
@@ -0,0 +1,46 @@
|
||||
import type { EmotionTag, RelationshipStage } from "@kokorone/shared";
|
||||
|
||||
const API_BASE_URL = process.env.NEXT_PUBLIC_API_URL ?? "http://localhost:3001";
|
||||
|
||||
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 interface ChatResult {
|
||||
text: string;
|
||||
actions: string[];
|
||||
isFastChannel: boolean;
|
||||
context: ChatContext;
|
||||
}
|
||||
|
||||
export async function sendChatMessage(
|
||||
characterId: string,
|
||||
userId: string,
|
||||
sessionId: string,
|
||||
text: string,
|
||||
): Promise<ChatResult> {
|
||||
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 async function endChatSession(sessionId: string, characterId: string): Promise<void> {
|
||||
await fetch(`${API_BASE_URL}/session/${sessionId}/end`, {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({ characterId }),
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user