When relay mode is enabled, skip serving frontend assets through the relay tunnel to reduce bandwidth pressure. Instead, show a helpful page on root directing users to the official frontend at app.hapi.run.
Changes:
- server/src/web/server.ts: Add relayMode and officialWebUrl options, skip static serving in relay mode, show helpful page on root
- server/src/index.ts: Pass relayMode and officialWebUrl to startWebServer
Add tlsGate module to validate tunnel TLS certificates before announcing public access. This ensures the tunnel has a valid, trusted certificate before displaying the public URL to users. The validation checks certificate validity period, hostname matching (including wildcard support), and handles both DNS names and IP addresses.
Refactor tunnel access announcement to wait for TLS readiness asynchronously, preventing premature display of access links.
Integrates tunwg (WireGuard tunnel) to enable optional public access
to the hapi server. Tunnel is disabled by default and enabled via
--relay flag or HAPI_TUNNEL=true environment variable.
Users can now run 'hapi server --relay' and get a direct link like:
https://app.hapi.run/?server=https://xxx.relay.hapi.run&token=xxx
- Improved preview output columns: Removed id and tag columns, added Title (from metadata.summary.text), First Message (first user message), and human-readable Updated date
- Reordered columns for clarity: Updated, Msgs (fixed width), Title, First Message, Path
- Added --message=PATTERN filter option for fuzzy matching on first user message (case-insensitive)
- Fixed deletion count to use actual session count instead of result.changes (which included CASCADE deleted messages)
- Added helper functions: formatDate(), truncate(), extractUserText()
Implement a visibility-aware notification system that delivers toast messages via SSE to visible browser tabs instead of sending push notifications, reducing unnecessary push requests. Includes VisibilityTracker for monitoring connection visibility, toast UI components, and enhanced SSEManager with toast delivery capability.
Add configurable host binding for the Mini App HTTP server through:
- New `webappHost` configuration (defaults to 127.0.0.1 for security)
- CLI arguments `--host` and `--port` with flexible parsing (--host=value or --host value)
- Priority order: CLI args > env vars > settings.json > defaults
- Updated Bun.serve() to bind to the configured hostname
Modified:
- server/src/config/settings.ts
- server/src/config/serverSettings.ts
- server/src/configuration.ts
- server/src/web/server.ts
- server/src/index.ts
- cli/src/commands/server.ts
Extract permission and model mode validation into reusable functions utilizing
@hapi/protocol schemas. Use isPermissionModeAllowedForFlavor and
isModelModeAllowedForFlavor to validate modes based on session flavor (claude/codex).
Replace inline type definitions with shared types from @hapi/protocol.
Extract permission mode display logic into shared utilities for better reusability and maintainability. Add PermissionModeTone type and related helpers to centralize mode-based styling rules across components. Update components to use new PermissionModeOption type for consistent permission mode presentation.
Extracted five focused modules from SyncEngine to improve maintainability
and separation of concerns:
- EventPublisher: handles event broadcasting and listener management
- SessionCache: manages session state and lifecycle
- MachineCache: manages machine state and lifecycle
- MessageService: handles message storage and retrieval
- RpcGateway: handles RPC communication with sessions and machines
- aliveTime: utility for clamping and validating alive timestamps
Removed unused members (sessionMessages cache, fetchMessages,
getSessionMessages, setPermissionMode, setModelMode) that added
complexity without clear value.
SyncEngine now orchestrates these services as a lightweight facade,
improving code organization and testability.
Instead of throwing a schema mismatch error when version is 0 but tables already exist, set the version and return. This allows the database to properly initialize without erroring.
Replace legacy migration logic (ALTER TABLE, missing column checks) with explicit
schema version tracking. This prevents silent schema mismatches and simplifies the
database lifecycle—users must rebuild or offline-migrate on version mismatch.
Changes:
- Add SCHEMA_VERSION and REQUIRED_TABLES constants
- Refactor initSchema() to check version and table presence
- Extract createSchema() and helper methods (getUserVersion, setUserVersion, etc)
- Add compound indexes for better query performance (tag+namespace, platform+namespace)
- Store dbPath for better error messages
Extract notification logic from PushNotifier into a modular architecture
with NotificationHub as the central coordinator and NotificationChannel
interface for different notification providers (push, telegram). This
enables better separation of concerns and easier addition of new
notification channels in the future.
- Create NotificationHub to coordinate multiple notification channels
- Create NotificationChannel interface for channel implementations
- Move push notification logic to PushNotificationChannel
- Update HappyBot to implement NotificationChannel
- Simplify HappyBot by removing sync event handling (delegated to hub)
- Add notification helper utilities (sessionInfo, eventParsing)
- Update index.ts to use new notification architecture
Allow updateSessionMetadata to conditionally update the updated_at timestamp
by adding an optional touchUpdatedAt flag. When set to false, the timestamp is
not modified, enabling metadata updates without changing the last modified time.
Implement push notification system with VAPID keys, client service worker integration, and push subscription management. Includes server-side PushService for sending notifications and PushNotifier for reactive event handling, plus client-side usePushNotifications hook and service worker support.
Implements comprehensive session lifecycle management with user-friendly interactions:
Rename: Update session metadata.name via PATCH endpoint with conflict detection
Archive: Abort active sessions via DELETE endpoint with validation
Delete: Permanently remove inactive sessions with cascade cleanup
Backend:
- Store.deleteSession() removes session and cascade-deletes messages
- SyncEngine.renameSession() with concurrency error handling
- SyncEngine.deleteSession() with active session validation
- PATCH /sessions/:id for rename, DELETE /sessions/:id for delete
Frontend Components:
- RenameSessionDialog: Text input with auto-focus and error display
- SessionActionMenu: Modal with rename, archive, delete buttons
- ConfirmDialog: Reusable confirmation with error feedback
- SessionHeader: Menu button (⋮) triggering action menu
- SessionList: Long-press detection triggering item actions
Interactions:
- Long-press on session list items (500ms threshold) opens action menu
- Menu button in session header (non-Telegram environments only)
- Confirmation dialogs with descriptive warnings for destructive actions
- Real-time error display in dialogs on operation failure
- Haptic feedback on long-press via usePlatform hook
Accessibility:
- Keyboard support (Enter/Space) for long-press handler
- Focus management in RenameSessionDialog
- Proper ARIA labels and semantic HTML
- Added /health endpoint to server for readiness checks (no auth required)
- Created autoStartServer module that auto-starts server when:
- HAPI_SERVER_URL not set (using default localhost:3006)
- cliApiToken exists in settings (server previously used)
- Port 3006 is not currently listening
- Server runs as child process (not daemon) and exits when CLI exits
- Integrated maybeAutoStartServer() into hapi, codex, and gemini commands
Implement namespace support across sessions, machines, and users for multi-user server deployments. Add access control with specific error reasons (namespace-missing, access-denied, not-found) and database schema updates with namespace columns and indexes.
- Add LICENSE file to root and cli/ directories with LGPL-3.0-or-later text
- Create cli/NOTICE file with MIT attribution for happy-cli derived code
- Update license field in cli/, server/, and web/ package.json to "LGPL-3.0-or-later"
- Add NOTICE to cli/package.json files array for npm publishing
Implements bidirectional sync of permission/model modes between CLI sessions and web app. Adds Codex-specific permission modes (read-only, safe-yolo, yolo) alongside Claude's modes. Web can now control CLI session state via RPC set-session-config handler, while CLI broadcasts state changes through keep-alive payloads. UI controls are flavor-aware, showing appropriate modes for Claude vs Codex vs Gemini. Type centralization in api/types eliminates circular dependencies.