Skip to content
Merged

Dev #181

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 57 additions & 8 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,69 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [1.3.0] - 2026-03-16
## [1.3.0] - 2026-03-19

### Added

- **Task priorities (T0/T1/T2)**: Tasks now carry a `priority` field across template and AI tasks; the UI sorts and highlights urgent/milestone tasks.
- **Proof photo completion**: Dad can optionally upload a proof photo when completing a task; Mom review UI shows thumbnails.
- **Shell Gifts (blind-box shells)**: Completing a task generates a shell gift for Mom (AI-generated title/content + optional proof photo); Mom can list and open shell gifts.
- **Dad dashboard**: Skill radar (six dimensions), achievements (seeded defaults + auto-unlock on verification), and perk cards (Mom issues, Dad redeems).
#### Dad Console

- **Empathetic Terminal theme**: Redesigned DadConsole with terminal-inspired UI, inline panels, and profile page
- **Dad console modular architecture**: Split monolithic DadConsole into modular components (chat, community, tasks, whisper, profile)
- **Dad chat & community panels**: Polished chat interface and community board for dad mode
- **Dad dashboard**: Skill radar (six dimensions), achievements (seeded defaults + auto-unlock on verification), and perk cards (Mom issues, Dad redeems)
- **Memory card generation**: AI-generated memory cards from task completions with mom view filtering

#### Tasks & Whisper

- **Task priorities (T0/T1/T2)**: Tasks now carry a `priority` field across template and AI tasks; the UI sorts and highlights urgent/milestone tasks
- **Proof photo completion**: Dad can optionally upload a proof photo when completing a task; Mom review UI shows thumbnails
- **Future letter workflow**: Replaced shell gift system with future letters — a more meaningful way to capture and deliver care messages over time
- **Enhanced whisper intelligence**: Refreshed whisper flows with scene guidance and improved AI tips
- **Time-space care engine**: Updated mom future letter prompt to use a time-space care engine for richer, more contextual letters

#### Entry & Auth

- **Anime landing page**: New animated entry page for unauthenticated users
- **Redesigned login/register**: New login and register page with improved UX

#### AI & Search

- **Deep RAG**: Implemented RAG with pgvector and ModelScope embeddings for semantic document retrieval

### Changed

- **Dad mode BGM disabled**: Background music pauses automatically in dad mode and resumes when switching back to mom mode

### Fixed

- **Vite 8 dependency resolution**: Updated `@vitejs/plugin-react` to match Vite 8 peer dependencies so `npm ci` succeeds.
- **MediaPipe Hands build**: Switched to side-effect import + global `Hands` usage to avoid missing ESM named exports under Vite 8/Rolldown.
- **ESLint**: Removed `any` usage in MediaPipe global access.
- **SonarCloud reliability**: Fixed reliability and maintainability issues across frontend and backend
- **Code duplication**: Reduced duplication in `task.go`, `useTutorial.ts`, and other modules to meet SonarCloud quality gate (≤3%)
- **Vite 8 compatibility**: Updated `@vitejs/plugin-react` and switched MediaPipe Hands to side-effect import for Vite 8/Rolldown
- **Pearl shell gesture**: Fixed gesture recognition failure in pearl shell interaction
- **Pearl position**: Fixed pearl sprite positioning and pearl menu entry
- **Photo grid**: Fixed photo grid layout issues
- **Avatar display**: Fixed avatar rendering
- **Dad mode header**: Fixed header display issues in dad console
- **Dad task & whisper panels**: Polished panel layout and interactions
- **Docker build**: Fixed Dockerfile configuration
- **Staticcheck warnings**: Resolved staticcheck and nilness lint warnings in Go backend

### Security

- **Removed hardcoded AI user password** (SonarCloud S2068)
- **Frontend security hardening**: Addressed PR review security findings
- **Backend security hardening**: Addressed PR review security findings

### Dependencies

- Vite 7.3.1 → 8.0.0
- Vue 3.5.29 → 3.5.30
- golang.org/x/crypto 0.48.0 → 0.49.0
- puppeteer 24.38.0 → 24.39.1
- typescript-eslint 8.56.1 → 8.57.0
- @vitejs/plugin-vue 6.0.4 → 6.0.5
- GitHub Actions: checkout 4.3.1 → 6.0.2, upload-artifact 4.6.2 → 7.0.0, download-artifact 4.3.0 → 8.0.1
- SonarSource/sonarqube-scan-action 6.0.0 → 7.0.0

---

Expand Down
18 changes: 13 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,11 @@ AI-powered wellness platform combining emotional companionship, community suppor
| **Sisterhood Bond** | Community Q&A with verified healthcare professionals and content moderation |
| **Echo / Memoir** | Self-reflection space with AI-generated memoir stickers and partner connection |
| **Photo Gallery** | Photo wall with AI-generated images, lifecycle management, and drag/zoom UI |
| **Whisper** | Audio-to-text conversation using speech recognition |
| **Tasks / Dad Console** | Daily task board with T0/T1/T2 priority, proof photos, partner review, XP/level, skill radar + achievements, perk cards, and blind-box shell gifts |
| **Whisper** | Audio-to-text whisper tips with AI-generated scene guidance |
| **Tasks / Dad Console** | Daily task board with T0/T1/T2 priority, proof photos, partner review, XP/level, skill radar + achievements, perk cards, and future letters |
| **Dad Console** | Terminal-themed modular dad UI with chat, community, tasks, whisper, dashboard, profile, and memory cards |
| **Deep RAG** | Semantic document retrieval using pgvector embeddings for AI-grounded responses |
| **Entry & Auth** | Anime landing page with redesigned login/register flow and role selection |
| **Mobile & PWA** | Responsive mobile layout with portrait/landscape sprite configs, touch gestures, dynamic viewport units, and offline-capable service worker |
| **Admin Panel** | Embedded single-page admin at `/admin` — dashboard, user CRUD, config management |

Expand Down Expand Up @@ -55,9 +58,14 @@ MomShell/
│ └── pkg/ # Shared utilities (JWT, password, OpenAI, Firecrawl)
├── frontend/ # Vue 3 (Vite + TypeScript + Pinia)
│ └── src/
│ ├── components/ # Overlay panels + beach scene + React 3D shell
│ ├── composables/# Animation, parallax, waves, music, mobile detection
│ ├── lib/api/ # API client modules (chat, community, echo, photo, etc.)
│ ├── components/
│ │ ├── dad/ # Dad console modules (chat, tasks, whisper, dashboard, profile, etc.)
│ │ ├── overlay/# UI panels (Auth, Chat, Community, Whisper, Task, Landing, etc.)
│ │ ├── react/ # React 3D pearl shell scene
│ │ ├── scene/ # Beach scene layers (sky, ocean, sand, sprites)
│ │ └── task/ # Task dashboard visuals (skill radar, etc.)
│ ├── composables/# Animation, parallax, waves, music, mobile detection, tutorial
│ ├── lib/api/ # API client modules (chat, community, echo, photo, task, etc.)
│ ├── stores/ # Pinia stores (auth, UI)
│ ├── types/ # TypeScript type definitions
│ └── utils/ # Shared utility functions
Expand Down
2 changes: 1 addition & 1 deletion backend/internal/model/task.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ type AIGeneratedTask struct {
ID uint `gorm:"primaryKey"`
CoupleKey string `gorm:"type:varchar(80);uniqueIndex:idx_couple_date_type" json:"couple_key"`
Date string `gorm:"type:varchar(10);uniqueIndex:idx_couple_date_type" json:"date"`
Type string `gorm:"type:varchar(20);default:'task';uniqueIndex:idx_couple_date_type" json:"type"`
Type string `gorm:"type:varchar(50);default:'task';uniqueIndex:idx_couple_date_type" json:"type"`
AgeStage string `gorm:"type:varchar(20)" json:"age_stage"`
Content string `gorm:"column:tasks_json;type:text" json:"content"` // Reusing tasks_json column for content
CreatedAt time.Time `json:"created_at"`
Expand Down
43 changes: 34 additions & 9 deletions docs/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ Technical architecture overview of MomShell.
| **Go 1.25** | Backend language |
| **Gin** | HTTP framework |
| **GORM** | ORM (PostgreSQL) |
| **pgvector** | Vector similarity search for Deep RAG |
| **JWT (golang-jwt)** | Authentication (httpOnly cookies) |
| **OpenAI SDK** | LLM integration (Qwen / any OpenAI-compatible) |
| **Firecrawl** | Web search for grounding AI responses |
Expand All @@ -21,7 +22,7 @@ Technical architecture overview of MomShell.
| Technology | Purpose |
|------------|---------|
| **Vue 3** | UI framework |
| **Vite** | Build tool |
| **Vite 8** | Build tool |
| **TypeScript** | Type safety |
| **Pinia** | State management |
| **Axios** | HTTP client |
Expand All @@ -43,7 +44,8 @@ MomShell/
│ │ ├── fileutil/ # Shared file utilities (deletion helper)
│ │ ├── handler/ # HTTP handlers (Gin)
│ │ ├── middleware/ # Auth, CORS, recovery, rate limiting
│ │ ├── model/ # GORM models (User, Task, ShellGift, Achievement, PerkCard, etc.)
│ │ ├── model/ # GORM models (User, Task, Achievement, PerkCard,
│ │ │ # FutureLetter, RAGDocument, ChatMemory, etc.)
│ │ ├── repository/ # Data access layer
│ │ ├── router/ # Route registration
│ │ ├── scheduler/ # Background job scheduling (photo cleanup)
Expand All @@ -57,18 +59,25 @@ MomShell/
├── frontend/ # Vue 3 frontend
│ └── src/
│ ├── assets/
│ │ ├── audio/ # Background music and sound effects
│ │ ├── audio/ # Background music tracks
│ │ └── images/ # Scene sprites, icons, backgrounds
│ ├── components/
│ │ ├── dad/ # Dad console modules (DadConsole, DcHome, DcChat,
│ │ │ # DcCommunity, DcDashboard, DcTaskList, DcTaskCard,
│ │ │ # DcWhisper, DcProfile, DcAiMemory, DcHeader, DcTabBar,
│ │ │ # DcAgePicker, DcMemoryCardDialog)
│ │ ├── overlay/ # UI panels (Auth, Chat, Community, AiMemory, Bar, Car,
│ │ │ # Whisper, Task, ShellGift, Profile, RoleSelect, Landing, etc.)
│ │ │ # Whisper, Task, Profile, RoleSelect, AnimeLanding,
│ │ │ # NeutralLanding, ConfirmDialog)
│ │ ├── react/ # React components (PearlShell 3D scene)
│ │ ├── task/ # Task dashboard visuals (skill radar, etc.)
│ │ └── scene/ # Beach scene layers (sky, ocean, sand, etc.)
│ ├── composables/ # Vue composables (animation, parallax, waves, music, input)
│ ├── composables/ # Vue composables (animation, parallax, waves, music,
│ │ # mobile detection, tutorial, input handling)
│ ├── constants/ # Scene configuration
│ ├── lib/
│ │ ├── api/ # API modules (chat, community, echo, photo, task, perkCard, shellGift, user, whisper)
│ │ ├── api/ # API modules (chat, community, echo, photo, task,
│ │ │ # perkCard, user, whisper)
│ │ ├── apiClient.ts # Axios instance with JWT interceptor
│ │ └── auth.ts # Raw fetch auth calls (register, login, refresh)
│ ├── stores/ # Pinia stores (auth, UI)
Expand Down Expand Up @@ -125,6 +134,22 @@ Role-based system prompts adjust tone for mom, dad, and professional users.
- Crisis keywords trigger auto-rejection
- Results: Passed / Rejected / NeedManualReview

### Deep RAG

Semantic retrieval-augmented generation using pgvector:

- Documents are chunked and embedded via ModelScope-hosted embedding models
- Embeddings stored in PostgreSQL using the pgvector extension (`RAGDocument` model)
- At query time, vector similarity search retrieves relevant chunks to ground AI responses with factual context

### Future Letters

Replaced the shell gift system with a time-space care engine:

- Task completions trigger AI-generated future letters with contextual, time-aware messages
- `FutureLetter` model stores letter content, delivery timing, and association to tasks
- Mom receives meaningful letters over time rather than one-shot blind-box gifts

### Deployment Modes

- **Docker Compose**: Nginx + Go + PostgreSQL as separate containers, port 80
Expand All @@ -133,13 +158,13 @@ Role-based system prompts adjust tone for mom, dad, and professional users.
## Data Flow

```
Frontend (Vue 3 / Vite)
Frontend (Vue 3 / Vite 8)
↕ REST API (JSON)
Backend (Go / Gin)
↕ GORM
PostgreSQL
PostgreSQL + pgvector
↕ HTTP
OpenAI-compatible LLM
OpenAI-compatible LLM + ModelScope Embeddings
```

---
Expand Down
44 changes: 39 additions & 5 deletions docs/features.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,14 +50,15 @@ Photo management with AI-powered image generation.

## Whisper

Audio-to-text conversation feature.
Whisper intelligence with AI-powered scene guidance.

- **Speech recognition**: Convert spoken words to text for the AI companion
- **Conque shell metaphor**: Listen and speak through the beach shell
- **AI whisper tips**: Context-aware guidance and tips generated by AI
- **Scene guidance**: Whisper flows integrated with beach scene interaction
- **Dad whisper panel**: Dedicated whisper interface in dad console

## Tasks

Daily task execution and partner verification loop (Dad Console).
Daily task execution and partner verification loop.

- **Daily task board**: Dad sees today's tasks with a `pending → completed → verified` lifecycle and XP/level progression
- **AI task generation**: Tasks can be generated based on the baby's age stage, with categories and difficulty
Expand All @@ -67,7 +68,40 @@ Daily task execution and partner verification loop (Dad Console).
- **Progress polling**: UI polls for updates to keep task state in sync between partners
- **Skill radar + achievements**: Verified task scores aggregate into a six-dimension radar; achievements auto-unlock from seeded rules
- **Perk cards**: Mom can issue perk cards; Dad can redeem them (active/used/expired)
- **Shell gifts**: Completing a task can generate a blind-box shell gift for Mom (AI title/content + optional proof photo)
- **Future letters**: Replacing shell gifts — a time-space care engine generates contextual future letters from task completions, delivering meaningful messages over time
- **Memory cards**: AI-generated memory cards from task completions with mom view filtering

## Dad Console

Terminal-themed modular interface for dad users.

- **Empathetic Terminal theme**: Dark terminal-inspired UI with dedicated layout replacing the beach scene
- **Modular architecture**: Split into focused components — DcHome, DcChat, DcCommunity, DcTaskList, DcWhisper, DcDashboard, DcProfile
- **Dad chat**: Dedicated chat interface with AI companion tuned for dad role
- **Dad community**: Community board accessible within the console
- **Task management**: Task cards with priority badges, proof photo upload, and completion flow
- **Dashboard**: Skill radar, achievements overview, and perk card management
- **Profile page**: Dad profile with age picker and settings
- **AI memory panel**: View and manage AI memory facts within the console
- **Memory card dialog**: View AI-generated memory cards from completed tasks
- **No BGM**: Background music automatically pauses in dad mode

## Deep RAG

Semantic document retrieval for AI-grounded responses.

- **pgvector embeddings**: Document chunks stored as vector embeddings in PostgreSQL using pgvector extension
- **ModelScope embeddings**: Text embeddings generated via ModelScope-hosted models
- **Semantic search**: Vector similarity search for retrieving relevant context to ground AI responses

## Entry & Auth

Animated entry experience and authentication flow.

- **Anime landing page**: Full-screen animated landing for unauthenticated users
- **Redesigned login/register**: New authentication pages with improved UX
- **Role selection**: Post-auth role selection panel (mom/dad)
- **Interactive tutorial**: 7-step onboarding tour for new mom users using driver.js

## Beach Scene Navigation

Expand Down
9 changes: 7 additions & 2 deletions frontend/src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@
</template>

<script setup lang="ts">
import { computed, onMounted } from 'vue'
import { useBackgroundMusicLoop } from '@/composables/useBackgroundMusicLoop'
import { computed, onMounted, watch } from 'vue'
import { useBackgroundMusicLoop, pauseBackgroundMusic, playBackgroundMusic } from '@/composables/useBackgroundMusicLoop'
import AnimeLanding from '@/components/overlay/AnimeLanding.vue'
import DadConsole from '@/components/dad/DadConsole.vue'
import BeachScene from '@/components/scene/BeachScene.vue'
Expand All @@ -52,6 +52,11 @@ useBackgroundMusicLoop()

const isDad = computed(() => authStore.user?.role === 'dad')

watch(isDad, (dad) => {
if (dad) pauseBackgroundMusic()
else playBackgroundMusic()
}, { immediate: true })

onMounted(async () => {
// Always initialize auth state
await authStore.init()
Expand Down
16 changes: 14 additions & 2 deletions frontend/src/components/dad/DadConsole.vue
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@
:preview-url="proofPreviewUrl"
:uploading="proofUploading"
:error="completeDialogError"
:success="completeSuccess"
@close="closeCompleteDialog"
@upload="onProofFileChange"
@submit-without-photo="submitCompleteWithoutPhoto"
Expand Down Expand Up @@ -220,6 +221,7 @@
const [taskList, taskStats] = await Promise.all([getDailyTasks(), getTaskStats()])
tasks.value = taskList
stats.value = taskStats
error.value = ''
}

async function pollTasks() {
Expand All @@ -229,6 +231,7 @@
if (stats.value?.xp !== taskStats.xp || stats.value?.level !== taskStats.level) {
stats.value = taskStats
}
if (error.value) error.value = ''
} catch { /* ignore */ }
}

Expand Down Expand Up @@ -297,6 +300,7 @@
const proofUploading = ref(false)
const completeDialogError = ref('')
const proofPreviewUrl = ref('')
const completeSuccess = ref(false)

function resetProof() {
if (proofPreviewUrl.value) {
Expand All @@ -317,9 +321,17 @@
showCompleteDialog.value = false
completeTarget.value = null
completeDialogError.value = ''
completeSuccess.value = false
resetProof()
}

function showSuccessThenClose() {
completeSuccess.value = true
window.setTimeout(() => {

Check warning on line 330 in frontend/src/components/dad/DadConsole.vue

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Prefer `globalThis` over `window`.

See more on https://sonarcloud.io/project/issues?id=koishi510_MomShell&issues=AZ0FuJlgR1axg1qaXFS5&open=AZ0FuJlgR1axg1qaXFS5&pullRequest=181
closeCompleteDialog()
}, 1800)
}

function onProofFileChange(e: Event) {
const input = e.target as HTMLInputElement
const file = input.files?.[0] ?? null
Expand All @@ -340,7 +352,7 @@
try {
const updated = await completeTask(id)
tasks.value = tasks.value.map((t) => (t.id === id ? updated : t))
closeCompleteDialog()
showSuccessThenClose()
} catch (e) {
completeDialogError.value = getErrorMessage(e)
} finally {
Expand All @@ -359,7 +371,7 @@
const uploaded = await uploadPhoto(proofFile.value, `任务证明:${completeTarget.value.title}`)
const updated = await completeTask(id, { proof_photo_url: uploaded.image_url })
tasks.value = tasks.value.map((t) => (t.id === id ? updated : t))
closeCompleteDialog()
showSuccessThenClose()
} catch (e) {
completeDialogError.value = getErrorMessage(e)
} finally {
Expand Down
Loading
Loading