274 Commits

Author SHA1 Message Date
kongweigen
4b59714b52 update readme 2026-04-12 17:21:58 +08:00
jensen
d28a0273e2 feat 更新群聊图片链接 2026-04-10 14:20:12 +08:00
jensen
9009a523dc fix 更新readme 2026-04-08 15:29:10 +08:00
jensen
c4655b7bf0 fix 修改部署skills加载失败、修改公共样式 2026-04-07 17:23:48 +08:00
Connor
0930ac858f feat: 添加 Docker 部署支持,更新 README
- 新增 Dockerfile (多阶段构建,前后端合并为单镜像)
- 新增 docker-compose.yml
- 新增 .dockerignore
- 新增 data/.gitkeep 确保 data 目录存在
- 修复 skills 路由路径解析 (process.cwd → __dirname)
- 修复数据库初始化时 data 目录不存在的问题
- 重写 README,更新为当前 TypeScript 技术栈
- 清理项目根目录临时文件

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-05 00:48:39 +08:00
jensen
b30ac5cfa8 fix: style preset button hover effect and add register link
- Button hover shows gradient background with lift animation
- Add "register now" text link in one-click config dialog
2026-04-03 16:51:18 +08:00
Connor
9970451aba 修改配置相关 2026-04-01 18:59:05 +08:00
Connor
846c0f27be 修改配置相关 2026-04-01 18:24:27 +08:00
Connor
ae4bf97a1c 修改readme相关内容 2026-04-01 16:41:50 +08:00
Connor
ffa9c5584e Merge branch 'feature-ts'
# Conflicts:
#	README-CN.md
#	README-JA.md
#	README.md
#	drama.png
2026-04-01 13:44:47 +08:00
Connor
d308e3dd7e feat: revamp studio workflow and media pipeline 2026-04-01 12:57:12 +08:00
Connor
cd16bbf753 feat: guided wizard for script panel — one step at a time
Replace scattered buttons with single-step focused wizard:

Step 1 (原始内容): Large textarea + "保存并继续 →"
Step 2 (AI 改写): "开始改写" button → loading → result editor + "保存并继续 →"
Step 3 (提取): "开始提取" button → loading → character table + scene chips + "继续 →"
Step 4 (音色): "AI 自动分配" or manual dropdown per character + voice sample player + "完成,进入分镜 →"

Features:
- Step bar with click navigation (can go back to completed steps)
- Auto-detect current step on page load
- Loading state with centered spinner
- Re-do buttons on each step (重新改写, 重新提取, 重新分配)
- Voice dropdown with 6 OpenAI voices (alloy/echo/fable/onyx/nova/shimmer)
- Inline audio player for voice samples
- updateCharVoice saves immediately via API

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 16:30:24 +08:00
Connor
b68f33f6c2 feat: redesign storyboard panel — card list + side editor
Replace sparse table with dense card list:
- Each shot is a compact card: #num | tag | desc (2 lines) | dialogue
- Left border highlight on selected card (orange accent)
- Auto-select first shot on load
- Auto-select next shot after delete

Editor panel (380px):
- Shot type dropdown + duration in one row
- Location, description, video prompt, dialogue fields
- blur auto-save
- Delete with auto-select next

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 16:23:39 +08:00
Connor
a48e0885fd fix: remove TypeScript generic from non-TS script block
ref<any>(null) → ref(null) — Nuxt treats <any> as HTML tag in
plain <script setup> blocks without lang="ts".

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 16:13:39 +08:00
Connor
e388d5127e feat: redesign storyboard panel — table + side editor
Split layout:
- Left: compact table (# | 景别 | 描述 | 时长) with row click selection
- Right: 340px detail editor panel with all fields
  - 景别 dropdown (远景/全景/中景/近景/特写)
  - 描述, 视频提示词, 对白 textareas
  - 时长, 地点 inputs
  - Delete button

Features:
- Selected row highlighted with accent background
- Fields auto-save on blur via storyboardAPI.update
- Total duration badge in toolbar
- Delete storyboard support (storyboardAPI.del)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 16:09:24 +08:00
Connor
989b443b4d fix: remove dark theme, light only
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 15:59:25 +08:00
Connor
8a064104de feat: complete UI redesign — clean professional interface
Full visual overhaul of all pages:

Design system (studio.css):
- Light/dark auto-switch with refined color palette
- Card component with shadow + border + hover states
- Pill-shaped tags with semantic colors
- Shadow-elevated buttons with proper states
- 13px base font, comfortable line height
- Rounded corners (6px/10px), consistent spacing

Layout (default.vue):
- Top navigation bar (48px) instead of narrow sidebar
- Brand + nav links in horizontal bar
- Clean content area below

Pages redesigned:
- index.vue: Card grid for projects, proper modal dialog
- [id]/index.vue: Episode list with badges and chevron arrows
- [episodeNumber].vue: 4-panel workbench with pipeline steps,
  split editor, resource cards, production grid, export player
- settings.vue: Centered form layout with toggle switches

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 15:53:11 +08:00
Connor
8385a407c9 fix: move [id].vue to [id]/index.vue for nested episode routes
[id].vue as a leaf file conflicts with [id]/episode/[episodeNumber].vue.
Nuxt needs [id] to be a directory with index.vue for nested routes to work.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 15:39:38 +08:00
Connor
4bd11c0ff4 feat: add colored console logs for all API calls and agent events
API requests:
  [API] GET /dramas → 200 12ms (green)
  [API] POST /ai-configs → 400 3ms (red) + error message

Agent SSE:
  [Agent] START script_rewriter drama=5 episode=136
  [Agent] CALL read_episode_script {args}
  [Agent] RESULT read_episode_script {data preview}
  [Agent] DONE script_rewriter
  [Agent] ERROR extractor {message}

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 15:34:55 +08:00
Connor
43bd270f9f fix: use vite.server.proxy instead of nitro.devProxy
nitro.devProxy doesn't work in SPA mode. Use Vite's built-in
proxy which works reliably for /api and /static forwarding.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 15:26:09 +08:00
Connor
e6c1516d33 fix: normalize all API responses to snake_case
Apply toSnakeCase/toSnakeCaseArray to all route responses:
- dramas.ts: list items, detail, create response
- episodes.ts: storyboard listing
- storyboards.ts: create response

Frontend reads snake_case fields (shot_type, video_prompt, episode_id, etc.)
but Drizzle returns camelCase. Now all responses are consistent.

Also fix bare import paths to use .js extension.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 15:24:44 +08:00
Connor
1cb3d9fe90 feat: system theme — auto light/dark via prefers-color-scheme
Light mode default, dark mode via @media (prefers-color-scheme: dark).
All colors use CSS variables, no hardcoded values in components.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 15:11:46 +08:00
Connor
34ab3c208b fix: set srcDir to app/ so Nuxt finds app.vue instead of welcome page
Also move composables/ into app/ directory.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 15:10:34 +08:00
Connor
aa2e8abce7 feat: complete frontend rewrite — Nuxt 3 professional studio UI
Full rewrite with Nuxt 3 + professional dark theme (DaVinci Resolve style):

Tech: Nuxt 3, Vue 3, vue-sonner, lucide-vue-next, pure CSS

Design:
- Deep black background (#0d0d0d)
- Compact 36px header, 52px icon sidebar
- 11px base font, monospace for data
- Minimal chrome, high information density
- Status tags: success/accent/info

Pages:
- / — Project list with inline create dialog
- /drama/[id] — Episode grid
- /drama/[id]/episode/[episodeNumber] — 4-panel workbench (studio layout)
- /settings — AI service config

Workbench 4 panels:
[剧本] Split editor + character voice cards + scene chips
[分镜] Data table with inline editing
[制作] Shot list with image/video/compose status + batch ops
[导出] Video player + download + merge trigger

Composables:
- useApi.ts — All 10 API modules in one file
- useAgent.ts — SSE agent execution with toast progress

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 15:06:01 +08:00
Connor
4b073c5088 feat: rewrite frontend with 4-panel pipeline workbench
Complete UI rewrite for 9-step short drama production pipeline:

[剧本] panel (steps 1-4):
  - Dual editor: raw content ↔ formatted script
  - Sub-step indicators: 原始内容→改写→提取→音色
  - Character cards with voice assignment + TTS audio playback
  - Scene list display
  - Agent buttons: rewrite, extract, assign voice

[分镜] panel (step 5):
  - Storyboard table with inline editing
  - Agent-driven breakdown with video prompts
  - Add/edit shots

[制作] panel (steps 6-8):
  - Shot list with thumbnail, video preview, status badges
  - Per-shot actions: generate image, generate video, compose
  - Batch operations: batch images, batch videos, batch compose

[导出] panel (step 9):
  - Final video preview with player
  - Merge button with progress polling
  - Download link

API layer updated:
  - Added characterAPI, imageAPI, videoAPI, composeAPI, mergeAPI
  - Added episodeAPI.getPipelineStatus

Composable updated:
  - useWorkbench now handles all 9 steps
  - 4 panel types with navigation

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 14:42:31 +08:00
Connor
73b88f94fb fix: resolve 7 code review issues
Critical fixes:
1. /dramas/stats route moved before /:id (was permanently shadowed)
2. Removed dead characters query in ffmpeg-compose (wrong FK column)

Security:
3. PUT /dramas/:id — whitelist allowed fields instead of spreading body

Correctness:
4. Middleware order: requestLogger before errorHandler (errors now logged)
5. getActiveConfig: sort by priority descending (deterministic provider selection)

tsc --noEmit: 0 errors

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 14:25:22 +08:00
Connor
7b76a9322b feat: complete 9-step pipeline — voice, TTS, compose, merge
New pipeline steps implemented:

Step 3 - Voice assignment agent:
  agents/tools/voice-tools.ts — get_characters, list_voices, assign_voice
  agents/index.ts — voice_assigner agent registered

Step 4 - TTS voice sample:
  services/tts-generation.ts — OpenAI compatible /audio/speech
  routes/characters.ts — POST /:id/generate-voice-sample

Step 8 - Shot composition (video + TTS audio + burned subtitles):
  services/ffmpeg-compose.ts — per-shot FFmpeg compose
  routes/compose.ts — POST /storyboards/:id/compose
                      POST /episodes/:id/compose-all

Step 9 - Episode merge (concat all composed shots):
  services/ffmpeg-merge.ts — FFmpeg concat with duration probe
  routes/merge.ts — POST/GET /episodes/:id/merge

Infrastructure:
  db/schema.ts — 5 new columns (voice_sample_url, voice_provider,
    tts_audio_url, subtitle_url, composed_video_url)
  services/ai.ts — audio service type support
  routes/episodes.ts — GET /:id/pipeline-status (10-step progress)

tsc --noEmit: 0 errors

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 14:20:05 +08:00
Connor
9a1b7e0e55 fix: force npm for backend (pnpm breaks better-sqlite3 native binding)
Add .npmrc with package-manager=npm, remove pnpm-lock.yaml.
Run: cd backend && rm -rf node_modules && npm install

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 12:52:13 +08:00
Connor
78443faec9 fix: resolve all TypeScript build errors (0 errors)
- agents/index.ts: cast OpenAI provider config as any for compatibility
- routes/agent.ts: access chunk.payload for Mastra stream fields,
  fallback to top-level for backwards compat
- routes/images.ts, videos.ts: add .all() to db.select() calls
- routes/characters.ts: remove non-existent imageGenerationStatus
- services/image-generation.ts: rewrite with proper .all() and .run()
- services/video-generation.ts: rewrite with proper .all() and .run()

npx tsc --noEmit: 0 errors

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 12:37:51 +08:00
Connor
4a00b6bb99 feat: comprehensive agent logging
Full lifecycle logging for agent chat:
- START: agent type, drama_id, episode_id, message
- LLM stream: calling status
- CALL: tool name + arguments (truncated 300 chars)
- RESULT: tool name + result (truncated 200 chars)
- DONE: elapsed time, chunk count, text length, tool call/result counts
- ERROR: full stack trace
- Unknown chunk types logged for debugging

Color-coded output:
  cyan=agent lifecycle, magenta=tool calls,
  green=tool results/done, red=errors, dim=unknown chunks

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 12:24:48 +08:00
Connor
0e92b2cbd2 fix: handle undefined tool result in agent stream
chunk.result can be undefined, causing .slice() to fail.
Add null check before stringifying.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 12:20:57 +08:00
Connor
ec9f61020b fix: inject episodeId/dramaId into agent tools via factory pattern
Before: tools required LLM to extract episode_id from message text
and pass it as a parameter — unreliable, LLM often got it wrong.

After: agent and tools created per-request with episodeId/dramaId
bound in closures. Tools have empty inputSchema for IDs — they
just use the injected values directly.

Changes:
- All tool files → factory functions (createScriptTools, etc.)
- agents/index.ts → createAgent() factory replaces static agents
- agent route → creates fresh agent per request with IDs injected
- No more [Context: ...] text injection in messages
- Added agent execution logging

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 11:06:39 +08:00
Connor
590e8c47d4 feat: add global request logger and error handler
Custom middleware replaces hono/logger:
- Colored output: time, method, path, status, duration
- POST/PUT/PATCH requests print request body (truncated to 500 chars)
- Global error handler catches uncaught exceptions with full stack trace
- Status codes color-coded: 2xx green, 4xx yellow, 5xx red

Also fix: CORS origins updated, static file path to frontend/dist

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 22:39:23 +08:00
Connor
9fd1c03236 fix: replace .returning() with .run() + lastInsertRowid
Drizzle + better-sqlite3 .returning() causes "not iterable" error.
Replace all 6 occurrences with .run() + select by lastInsertRowid:
- aiConfigs.ts POST
- dramas.ts POST (also add metadata field, fix missing .run())
- scenes.ts POST
- storyboards.ts POST
- image-generation.ts
- video-generation.ts

Also fix .js import extensions and add .run() to all sync db calls.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 20:08:12 +08:00
Connor
0db0c4f256 feat: redesign DramaList — centered layout, video model selection
DramaList:
- Page centered with max-width 800px
- Create dialog: title, description, episode count, style, video model
- Video model dropdown populated from AI service configs (video type)
- Selected video model stored in drama.metadata.video_model
- Project rows show video model if set
- Delete button on each row with confirmation
- Empty state with icon and create button
- Status labels in Chinese

DramaDetail:
- Center layout to match

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 20:03:28 +08:00
Connor
d7e6f75dbe fix: center Settings page content
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 19:58:23 +08:00
Connor
4ede589762 fix: unify AI config API — snake_case response + edit dialog
Backend:
- Add toSnakeCase/toSnakeCaseArray transform utility
- aiConfigs route returns snake_case JSON (matches frontend expectations)
- Consistent field names: service_type, api_key, base_url, is_active

Frontend Settings:
- Unified snake_case field access (no more dual format checks)
- Add edit button with pencil icon → opens same dialog with pre-filled values
- Provider selection via dropdown (8 providers)
- Base URL auto-fills from provider default
- Model field supports comma-separated multiple models
- Show base URL in config row

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 19:37:40 +08:00
Connor
4cdc81e115 chore: clean up project — rename server→backend, client→frontend
Remove all unrelated files:
- Old docs, README files, LICENSE, Docker files
- Old design specs and plans
- Runtime DB files (shm/wal)
- IDE config, images

Rename:
- server/ → backend/
- client/ → frontend/

Update CLAUDE.md with new structure.

Final layout:
  backend/   — Hono + Drizzle + Mastra
  frontend/  — Vue 3 + Vite
  configs/   — config.yaml
  data/      — SQLite DB
  skills/    — Agent skills

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 17:33:43 +08:00
Connor
1eefac946a chore: remove Go backend and old Vue frontend
Delete 315 files — entire Go codebase and old web/ frontend.
Project now uses TypeScript-only stack:

  server/  — Hono + Drizzle + Mastra (port 5679)
  client/  — Vue 3 + Vite (port 3013)
  configs/ — YAML config
  data/    — SQLite DB + static files
  skills/  — Agent skill definitions
  docs/    — Design specs

All code is recoverable from git history.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 17:15:39 +08:00
Connor
9a0369aadd fix: use Chat Completions API instead of Responses API
Chatfire doesn't support OpenAI Responses format.
Switch to compatibility mode + provider.chat() to force
standard /v1/chat/completions endpoint.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 15:51:31 +08:00
Connor
ee6e8e7707 feat: new Vue 3 frontend — clean rewrite from scratch
Minimal, fast Vue 3 + TypeScript frontend (1s build, 124KB vendor):

Structure:
  client/src/
  ├── main.ts              — Pinia + Vue Router setup
  ├── App.vue              — Sidebar layout (collapsible)
  ├── api/index.ts         — Unified API client + SSE agent streaming
  ├── composables/
  │   └── useWorkbench.ts  — Workbench state (data, agents, pipeline)
  ├── router/index.ts      — 4 routes: list, detail, workbench, settings
  ├── views/
  │   ├── DramaList.vue    — Project list + create dialog
  │   ├── DramaDetail.vue  — Episodes grid + resources summary
  │   ├── Workbench.vue    — Script/Storyboard tabs with pipeline
  │   └── Settings.vue     — AI service config (flat list by type)
  └── assets/main.css      — Dark theme, utility classes, no framework

Key differences from old frontend:
- Zero UI framework (no Shadcn/Element Plus/Radix) — pure CSS
- Single API module with fetch (no Axios)
- Single composable for workbench (no 6 separate composables)
- No i18n overhead (Chinese only for now)
- Agent SSE via async generator (20 lines vs 87)
- Build: 1s / 124KB vendor (vs 3s / 213KB)

Dev: npm run dev → http://localhost:3013 (proxy → 5679)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 13:27:01 +08:00
Connor
82684227fc feat: Phase 3 — AI generation services, file upload, frontend switch
Image generation service:
- Calls OpenAI-compatible /images/generations API
- Async polling (5s interval, 5min timeout) for task-based providers
- Downloads results to local storage, updates storyboard

Video generation service:
- Calls Chatfire/Doubao /video/generations API
- Builds content array with text + reference images
- Appends --ratio and --dur to prompt
- Async polling (10s interval, 50min timeout)
- Downloads video, updates storyboard

File utilities:
- storage.ts: downloadFile(), saveUploadedFile(), getAbsolutePath()
- upload.ts: POST /upload/image with multipart form handling

Frontend:
- Switch vite proxy from Go (5678) to TS (5679)

All endpoints tested: health, dramas, ai-configs, agent debug 

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 13:20:48 +08:00
Connor
cfb41f551a feat: Phase 2 — Mastra agents, SSE streaming, generation routes
Agents (Mastra + AI SDK):
- script_rewriter: read → rewrite → save script tools
- extractor: read script → save characters → save scenes tools
- storyboard_breaker: read context → save storyboards tools
- All agents use OpenAI-compatible provider from DB config
- SSE streaming via Hono streamSSE with fullStream parsing

New routes:
- POST /agent/:type/chat — SSE streaming agent conversation
- GET /agent/:type/debug — Agent info
- /characters — CRUD + generate-image placeholder
- /images — CRUD + batch placeholder
- /videos — CRUD

Agent tool implementations:
- script-tools: read_episode_script, rewrite_to_screenplay, save_script
- extract-tools: read_script_for_extraction, save_characters, save_scenes
- storyboard-tools: read_storyboard_context, save_storyboards, update_storyboard

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 11:07:05 +08:00
Connor
9d86057140 chore: add server/.gitignore, remove node_modules from tracking
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 11:03:15 +08:00
Connor
cee1468a53 feat: TypeScript backend foundation (Hono + Drizzle + SQLite)
Phase 1 of Go → TypeScript rewrite:

Stack: Hono + Drizzle ORM + better-sqlite3 + Mastra (pending)

Project structure:
  server/src/
  ├── index.ts          — Hono app, middleware, route mounting
  ├── db/
  │   ├── schema.ts     — Drizzle schema matching existing SQLite DB
  │   └── index.ts      — Database connection with WAL mode
  ├── routes/
  │   ├── dramas.ts     — Drama CRUD with episodes/characters/scenes
  │   ├── episodes.ts   — Episode update + storyboard listing
  │   ├── storyboards.ts — Storyboard CRUD with field mapping
  │   ├── scenes.ts     — Scene CRUD
  │   ├── aiConfigs.ts  — AI service config CRUD + providers
  │   └── agentConfigs.ts — Agent config CRUD
  └── utils/
      └── response.ts   — Standard JSON response helpers

Key decisions:
- Reuses existing drama_generator.db (no migration needed)
- Schema reverse-engineered from PRAGMA table_info()
- Runs on port 5679 (parallel to Go on 5678)
- ESM modules with tsx for development
- All endpoints match Go API contract for frontend compatibility

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 11:03:04 +08:00
Connor
e1f23dcfe6 fix: AIConfig edit/add buttons not responding
- Change Button size from 'icon' to 'sm' for edit/delete buttons
- Add @click.stop to prevent event bubbling
- Replace Object.assign with direct property assignment on reactive
- Change add button from <button> to <div> to avoid form nesting

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 10:39:59 +08:00
Connor
51c8a23bfb fix: wrap password inputs in form elements
Fixes DOM warning about password fields not contained in forms.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 10:34:59 +08:00
Connor
d539f91b47 fix: AIConfig dialog — use reactive editForm, fix Select binding
- editForm changed from ref to reactive (fixes v-model binding)
- Select uses explicit :model-value + @update:model-value
- Remove .value access on editForm in saveEdit

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 02:00:05 +08:00
Connor
0c07753996 refactor: redesign AI config as flat service list grouped by type
Replace tab-based accordion UI with a clean, flat layout:
- Four sections: 文本/图片/视频/音频, all visible at once
- Each section shows configured services as compact rows:
  provider dot + name + models + URL + key status + toggle + edit/delete
- Add button per section with dashed border
- Edit/Create dialog: provider select, API key, base URL, models (comma-separated)
- Remove ProviderCard dependency, remove service type tabs
- Simpler data flow: no expandable rows, direct CRUD via dialog

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 01:57:40 +08:00
Connor
fa10ab0885 chore: remove lipsync tab from AI config page
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 01:55:32 +08:00