- Connection errors (ECONNREFUSED, ETIMEDOUT, ENOTFOUND, "Network Error") show
a friendly message with the server URL and network troubleshooting hints
- Authentication errors (401, 403, "unauthorized", "forbidden") suggest running
`hapi auth login` to help users resolve auth issues
- Use case-insensitive matching (toLowerCase) to reliably catch error message
variants
The settings popup in HappyComposer did not show any option selected when
permissionMode or modelMode was null, since destructuring defaults only
handle undefined, not null. This fix uses the ?? operator to properly
handle both null and undefined cases, falling back to 'default' in both.
Adds touch device detection via media query (pointer: coarse) to prevent
triggering virtual keyboard on mobile. Input auto-focus is now conditional
on desktop environments where it improves keyboard-based interactions.
- Make TELEGRAM_BOT_TOKEN and ALLOWED_CHAT_IDS optional environment variables
- Add telegramEnabled flag to conditionally initialize the bot on startup
- Introduce persistent owner ID for unified user identity across web and Telegram auth
- Update Telegram bot to accept configuration in constructor instead of using global config
- Handle empty allowlist by showing chat ID prompt on /start command
- Use owner ID instead of Telegram user ID for API authentication
- Add conditional Telegram support checks in auth routes with clear error messages
- Update documentation to explain optional Telegram configuration and binding workflow
- Rename telegramUserId to userId in auth middleware for clarity
Add helper functions to identify and split task children into pending
permission blocks and other details, allowing permission prompts to display
immediately while keeping other task details collapsible.
- Add back buttons to MachinesPage and SpawnPage for non-Telegram environments
- Fix navigation after session creation to clear spawn flow from history
- Update useAppGoBack hook to use explicit path navigation for consistent behavior
- Add support for running CLI from TypeScript source when using tsx or similar tools
- Fix outdated happy__change_title reference to hapi__change_title in codex prompt
- Replace embeddedAssets stub with generated type definitions
- Fix Bun.isCompiled access with proper type assertion to prevent undefined errors
- Improve router search validation with explicit SessionFileSearch type
- Simplify middleware return patterns for better readability
Consolidate CLI and server runtime directories from ~/.config/hapi/ (CLI) and ~/.hapi-server/ (Server) to a single ~/.hapi/ directory. Unify environment variables from HAPI_HOME_DIR (CLI) and HAPI_BOT_DATA_DIR (Server) to a single HAPI_HOME variable across both applications. Update all documentation and configuration references accordingly. Bump bun-types to 1.3.5.
This fixes an issue where viewport-fit=cover and black-translucent statusbar
configuration allowed content to extend under the iOS statusbar. Added env(safe-area-inset-top)
CSS handling to all main layout components:
- SessionHeader with pt-[env(safe-area-inset-top)]
- SessionsPage, MachinesPage, SpawnPage with safe-area padding
- FilesPage and FilePage headers with safe-area padding
This commit rebrands the project from "Happy" to "HAPI" throughout the codebase, including documentation, comments, logs, and tool references. It also adds comprehensive README files for the server and web components, clarifies the monorepo structure in AGENTS.md and root README.md, and removes the outdated roadmap.md file.
Changes include:
- Rebrand references from Happy to HAPI in CLI, server, and web components
- MCP tool names updated from mcp__happy__ to mcp__hapi__
- Process/service names updated consistently
- New server/README.md with deployment and configuration guide
- New web/README.md with stack and development instructions
- Updated root README.md with quickstart guide
- Updated AGENTS.md with cleaner structure documentation
- Removed cli/roadmap.md (now superseded by documentation)
Implements comprehensive ACP backend enabling integration with ACP-compliant agents like Gemini. Includes stdio transport, message handling, permission flow, and registry for agent management. Adds new 'hapi gemini' command to launch ACP agent sessions.
Implement CLI output message type for displaying command output from user/assistant messages. Adds CliOutputBlock component and type with detection logic based on message metadata and CLI tags. Includes merging of adjacent CLI output blocks for cleaner presentation. Enhance layout throughout components with proper overflow handling and width constraints for improved text wrapping and scrolling behavior.
Implement support for bundling web assets into CLI single executable binaries.
When built with --with-web-assets, the executable includes the compiled web
application and serves it directly without file system access. A stub generator
creates empty manifests for normal builds to maintain compatibility.
Key changes:
- Add --with-web-assets flag to build-executable.ts with manifest validation
- Generate embeddedAssets.ts manifest from web/dist during build
- Serve embedded assets in web server with fallback to file system
- Add hapi server subcommand to start API + web server
- Include server sources in CLI tsconfig for compilation scope
- Add workspace-level build:single-exe scripts for production builds
Split embedded assets loading into runtime-specific variants using package.json imports field. Bun-compiled binaries use the full implementation with file assets, while stub fallback provides clear error for non-Bun runtimes.
Adds scrollRestoration: true to createRouter configuration to preserve
scroll position when navigating between pages, improving navigation UX
when switching between views like sessions list and session details.
Enables building hapi as standalone Bun-compiled executables for macOS,
Linux, and Windows (x64/arm64). Adds build script, bootstrap entry point,
runtime asset management, and automatic deployment of bundled tools
(ripgrep, difftastic). Includes MCP stdio bridge support and proper
environment handling for compiled binaries. Updates documentation with
build and installation instructions for single executable distribution.
- Show selected answers with green borders and checkmarks in the question view
- Use circles (●/○) for single-select and squares (☑/☐) for multi-select
- Multi-question titles now show "N Questions" with subtitle "(+N more)"
- Remove redundant Single/Multi badges from footer
- Hide empty Result section when answers are shown in the view
- Dialog header updates to "Questions & Answers" when answered
- Handle freeform/fallback answers gracefully in all display modes
Replace state-based screen navigation with proper URL-based routing. This includes:
- New router configuration with routes for sessions, machines, and spawn pages
- App context provider to share API and token across the app
- useAppGoBack hook for handling browser and Telegram back navigation
- Refactored App component to render outlet and use router hooks
- Memory history for Telegram app, browser history for web
Introduce runtime path abstraction for Bun-compiled binaries that extracts
assets to ~/.happy/runtime/{version} instead of using project paths. This
enables proper distribution of CLI as a self-contained binary with embedded
tools (ripgrep, difftastic) and scripts that are extracted at runtime.
Replace hardcoded 'node' commands with process.execPath to support
Bun runtime alongside Node.js. Add runtime detection and entrypoint
resolution for Bun. Update documentation to reflect multi-runtime support.
- web/src/components/AssistantChat/messages/UserMessage.tsx now subscribes only to role, text, status,
and localId instead of the entire message object to avoid re-renders caused by unrelated message state
changes (hover/isLast/etc.).
- web/src/components/AssistantChat/messages/SystemMessage.tsx now subscribes only to role, text, and icon
for the same reason.
- This reduces unnecessary renders observed in React DevTools without changing message UI or behavior.
Replace manual state management with TanStack Query (React Query) for more robust server state handling. This refactoring introduces:
- New hooks for queries: useSessions, useSession, useMessages, useMachines
- New hooks for mutations: useSendMessage, useSessionActions, useSpawnSession
- Centralized query client with optimized configuration (5s staleTime, disabled window focus refetch)
- Query key factory for consistent cache invalidation
- Improved message synchronization via socket events with cache updates
- Optimistic updates for message sending with retry capability
- Simplified App.tsx by removing manual state management logic
- Integrated React Query devtools in development mode
This enables automatic cache management, better error handling, and a foundation for more sophisticated data fetching patterns.
Wrap SessionHeader content in a centered container using the same
mx-auto w-full max-w-[720px] pattern as HappyThread to ensure the
back button and session info align with the main content area instead
of appearing at the top-left corner.
Slim down SessionSummary responses to reduce payload size:
- Replace full todos array with computed todoProgress summary
- Replace metadata object with only necessary fields (name, path, summary.text)
- Remove unused fields (thinking, createdAt, permissionMode, modelMode)
- Refactor sorting to work on full Session objects before mapping
This significantly reduces /api/sessions response size, especially for
sessions with many todos or tools.
Use the cached message converter from @assistant-ui/react to prevent
re-converting all messages on every render. The previous implementation
called convertMessage for every ChatBlock on each render cycle, creating
new objects (Date, arrays, metadata) that triggered unnecessary state
updates and re-render storms.
The new implementation:
- Uses useExternalMessageConverter which internally caches via WeakMap
- Memoizes callbacks with useCallback for stable references
- Memoizes the adapter object to prevent subscription churn
Implement block reconciliation to maintain object identity across renders when content hasn't changed, reducing unnecessary re-renders. Add memoization and performance optimizations to ToolCard component.
Enable concurrent web development workflow with Vite HMR instead of requiring pre-build. Configure Vite server to listen on 0.0.0.0 for LAN access, proxy /api and /socket.io to backend (127.0.0.1:3006), and run dev:server and dev:web together.
The conditional Telegram SDK loading (commit 4606ba2) caused dark mode to
break in non-Telegram browsers. Added dark mode CSS variable overrides with
proper fallbacks, and restored the module-level applyTheme() call that applies
theme before React renders, preventing a flash of incorrect styling.
- web/src/index.css: Added dark mode overrides for primary colors (--app-bg,
--app-fg, --app-hint, --app-link, --app-button, --app-button-text,
--app-secondary-bg) with system-appropriate dark fallbacks when Telegram
theme variables are unavailable
- web/src/hooks/useTheme.ts: Restored module-level applyTheme(currentScheme)
call to ensure theme is applied before React renders
Add comprehensive support for the AskUserQuestion tool including:
- New footer component for handling user responses with multi-step question flow
- Type definitions and parsing utilities for question and answer formats
- View component for displaying questions and options
- Integration with permission system to capture user answers
- Support for single and multi-select questions with optional text input
- Haptic feedback and error handling for better UX
Add lazy loading of Telegram SDK only when running inside Telegram Mini App
environment instead of unconditionally loading in all browsers. Includes:
- New environment detection functions: isTelegramEnvironment(), isTelegramApp()
- Dynamic SDK loading with 3s timeout via loadTelegramSdk()
- Removed static script tag from index.html
- Made haptic feedback lazy (SDK check on each call)
- Made theme listeners lazy (attached in initializeTheme())
- Updated all components to use unified detection functions
This prevents SDK load time overhead in regular browser environments while
ensuring the app works correctly both in Telegram and browser contexts.
Improve service worker update handling to fix caching issues during development:
- Add skipWaiting and clientsClaim in Workbox config for immediate SW activation
- Remove user confirmation prompt and switch to silent automatic updates
- Replace hourly polling with visibility-based update checks via visibilitychange event
This resolves the issue where web updates would not take effect without manual cache clearing.
Remove unreliable conditions from Telegram environment detection in useAuthSource:
- window.Telegram !== undefined: Always true due to unconditional SDK loading
- window.self !== window.top: Causes false positives in iframe scenarios
Only keep URL parameter detection (tgWebApp in search/hash) which is reliable.
This prevents 5-second polling delay before login page displays on PC browser.
Syncs React routing state with browser History API. Clicking the browser
back button now navigates within the app instead of exiting. Telegram
BackButton behavior is preserved by checking for initData.
Replaces react-shiki with a custom minimal Shiki highlighter to significantly reduce bundle size. Only loads 29 common languages and 2 themes (github-light/dark), using the JavaScript RegExp engine instead of WASM.
- Reduced web bundle from 5.8MB to 2.5MB (57% reduction)
- Saves 622KB by avoiding WASM runtime
- Graceful fallback for unsupported languages
- Removed react-shiki dependency
- Added @shikijs/langs, @shikijs/themes, shiki, hast-util-to-jsx-runtime
- Added light mode CSS rules for syntax highlighting
- Add iOS Safari install prompt with step-by-step modal guide
- Fix Telegram environment detection (check initData, not just SDK presence)
- Fix install prompt re-entrancy issue (clear deferredPrompt immediately)
- Extract icon components to separate file (web/src/components/icons.tsx)
- Rename "Happy App" to "Hapi" throughout the UI and manifests
- Change button/icon colors from blue (--app-button) to neutral theme (--app-fg/--app-bg)
- Add install dismiss state to prevent repeated prompts
- Improve iOS Safari detection with robust user agent parsing
Add complete PWA implementation including service worker registration,
offline support, and installation prompts:
- Add vite-plugin-pwa and workbox-window dependencies for PWA tooling
- Configure VitePWA plugin with web app manifest and app metadata
- Set up Workbox caching strategies for API endpoints and CDN assets
- Implement service worker auto-update with user-triggered refresh
- Create usePWAInstall hook to handle beforeinstallprompt events
- Create useOnlineStatus hook for monitoring network connectivity
- Add InstallPrompt component with haptic feedback integration
- Add OfflineBanner component to notify users of offline status
- Configure PWA icons and assets (64x64, 192x192, 512x512 variants)
- Add TypeScript type declarations for virtual PWA register module
- Integrate PWA components and service worker into App.tsx and main.tsx
- Add PWA meta tags and viewport configuration to index.html
Replace no-op browser haptic feedback with Web Vibration API support,
allowing haptic feedback when running outside Telegram Mini App. Also
remove stale react-syntax-highlighter type reference from tsconfig.
Enable the web client to run in plain browser environments alongside Telegram Mini App support:
- Server: Add CLI_API_TOKEN authentication path as alternative to Telegram initData
- Client: Add useAuthSource hook to detect and manage Telegram vs browser auth sources
- Client: Add usePlatform hook for platform abstraction with graceful haptic feedback degradation
- Client: Add LoginPrompt component for browser access token login
- Client: Extend useTheme to fall back to system prefers-color-scheme in browser
- Client: Migrate all direct HapticFeedback calls to use usePlatform hook
Consolidate markdown rendering logic into dedicated assistant-ui components and update syntax highlighting to use Shiki with GitHub themes. Removes dependency on react-markdown and react-syntax-highlighter in favor of @assistant-ui/react-markdown with Shiki-based highlighting.
Consolidate markdown rendering logic into dedicated assistant-ui components and update syntax highlighting to use Shiki with GitHub themes. Removes dependency on react-markdown and react-syntax-highlighter in favor of @assistant-ui/react-markdown with Shiki-based highlighting.
- Refactor HappyComposer settings overlay to conditionally render permission and model settings based on their availability
- Add showPermissionSettings and showModelSettings flags for cleaner conditional rendering
- Enhance ToolMessage fallback UI with styled card layout and code blocks for arguments and results
- Improve type validation in isToolCallBlock with comprehensive property checks
- Add safeStringify utility for robust JSON serialization with fallback handling
Add underscore to the regex pattern in getProjectPath to ensure underscores
are replaced with hyphens, along with existing handling for slashes, colons,
and dots. Includes test case for paths with underscores.
Remove 5 unused component files that were not imported anywhere:
- SessionDetail.tsx (replaced by SessionChat)
- PermissionPanel.tsx (only used by dead SessionDetail)
- MessageList.tsx
- PermissionBanner.tsx
- PermissionDialog.tsx
Confirmed via grep searches and successful build.
- Unify session title logic across components to check metadata.name first
- Add Telegram Web App detection with re-check after mount
- Hide header and buttons when running in Telegram environment
- Replace host display with path information in session details
- Remove unused Badge components for session status
- Simplify SessionList and SessionHeader layouts
Adds todo tracking infrastructure with TodoWrite tool integration to extract
and persist todos in sessions. Refactors ToolCard component to support
custom tool view rendering and displays todo progress in SessionList.
- Display connection status indicators (online, offline, thinking, permission required) in ChatInput with dynamic vibing messages
- Add context size percentage display showing remaining context availability
- Track latest usage data in reducer with inputTokens, outputTokens, cache metrics, and contextSize
- Calculate contextSize from message usage data and expose via latestUsage in reduceChatBlocks
- Pass thinking, agentState, and contextSize props to ChatInput component
- Remove redundant status indicators from SessionHeader (moved to ChatInput for unified display)
Extract word detection and suggestion logic into reusable utilities and hooks.
Add FloatingOverlay and Autocomplete components for intelligent input assistance.
Integrate settings panel and abort button directly into ChatInput component.
Simplify SessionHeader by removing settings dialog (now in ChatInput).
Implements comprehensive token management with intelligent priority resolution.
Token sources (highest to lowest priority): environment variable, settings file,
interactive prompt. Changes include:
- Updated home directory from ~/.happy to ~/.config/hapi (env var: HAPI_HOME_DIR)
- Added cliApiToken field to Settings interface for persistent storage
- Made cliApiToken mutable in Configuration class (private field with getter/setter)
- Created ui/tokenInit.ts module for token initialization with fallback prompt
- Enhanced auth command: login (interactive input), logout (clear token), status (show source)
- Updated doctor command to correctly identify token source and mask saved token in output
- Token initialization called early in startup flow to ensure availability before API use