chore: Archive all pending OpenSpec proposals
Force archive the following proposals: - add-audio-device-selector (complete) - add-embedded-backend-packaging (19/26 tasks) - add-flexible-deployment-options (20/21 tasks) New specs created: - audio-device-management (7 requirements) - embedded-backend (8 requirements) Updated specs: - transcription (+2 requirements for model download progress) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,115 @@
|
||||
# Design: Embedded Backend Packaging
|
||||
|
||||
## Context
|
||||
Meeting Assistant uses a three-tier architecture: Electron Client → FastAPI Middleware → MySQL/Dify. For enterprise deployment, administrators want to distribute a single executable that users can run without additional setup. The backend must still connect to remote MySQL and Dify services (no local database).
|
||||
|
||||
**Stakeholders:**
|
||||
- Enterprise IT administrators (simplified deployment)
|
||||
- End users (double-click to run)
|
||||
- Developers (maintain backward compatibility)
|
||||
|
||||
## Goals / Non-Goals
|
||||
|
||||
### Goals
|
||||
- Package backend as a sidecar executable using PyInstaller
|
||||
- Electron manages backend lifecycle (start on launch, stop on close)
|
||||
- Single `config.json` for all configuration (frontend, backend, whisper)
|
||||
- Health check ensures backend is ready before showing UI
|
||||
- Backward compatible with existing separate-deployment mode
|
||||
- Show Whisper model download progress to improve UX
|
||||
|
||||
### Non-Goals
|
||||
- Embedding MySQL database (still remote)
|
||||
- Embedding LLM model (still uses Dify API)
|
||||
- Removing external authentication (still requires company SSO)
|
||||
- Pre-bundling Whisper model (user downloads on first run)
|
||||
|
||||
## Decisions
|
||||
|
||||
### Decision 1: Use PyInstaller for Backend Packaging
|
||||
**What:** Package FastAPI + uvicorn as standalone executable using PyInstaller `--onedir` mode.
|
||||
|
||||
**Why:**
|
||||
- Consistent with existing transcriber sidecar approach
|
||||
- `--onedir` provides faster startup than `--onefile`
|
||||
- Team already has PyInstaller expertise
|
||||
|
||||
**Alternatives considered:**
|
||||
- Nuitka: Better optimization but longer build times
|
||||
- cx_Freeze: Less community support for FastAPI
|
||||
|
||||
### Decision 2: Configuration via Extended config.json
|
||||
**What:** Add `backend` section to existing `config.json` with database, API, and auth settings.
|
||||
|
||||
**Why:**
|
||||
- Single configuration file for users to manage
|
||||
- Runtime modifiable without rebuilding
|
||||
- Consistent with existing whisper config pattern
|
||||
|
||||
**Schema:**
|
||||
```json
|
||||
{
|
||||
"apiBaseUrl": "http://localhost:8000/api",
|
||||
"backend": {
|
||||
"embedded": true,
|
||||
"host": "127.0.0.1",
|
||||
"port": 8000,
|
||||
"database": { "host": "", "port": 33306, "user": "", "password": "", "database": "" },
|
||||
"externalApis": { "authApiUrl": "", "difyApiUrl": "", "difyApiKey": "", "difySttApiKey": "" },
|
||||
"auth": { "adminEmail": "", "jwtSecret": "", "jwtExpireHours": 24 }
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Decision 3: Health Check Before Window Display
|
||||
**What:** Electron polls `/api/health` endpoint before creating main window.
|
||||
|
||||
**Why:**
|
||||
- Prevents "connection refused" errors on startup
|
||||
- Provides clear feedback if backend fails to start
|
||||
- Maximum 30 attempts with 1-second intervals
|
||||
|
||||
### Decision 4: Backward Compatibility via Feature Flag
|
||||
**What:** `backend.embedded: false` (default) preserves existing behavior; `true` enables embedded mode.
|
||||
|
||||
**Why:**
|
||||
- Existing deployments continue working unchanged
|
||||
- Gradual migration path for enterprises
|
||||
- Same codebase supports both deployment models
|
||||
|
||||
### Decision 5: Huggingface Hub Progress Callback for Model Download
|
||||
**What:** Intercept huggingface_hub download progress and emit JSON status messages.
|
||||
|
||||
**Why:**
|
||||
- faster-whisper uses huggingface_hub internally
|
||||
- Can emit progress without modifying faster-whisper source
|
||||
- JSON format consistent with existing sidecar protocol
|
||||
|
||||
## Risks / Trade-offs
|
||||
|
||||
| Risk | Impact | Mitigation |
|
||||
|------|--------|------------|
|
||||
| PyInstaller hidden imports missing | Backend fails to start | Comprehensive hidden-import list; test on clean Windows |
|
||||
| Config file contains sensitive data | Security exposure | Document security best practices; consider encryption |
|
||||
| Backend startup timeout | Poor UX | Increase timeout; show loading indicator |
|
||||
| Port 8000 already in use | Backend fails | Allow configurable port; detect and report conflicts |
|
||||
|
||||
## Migration Plan
|
||||
|
||||
### For New Deployments (All-in-One)
|
||||
1. Build with `--embedded-backend` flag
|
||||
2. Configure `config.json` with database/API credentials
|
||||
3. Distribute single exe to users
|
||||
|
||||
### For Existing Deployments (Separate Backend)
|
||||
1. No changes required
|
||||
2. Ensure `backend.embedded: false` in config
|
||||
3. Continue using existing backend deployment
|
||||
|
||||
### Rollback
|
||||
- Set `backend.embedded: false` to disable embedded backend
|
||||
- Deploy backend separately as before
|
||||
|
||||
## Open Questions
|
||||
- Should we add config validation UI on first startup?
|
||||
- Should backend port be auto-discovered if 8000 is in use?
|
||||
@@ -0,0 +1,28 @@
|
||||
# Change: Add Embedded Backend Packaging for All-in-One Deployment
|
||||
|
||||
## Why
|
||||
Currently, deploying Meeting Assistant requires setting up both the Electron client and a separate backend server. For enterprise internal deployment, users want a simpler experience: **double-click the exe and it works** without needing to understand or configure backend services separately.
|
||||
|
||||
Additionally, when users first run the packaged application, the Whisper model download (~1.5GB) shows only "loading_model" status with no progress indication, causing confusion about whether the download is actually happening.
|
||||
|
||||
## What Changes
|
||||
- **New capability: Embedded Backend** - Package FastAPI backend as a sidecar managed by Electron
|
||||
- **Backend sidecar management** - Electron starts/stops backend process automatically
|
||||
- **Health check mechanism** - Wait for backend readiness before loading frontend
|
||||
- **Configuration unification** - All settings (DB, API keys, auth) in single `config.json`
|
||||
- **Backward compatible** - Existing deployment method (separate backend) still works via `backend.embedded: false` flag
|
||||
- **Model download progress** - Show real-time download percentage for Whisper model
|
||||
|
||||
## Impact
|
||||
- Affected specs: `embedded-backend` (new), `transcription` (modified)
|
||||
- Affected code:
|
||||
- `backend/run_server.py` (new) - Backend entry point for packaging
|
||||
- `backend/build.py` (new) - PyInstaller build script
|
||||
- `backend/app/config.py` - Support frozen executable paths
|
||||
- `client/src/main.js` - Backend sidecar management
|
||||
- `client/src/preload.js` - Expose backend status API
|
||||
- `client/config.json` - Extended configuration schema
|
||||
- `client/package.json` - Build configuration for backend resources
|
||||
- `sidecar/transcriber.py` - Model download progress reporting
|
||||
- `scripts/build-client.bat` - Integrated build script
|
||||
- `scripts/build-all.ps1` - PowerShell build script
|
||||
@@ -0,0 +1,89 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Embedded Backend Packaging
|
||||
The FastAPI backend SHALL be packaged as a standalone executable using PyInstaller for all-in-one deployment.
|
||||
|
||||
#### Scenario: Backend executable creation
|
||||
- **WHEN** build script runs with embedded backend flag
|
||||
- **THEN** PyInstaller SHALL create `backend/dist/backend/backend.exe` containing FastAPI, uvicorn, and all dependencies
|
||||
|
||||
#### Scenario: Backend executable startup
|
||||
- **WHEN** backend executable is launched
|
||||
- **THEN** it SHALL read configuration from `config.json` in the same directory
|
||||
- **AND** start uvicorn server on configured host and port
|
||||
|
||||
### Requirement: Electron Backend Sidecar Management
|
||||
The Electron main process SHALL manage the embedded backend as a sidecar process.
|
||||
|
||||
#### Scenario: Start backend on app launch
|
||||
- **WHEN** Electron app launches with `backend.embedded: true` in config
|
||||
- **THEN** main process SHALL spawn backend executable as child process
|
||||
- **AND** pass configuration via environment variables
|
||||
|
||||
#### Scenario: Skip backend when disabled
|
||||
- **WHEN** Electron app launches with `backend.embedded: false` in config
|
||||
- **THEN** main process SHALL NOT spawn backend executable
|
||||
- **AND** frontend SHALL connect to remote backend via `apiBaseUrl`
|
||||
|
||||
#### Scenario: Terminate backend on app close
|
||||
- **WHEN** user closes Electron app
|
||||
- **THEN** main process SHALL send SIGTERM to backend process
|
||||
- **AND** force kill after 5 seconds if still running
|
||||
|
||||
### Requirement: Backend Health Check
|
||||
The Electron main process SHALL verify backend readiness before showing the main window.
|
||||
|
||||
#### Scenario: Health check success
|
||||
- **WHEN** backend `/api/health` returns HTTP 200
|
||||
- **THEN** main process SHALL proceed to create main window
|
||||
- **AND** set `backendReady` state to true
|
||||
|
||||
#### Scenario: Health check timeout
|
||||
- **WHEN** backend does not respond within 30 seconds (30 attempts, 1s interval)
|
||||
- **THEN** main process SHALL display error dialog
|
||||
- **AND** log detailed error for debugging
|
||||
|
||||
#### Scenario: Health check polling
|
||||
- **WHEN** health check attempt fails
|
||||
- **THEN** main process SHALL retry after 1 second
|
||||
- **AND** log attempt number for debugging
|
||||
|
||||
### Requirement: Unified Configuration Schema
|
||||
All configuration for frontend, backend, and whisper SHALL be in a single `config.json` file.
|
||||
|
||||
#### Scenario: Backend configuration loading
|
||||
- **WHEN** backend sidecar starts
|
||||
- **THEN** it SHALL read database credentials from `config.json` backend.database section
|
||||
- **AND** read API keys from `config.json` backend.externalApis section
|
||||
- **AND** read auth settings from `config.json` backend.auth section
|
||||
|
||||
#### Scenario: Configuration priority
|
||||
- **WHEN** both environment variable and config.json value exist
|
||||
- **THEN** environment variable SHALL take precedence
|
||||
|
||||
#### Scenario: Default values
|
||||
- **WHEN** configuration value is not specified
|
||||
- **THEN** system SHALL use sensible defaults (host: 127.0.0.1, port: 8000)
|
||||
|
||||
### Requirement: Backend Status API
|
||||
The Electron app SHALL expose backend status to the renderer process.
|
||||
|
||||
#### Scenario: Get backend status
|
||||
- **WHEN** renderer calls `window.electronAPI.getBackendStatus()`
|
||||
- **THEN** it SHALL return object with `ready` boolean and `url` string
|
||||
|
||||
#### Scenario: Backend status in UI
|
||||
- **WHEN** backend is starting
|
||||
- **THEN** UI MAY display loading indicator
|
||||
|
||||
### Requirement: Backward Compatibility
|
||||
The embedded backend feature SHALL NOT break existing separate-deployment mode.
|
||||
|
||||
#### Scenario: Separate deployment unchanged
|
||||
- **WHEN** `backend.embedded` is false or undefined
|
||||
- **THEN** system SHALL behave exactly as before this change
|
||||
- **AND** frontend connects to `apiBaseUrl` without spawning local backend
|
||||
|
||||
#### Scenario: Existing scripts work
|
||||
- **WHEN** user runs `./start.sh start` or `./scripts/setup-backend.sh`
|
||||
- **THEN** backend SHALL start normally as standalone server
|
||||
@@ -0,0 +1,40 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Model Download Progress Display
|
||||
The sidecar SHALL report Whisper model download progress to enable UI feedback.
|
||||
|
||||
#### Scenario: Emit download start
|
||||
- **WHEN** Whisper model download begins
|
||||
- **THEN** sidecar SHALL emit JSON to stdout: `{"status": "downloading_model", "model": "<size>", "progress": 0, "total_mb": <size>}`
|
||||
|
||||
#### Scenario: Emit download progress
|
||||
- **WHEN** download progress updates
|
||||
- **THEN** sidecar SHALL emit JSON: `{"status": "downloading_model", "progress": <percent>, "downloaded_mb": <current>, "total_mb": <total>}`
|
||||
- **AND** progress updates SHALL occur at least every 5% or every 5 seconds
|
||||
|
||||
#### Scenario: Emit download complete
|
||||
- **WHEN** model download completes
|
||||
- **THEN** sidecar SHALL emit JSON: `{"status": "model_downloaded", "model": "<size>"}`
|
||||
- **AND** proceed to model loading
|
||||
|
||||
#### Scenario: Skip download for cached model
|
||||
- **WHEN** model already exists in huggingface cache
|
||||
- **THEN** sidecar SHALL NOT emit download progress messages
|
||||
- **AND** proceed directly to loading
|
||||
|
||||
### Requirement: Frontend Model Download Progress Display
|
||||
The Electron frontend SHALL display model download progress to users.
|
||||
|
||||
#### Scenario: Show download progress in transcript panel
|
||||
- **WHEN** sidecar emits download progress
|
||||
- **THEN** whisper status element SHALL display download percentage and size
|
||||
- **AND** format: "Downloading: XX% (YYY MB / ZZZ MB)"
|
||||
|
||||
#### Scenario: Show download complete
|
||||
- **WHEN** sidecar emits model_downloaded status
|
||||
- **THEN** whisper status element SHALL briefly show "Model downloaded"
|
||||
- **AND** transition to loading state
|
||||
|
||||
#### Scenario: Forward progress events via IPC
|
||||
- **WHEN** main process receives download progress from sidecar
|
||||
- **THEN** it SHALL forward to renderer via `model-download-progress` IPC channel
|
||||
@@ -0,0 +1,39 @@
|
||||
# Tasks: Add Embedded Backend Packaging
|
||||
|
||||
## 1. Backend Packaging Infrastructure
|
||||
- [x] 1.1 Create `backend/run_server.py` - Entry point that loads config and starts uvicorn
|
||||
- [x] 1.2 Create `backend/build.py` - PyInstaller build script with hidden imports
|
||||
- [x] 1.3 Modify `backend/app/config.py` - Support frozen executable path detection
|
||||
- [ ] 1.4 Test backend executable runs standalone on Windows
|
||||
|
||||
## 2. Electron Backend Sidecar Management
|
||||
- [x] 2.1 Add `backendProcess` and `backendReady` state variables in `main.js`
|
||||
- [x] 2.2 Implement `startBackendSidecar()` function
|
||||
- [x] 2.3 Implement `waitForBackendReady()` health check polling
|
||||
- [x] 2.4 Modify `app.whenReady()` to start backend before window
|
||||
- [x] 2.5 Modify window close handler to terminate backend process
|
||||
- [x] 2.6 Add `get-backend-status` IPC handler
|
||||
|
||||
## 3. Configuration Schema Extension
|
||||
- [x] 3.1 Extend `client/config.json` with `backend` section
|
||||
- [x] 3.2 Modify `client/src/preload.js` to expose backend status API
|
||||
- [x] 3.3 Add configuration loading in backend entry point
|
||||
- [ ] 3.4 Document configuration options in DEPLOYMENT.md
|
||||
|
||||
## 4. Build Script Integration
|
||||
- [x] 4.1 Modify `scripts/build-client.bat` to build backend sidecar
|
||||
- [ ] 4.2 Modify `scripts/build-all.ps1` to build backend sidecar
|
||||
- [x] 4.3 Update `client/package.json` extraResources for backend
|
||||
- [x] 4.4 Add `--embedded-backend` flag to build scripts
|
||||
|
||||
## 5. Model Download Progress Display
|
||||
- [x] 5.1 Modify `sidecar/transcriber.py` to emit download progress JSON
|
||||
- [x] 5.2 Add progress event forwarding in `main.js`
|
||||
- [x] 5.3 Expose `onModelDownloadProgress` in `preload.js`
|
||||
- [x] 5.4 Update `meeting-detail.html` to display download progress
|
||||
|
||||
## 6. Testing and Documentation
|
||||
- [ ] 6.1 Test embedded mode on clean Windows machine
|
||||
- [ ] 6.2 Test backward compatibility (embedded: false)
|
||||
- [ ] 6.3 Test model download progress display
|
||||
- [ ] 6.4 Update DEPLOYMENT.md with all-in-one deployment instructions
|
||||
Reference in New Issue
Block a user