Skip to content

Comments

feat(ui): migrate to Vite React with Heidi backend integration#78

Merged
heidi-dang merged 1 commit intomainfrom
feat/ui-work-theme
Feb 17, 2026
Merged

feat(ui): migrate to Vite React with Heidi backend integration#78
heidi-dang merged 1 commit intomainfrom
feat/ui-work-theme

Conversation

@heidi-dang
Copy link
Owner

Part 1: UI Migration + Backend Integration

What Changed:

  • Replaced legacy UI with Vite-based React application
  • New structure: ui/src/ with components, API layer, and types
  • API client (src/api/heidi.ts): health, listAgents, listRuns, getRun, runOnce, runLoop, chat, cancelRun
  • Streaming support (src/api/stream.ts): SSE with polling fallback
  • Components migrated: Sidebar, ChatArea, AgentArea, TerminalArea, SettingsModal, RightSidebar
  • Vite config: port 3002, allowedHosts (heidiai.com.au), proxy to backend :7777

What Did NOT Change (Intentionally Excluded):

  • SSH Terminal: MVP placeholder only (Phase 2 - full SSH connector later)
  • No direct AI model keys in browser (all calls routed through Heidi backend)
  • No socket.io or SSH credentials handled in UI for this release

Part 2: Packaging, Serving, CI, and Documentation

What Changed:

  • heidi ui build: builds with --base=/ui/, outputs to ~/.cache/heidi/ui/dist
  • Backend serves /ui/ with SPA fallback routing (redirects /ui/ui/, serves index.html for unknown paths)
  • pyproject.toml: includes ui_dist/**/* in package-data for wheel/sdist
  • .github/workflows/ci.yml: added ui-build job (Node 20, npm caching, verifies dist artifacts)
  • README.md: added Web UI section with dev/prod workflows and port reference table
  • .local/worklog: added with migration summary and date (2026-02-17)
  • .gitignore: granular policy for .local/ (tracks docs/worklog, ignores secrets/state/cache)

How to Test:

# Clean install
pip install -e '.[dev]'

# Build UI
heidi ui build --force

# Start backend (serves UI at /ui/)
heidi serve

# Verify UI serving + SPA routing
curl -I http://localhost:7777/ui/                 # 200 + index.html
curl -I http://localhost:7777/ui/assets/<file>    # 200 + JS/CSS asset (pick an actual file)
curl -I http://localhost:7777/ui/any-path         # 200 + index.html (SPA fallback)

# Verify .gitignore policy
git check-ignore -v .local/secrets/test.key       # should be ignored
git check-ignore -v .local/worklog                # should NOT be ignored

Port Reference:

  • Vite Dev Server: 3002 (development with hot reload)
  • Heidi Backend: 7777 (production UI serving + API)

Backward Compatibility:

  • Existing CLI commands unchanged
  • Default behavior: backend serves bundled ui_dist if no cache build exists
  • HEIDI_UI_DIST can override dist location

Commit SHA: 5b4ee55

Relates to: dev_1_ui_migrator, dev_3_packaging_release

- Replace legacy UI with Vite-based React application (port 3002)
- Implement Heidi API client layer (src/api/heidi.ts) with typed methods:
  health(), listAgents(), listRuns(), getRun(), runOnce(), runLoop(), chat(), cancelRun()
- Add SSE streaming support (src/api/stream.ts) with polling fallback
- Configure Vite: allowedHosts for heidiai.com.au, proxy to backend :7777
- Add CLI commands: heidi ui build, heidi ui status, heidi ui path
- Serve UI at /ui/ with SPA fallback routing
- Include ui_dist in Python package via setuptools package-data
- Add CI ui-build job with Node 20 and npm caching
- Update README with dev/prod workflow and port reference
- Add worklog entry (2026-02-17) and safe .local/ gitignore policy

Testing:
- Clean install smoke test passed (pip install -> heidi ui build -> heidi serve)
- UI loads at /ui/, assets serve correctly, SPA routing works
- No built artifacts committed; source UI only in git

Relates to: dev_1_ui_migrator, dev_3_packaging_release
@gemini-code-assist
Copy link

Summary of Changes

Hello @heidi-dang, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request introduces a significant overhaul of the Heidi CLI's user interface, transitioning it to a modern Vite-based React application. The changes encompass a complete restructuring of the UI, robust integration with the Heidi backend API for all core functionalities, and the establishment of a streamlined packaging and continuous integration pipeline. This migration aims to provide a more responsive and maintainable frontend experience, while ensuring proper deployment and operational workflows.

Highlights

  • UI Migration to Vite React: The user interface has been completely migrated from a legacy architecture to a modern Vite-based React application, establishing a new and organized UI structure.
  • Heidi Backend Integration: A comprehensive API client layer (src/api/heidi.ts) has been implemented to integrate with the Heidi backend for functionalities such as health checks, agent listing, run management (runOnce, runLoop), chat, and run cancellation.
  • Real-time Streaming Support: Streaming for run updates is now supported via Server-Sent Events (SSE) with an automatic polling fallback mechanism, ensuring real-time feedback in the UI.
  • Packaging and CI Enhancements: The UI build process is integrated into the CLI (heidi ui build), the Python package (pyproject.toml) now includes UI distribution files, and a new GitHub Actions job (ui-build) verifies UI artifacts.
  • Documentation and Configuration Updates: The README.md has been updated with detailed Web UI sections, including development and production workflows, and the Vite configuration now includes expanded allowed hosts and proxy rules for seamless backend communication.
  • Granular Git Ignore Policy: The .gitignore file has been updated to implement a more granular policy for the .local/ directory, allowing specific documentation and worklogs to be tracked while ignoring sensitive files.
Changelog
  • .gitignore
    • Updated to implement a granular policy for the .local/ directory, tracking specific files while ignoring others.
    • Added an entry to ignore the packaged UI distribution files (src/heidi_cli/ui_dist/).
  • .local/worklog
    • Added a new worklog file detailing the UI migration, including key deliverables, configuration, packaging, documentation, and verification steps.
  • README.md
    • Updated to include a new 'Web UI' section with instructions for development and production modes, UI commands, configuration details, and a port reference table.
  • pyproject.toml
    • Modified to include ui_dist/**/* in package-data for setuptools, ensuring the built UI is part of the Python package.
  • ui/App.tsx
    • Removed as part of the UI restructuring and migration to the new Vite React application.
  • ui/README.md
    • Replaced with a new, more detailed README for the UI, focusing on 'HEIFI Neural Interface: Matrix v3' design language, technology stack, and architectural breakdown.
  • ui/components/Sidebar.tsx
    • Removed as part of the UI component migration.
  • ui/components/ThinkingBubble.tsx
    • Removed as part of the UI component migration.
  • ui/components/ToolCard.tsx
    • Removed as part of the UI component migration.
  • ui/components/TranscriptItem.tsx
    • Removed as part of the UI component migration.
  • ui/hooks/useCollaboration.ts
    • Removed, indicating the removal of real-time collaboration features or a different implementation approach.
  • ui/index.html
    • Significantly updated with new Tailwind CSS configuration, custom styles for glassmorphism, ambient mesh background, scrollbar aesthetics, and typing animations.
    • Changed the entry point for the application to src/main.tsx.
  • ui/index.tsx
    • Removed, replaced by ui/src/main.tsx as the new application entry point.
  • ui/metadata.json
    • Removed, suggesting a change in how metadata is handled or that it is no longer needed.
  • ui/package-lock.json
    • Updated to reflect changes in dependencies, including the addition of react-virtuoso and updates to caniuse-lite.
  • ui/package.json
    • Updated the project name to heidi-ui and added react-virtuoso as a dependency.
    • Modified the dev script for Vite to include host, port, and strict port settings.
  • ui/pages/Chat.tsx
    • Removed as part of the UI component migration.
  • ui/pages/Gemini.tsx
    • Removed, indicating the removal of Gemini-specific features or a different integration strategy.
  • ui/pages/Settings.tsx
    • Removed as part of the UI component migration.
  • ui/pnpm-lock.yaml
    • Removed, indicating a switch from pnpm to another package manager or a different lockfile management approach.
  • ui/services/gemini.ts
    • Removed, indicating the removal of Gemini-specific services.
  • ui/services/heidi.ts
    • Removed, replaced by the new API client in ui/src/api/heidi.ts.
  • ui/src/App.tsx
    • Added as the new main application component, orchestrating various UI components and backend interactions.
  • ui/src/api/heidi.ts
    • Added as the new API client for the Heidi backend, providing functions for health checks, agent listing, run management, and chat.
  • ui/src/api/stream.ts
    • Added for handling Server-Sent Events (SSE) streaming for run updates, with a polling fallback mechanism.
  • ui/src/components/AgentArea.tsx
    • Added as a new component for the agent interaction area.
  • ui/src/components/ChatArea.tsx
    • Added as a new component for the chat interaction area.
  • ui/src/components/RightSidebar.tsx
    • Added as a new component for the right-hand sidebar, managing chat history and project files.
  • ui/src/components/SettingsModal.tsx
    • Added as a new modal component for application settings.
  • ui/src/components/Sidebar.tsx
    • Added as a new component for the main navigation sidebar.
  • ui/src/components/TerminalArea.tsx
    • Added as a new component for the terminal area, currently serving as a placeholder for future SSH functionality.
  • ui/src/main.tsx
    • Added as the new entry point for the Vite React application.
  • ui/src/types/index.ts
    • Added, defining new TypeScript types and enums for the UI, including AIProviderId, AppView, User, Message, ChatSession, ProjectFile, ProviderInfo, RunStatus, AppMode, Agent, RunRequest, LoopRequest, RunResponse, RunEvent, ToolEvent, RunMeta, RunDetails, RunSummary, HealthStatus, SettingsState, and StreamCallbacks.
  • ui/types.ts
    • Removed, replaced by ui/src/types/index.ts for centralized type definitions.
  • ui/vite.config.ts
    • Updated to include build configuration for output directory and empty output directory.
    • Expanded allowedHosts for the dev server to include localhost and 127.0.0.1.
    • Modified proxy rules to consolidate /api endpoint handling and removed specific /auth and /connect proxies.
    • Added a resolve.alias configuration for @ to point to the src directory.
Ignored Files
  • Ignored by pattern: .github/workflows/** (1)
    • .github/workflows/ci.yml
Activity
  • heidi-dang initiated a significant UI migration, transitioning the frontend to a Vite-based React application.
  • The PR includes detailed explanations of changes across UI components, API integration, and build processes.
  • Comprehensive testing instructions have been provided to ensure proper functionality of the new UI and its backend interactions.
  • The .local/worklog file was added, documenting the migration summary and key deliverables, indicating thorough planning and execution.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@heidi-dang heidi-dang merged commit a18a1e8 into main Feb 17, 2026
9 checks passed
Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request successfully migrates the UI to a modern Vite-based React application and integrates it with the Heidi backend. However, a critical security concern was identified: the API key is transmitted as a query parameter in the SSE stream URL, which could lead to credential leakage. It is recommended to use a more secure method for transmitting sensitive information, such as a fetch-based streaming approach with headers or short-lived tokens. Additionally, I've identified a few other issues, including a significant discrepancy in the ui/README.md that could mislead developers, a potential bug in the event streaming fallback logic, and a minor typo in a worklog file. Overall, this is a great step forward for the project, and addressing these points will further enhance its quality and security.

Comment on lines +195 to +200
export const getStreamUrl = (runId: string, apiKey?: string): string => {
const baseUrl = getBaseUrl();
const key = apiKey || getSettings().apiKey;
const url = `${baseUrl}/runs/${runId}/stream`;
return key ? `${url}?key=${encodeURIComponent(key)}` : url;
};

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

security-high high

The API key is appended to the SSE stream URL as a query parameter. Sensitive information in URLs can be leaked through server logs, browser history, and proxy logs. This is a security risk as the API key grants access to the Heidi backend, which can execute commands on the host system.

Comment on lines +1 to +68
# 🌌 HEIFI Neural Interface: Matrix v3

HEIFI is a high-fidelity, enterprise-grade command center that bridges Large Language Models with infrastructure orchestration. Designed for the "Power Operator," it offers a unified interface for AI reasoning and autonomous SSH workflows.

![HEIFI Interface](https://img.shields.io/badge/HEIFI-Neural_Interface-white?style=for-the-badge&logo=google-gemini)

## 🎨 Design Language & Theming

The **HEIFI Matrix v3** aesthetic is built on a "Premium Industrial" design language, prioritizing high-density information without visual clutter.

### Color Palette
- **Obsidian Backbone**: `#000000` (Pure Black) for maximum contrast and OLED optimization.
- **Neural Accents**: `#1d9bf0` (Grok Blue) for primary interactive elements and active neural links.
- **Semantic Feedback**:
- `Success`: `#10b981` (Emerald) for successful handshakes and stable links.
- `Error`: `#ef4444` (Rose Red) for critical faults and security breaches.
- **Typography**:
- `Sans`: **Inter** for clean, readable UI labels.
- `Mono`: **Geist Mono** for code, terminal streams, and low-level logical identifiers.

### Visual Effects
- **Glassmorphism 2.0**: Uses deep `backdrop-blur(45px)` combined with low-opacity backgrounds (`rgba(10, 10, 10, 0.15)`) to create a sense of depth and focus.
- **Ambient Mesh**: A fixed radial gradient system (`radial-gradient`) simulates an ambient glow emanating from the corners of the interface, reducing eye strain in dark environments.
- **Glow-Pulse Feedback**: Interactive cards use a custom `glowPulse` animation that shifts border-color and box-shadow based on system state.

## 🚀 Core Technology Stack

### Intelligence Layer
- **Google Gemini 3 API**: Specifically **Gemini 3 Pro Preview** for its superior tool-calling accuracy and **Gemini 2.5 Flash** for high-speed advisory tasks.
- **Thinking Budget**: Leverages the model's reasoning tokens (up to 32k) for "Deep Mode" architectural planning.
- **Local Neural Bridge**: Native integration for **Ollama** and **LM Studio** via a custom local proxy.

### Orchestration & Communication
- **Real-time Streams**: **Socket.io** handles the low-latency duplex stream between the browser and remote SSH targets.
- **SSH Logic**: Powered by the **ssh2** library on the backend, supporting RSA/Ed25519 keys and password-based auth.
- **Terminal UI**: **Xterm.js** with `FitAddon` and `WebLinksAddon` for a native-feeling TTY experience.

### Frontend Architecture
- **React 19**: Utilizing the latest concurrent rendering features.
- **Tailwind CSS**: Custom configuration extending Grok-style spacing and animations.
- **React Virtuoso**: High-performance virtualization for infinite chat history and agent reasoning logs.
- **Lucide Icons**: Feather-weight vector iconography for clear operational signals.

## 🏗️ Architectural Breakdown

### 1. The Autonomous Loop
When in **Agent Mode**, HEIFI enters a recursive reasoning loop:
1. **Perception**: The model analyzes the user's objective and current file system state.
2. **Planning**: It emits `functionCall` objects (e.g., `list_dir`, `read_file`).
3. **Validation**: The UI presents these actions to the operator (Human-in-the-Loop).
4. **Execution**: The backend executes the command via the established SSH socket.
5. **Synthesis**: The output is fed back into the model to refine the next step.

### 2. Security Enclave
- **Zero-Knowledge Auth**: Credentials (SSH keys/passwords) are held in ephemeral memory and never persisted to a database.
- **RSA-4096 Encryption**: All device-flow links (GitHub/Copilot) use standard OAuth 2.0 security protocols.
- **Termination Purge**: Clicking "Terminate Node" triggers a complete memory sweep of the socket session on the backend.

## 🛠️ Operational Commands

| Command | Description |
| :--- | :--- |
| `npm run dev` | Initialize local neural hub and next.js server. |
| `npm run build` | Compile the matrix for production deployment. |
| `docker-compose up` | Launch the fully containerized HEIFI stack. |

---
*HEIFI: The thin layer between human intent and machine execution.* No newline at end of file

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The content of this README appears to be for a different or future version of the project. It mentions technologies like Socket.io, ssh2, and Next.js, which the pull request description states were intentionally removed. This discrepancy can be very misleading for developers. Please update this file to accurately reflect the current state of the UI architecture as implemented in this pull request (e.g., Vite, React, SSE for streaming).

Comment on lines +148 to +154
// Send new events
details.events.forEach((event, index) => {
// Simple deduplication: only send last event if it's new
if (index === details.events.length - 1) {
onEvent?.(event);
}
});

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The polling fallback logic is flawed. It only processes the last event from the fetched list in each polling interval (if (index === details.events.length - 1)). If multiple events occur between polls, all but the last one will be missed by the UI.

To fix this, you should process all events that are new since the last poll. You can achieve this by tracking the number of events already processed.

First, declare a counter at the top of the subscribeRunStream function:

let lastEventCount = 0;

Then, update the polling logic to process only new events as suggested below.

          // Process only new events
          if (details.events.length > lastEventCount) {
            const newEvents = details.events.slice(lastEventCount);
            newEvents.forEach(event => onEvent?.(event));
            lastEventCount = details.events.length;
          }

@@ -0,0 +1,64 @@
# Heidi CLI UI Migration Worklog
## Date: 2026-02-17

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The date 2026-02-17 is set far in the future. This appears to be a typo and could be confusing. Please correct it to the actual date of the work.

## Date: 2024-02-17

@heidi-dang heidi-dang deleted the feat/ui-work-theme branch February 17, 2026 04:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant