# AI Runtime Client Sync Implementation Plan

> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.

**Goal:** Synchronize AI calls in web, web-admin, life-script, and mini-program so user-facing AI output uses the backend scene routing runtime and streams text progressively.

**Architecture:** The backend remains the single trust boundary for provider credentials, scene bindings, user context enrichment, and workflow selection. Browser and mini-program clients call `/ai/runtime/stream` with `sceneCode` and `inputs`, while existing WebSocket chat is bridged through `AiRuntimeService` so chat also follows the configured `chat` scene. Existing business save APIs remain responsible for persistence after a stream completes.

**Tech Stack:** Spring Boot, STOMP WebSocket, FastJSON, Vue 3, React/Vite, uni-app chunked request, Element Plus.

---

### Task 1: Backend Chat Bridge To Runtime

**Files:**
- Modify: `server/src/main/java/com/emotion/service/impl/WebSocketServiceImpl.java`
- Modify: `server/src/main/java/com/emotion/dto/websocket/WebSocketMessage.java`

- [x] Route chat generation through `AiRuntimeService` with `sceneCode=chat`.
- [x] Push `start`, `delta`, `done`, and `error` events over the existing user WebSocket topic.
- [x] Save the final assistant message after `done` using the accumulated stream output.
- [x] Preserve the existing user-message persistence and conversation ID behavior.

### Task 2: Shared Runtime Clients

**Files:**
- Create: `web/src/services/aiRuntime.ts`
- Create: `life-script/src/services/aiRuntime.js`
- Modify: `mini-program/src/services/aiRuntime.js`
- Modify: `web-admin/src/api/aiconfig.ts`
- Modify: `web-admin/src/views/aiconfig/AiRoutingList.vue`

- [x] Add browser SSE client helpers that parse unified AI stream events.
- [x] Keep mini-program chunk parsing but localize error messages and flush trailing frames.
- [x] Add a web-admin stream test helper and make the test dialog render output progressively.

### Task 3: Client Scene Migration

**Files:**
- Modify: `life-script/src/services/ai.js`
- Modify: `life-script/src/views/ScriptView.jsx`
- Modify: `life-script/src/views/TimelineView.jsx`
- Modify: `life-script/src/views/PathView.jsx`
- Modify: `mini-program/src/pages/main/ScriptView.vue`
- Inspect: `web/src/stores/chat.ts`

- [x] Remove direct OpenRouter calls and hard-coded client API keys.
- [x] Route `script_generate`, `life_healing`, and path generation through `streamAiScene`.
- [x] Ensure pages append `delta` content instead of waiting for complete text.
- [x] Keep final persistence through existing business save APIs after stream completion.

### Task 4: Verification

**Commands:**
- `mvn test`
- `mvn -DskipTests clean package`
- `npm run build` in `web`
- `npm run build` in `web-admin`
- `npm run build` in `life-script`
- `npm run build:mp-weixin` in `mini-program`

- [x] Backend tests pass.
- [x] Backend package succeeds.
- [x] All four frontend builds succeed.
- [x] Source scan shows no client-side external AI provider key or direct Dify/Coze/OpenRouter call.
- [x] Database scene bindings are enabled with streaming endpoints for `chat`, `script_generate`, `short_story_generate`, `diary_summary`, `emotion_summary`, `emotion_analysis`, and `life_healing`.
