From 9b3dfd0c2ddd57ac913d19d808615aaddbbe259e Mon Sep 17 00:00:00 2001 From: Cyrus Gray <144336577+graycyrus@users.noreply.github.com> Date: Tue, 3 Feb 2026 05:35:54 +0530 Subject: [PATCH] Handling the status of skills (#23) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * chore: bump version to 0.20.0 [skip ci] * revert: remove automatic skill dependency installation system - Removed dependency installation loading state from SkillSetupWizard - Reverted SkillRuntime dependency checking and installation methods - Cleaned up dependency-related imports and event listeners - Documented complete implementation in skills/todo.md for future work The dependency installation system was causing unwanted loading states when configuring skills. All functionality has been properly reverted while preserving implementation details for future development. * Refactor SkillManagementPanel to conditionally show action buttons based on connection status - Added offline and setup-required states with informative messages - Updated SkillSetupModal to use connection status for setup vs. manage mode - Simplified mode logic for better UX and error handling in setup scenarios * Update CLAUDE.md with new features, state slices, and code quality tools - Document additions: Redux aiSlice, skillsSlice, teamSlice, and architecture updates - Add ESLint, Prettier integrations with Husky hooks and GitHub workflows - Update development commands from npm to yarn for consistency - Expand key user groups and revise target audiences - Include enhanced project structure, build outputs, and CI/CD updates * fix: resolve TypeScript compilation error and enhance skill session synchronization - Fix unused parameter error in SkillManager.getSkillLoadParams() by prefixing with underscore - Add support for session parameter passing in SkillRuntime.load() method - Implement skill reloading capability for post-authentication updates - Ensure proper connection status synchronization between skill setup and UI display 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude * fix: change skill button text from 'Configure' to 'Manage' for connected skills - Update SkillsGrid button text to dynamically show based on connection status - Connected skills now show 'Manage' button instead of 'Configure' - Provides clearer user indication of skill state - Improves UX for authenticated skills like Telegram 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude * refactor: update documentation, download system and code formatting improvements - Update Claude rules with improved project overview and command documentation - Enhance download screen with better architecture detection and formatting - Improve device detection utilities with multi-architecture support - Add skills system troubleshooting documentation - Code formatting improvements with better line breaks and spacing - Optimize GitHub release asset parsing for platform-specific downloads 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --------- Co-authored-by: Steven Enamakel <31011319+senamakel@users.noreply.github.com> Co-authored-by: github-actions[bot] Co-authored-by: Claude --- .claude/rules/01-project-overview.md | 84 ++++++--- .claude/rules/02-development-commands.md | 72 +++++--- .claude/rules/08-frontend-guide.md | 59 +++++-- .claude/skills-system-troubleshooting.md | 160 ++++++++++++++++++ CLAUDE.md | 101 ++++++++--- package.json | 2 +- src/components/DownloadScreen.tsx | 26 +-- src/components/SkillsGrid.tsx | 2 +- .../skills/SkillManagementPanel.tsx | 89 +++++----- src/components/skills/SkillSetupModal.tsx | 24 ++- src/components/skills/SkillSetupWizard.tsx | 2 + src/lib/skills/manager.ts | 43 ++++- src/lib/skills/runtime.ts | 6 +- src/utils/deviceDetection.ts | 39 ++++- 14 files changed, 549 insertions(+), 160 deletions(-) create mode 100644 .claude/skills-system-troubleshooting.md diff --git a/.claude/rules/01-project-overview.md b/.claude/rules/01-project-overview.md index 31e232674..b2a140536 100644 --- a/.claude/rules/01-project-overview.md +++ b/.claude/rules/01-project-overview.md @@ -11,59 +11,87 @@ This project is a **crypto-focused communication platform** built with Tauri v2, ## Target Users -- Traders, Yield Farmers, Investors -- Researchers, KOLs, Developers -- General crypto community members +- **Crypto Professionals**: Traders, Yield Farmers, Investors +- **Researchers & Analysts**: KOLs, Developers, Researchers +- **Teams & Organizations**: Collaborative workspaces for crypto projects +- **General Community**: Crypto enthusiasts and community members ## Technology Stack -| Layer | Technology | Version | Purpose | -| --------------------- | --------------- | ------- | ----------------------- | +| Layer | Technology | Version | Purpose | +| --------------------- | --------------- | ------- | ------------------------ | | **Frontend Core** | -| UI Framework | React | 19.1.0 | Component-based UI | -| Language | TypeScript | 5.8.3 | Type safety | -| Build Tool | Vite | 7.0.4 | Fast development | +| UI Framework | React | 19.1.0 | Component-based UI | +| Language | TypeScript | 5.8.3 | Type safety | +| Build Tool | Vite | 7.0.4 | Fast development | | **UI & Styling** | -| Styling | Tailwind CSS | Latest | Utility-first CSS | -| Components | Headless UI | Latest | Accessible components | -| Animation | Framer Motion | Latest | Smooth animations | +| Styling | Tailwind CSS | Latest | Utility-first CSS | +| Components | Headless UI | Latest | Accessible components | +| Animation | Framer Motion | Latest | Smooth animations | | **State & Data** | -| State Management | Zustand | Latest | Lightweight state | -| Data Fetching | TanStack Query | Latest | Server state management | -| Form Handling | React Hook Form | Latest | Form validation | +| State Management | Redux Toolkit | Latest | Predictable state mgmt | +| State Persistence | Redux Persist | Latest | State rehydration | +| Data Fetching | TanStack Query | Latest | Server state management | +| Form Handling | React Hook Form | Latest | Form validation | +| **AI & Intelligence** | +| AI Memory | Custom System | Latest | Context & learning | +| Entity Graph | Neo4j | Latest | Knowledge relationships | +| Embeddings | OpenAI | Latest | Semantic search | +| **Communication** | +| Real-time | Socket.io | Latest | Live messaging | +| Telegram Integration | MTProto | Latest | Deep Telegram access | +| MCP Protocol | JSON-RPC 2.0 | Latest | AI tool execution | +| **Team & Skills** | +| Skills Platform | GitHub Sync | Latest | Dynamic skill loading | +| Team Management | REST API | Latest | Multi-user collaboration | | **Backend Core** | -| Language | Rust | 1.93.0 | Performance & safety | -| Framework | Tauri | 2.x | Cross-platform apps | +| Language | Rust | 1.93.0 | Performance & safety | +| Framework | Tauri | 2.x | Cross-platform apps | | **Backend Libraries** | -| Async Runtime | Tokio | Latest | Async operations | -| JSON Handling | Serde JSON | Latest | Serialization | -| Database | SQLx + SQLite | Latest | Local storage | -| HTTP Client | Reqwest | Latest | API requests | -| WebSocket | WebSocket crate | Latest | Real-time messaging | -| Utilities | UUID | Latest | Unique identifiers | +| Async Runtime | Tokio | Latest | Async operations | +| JSON Handling | Serde JSON | Latest | Serialization | +| Database | SQLx + SQLite | Latest | Local storage | +| HTTP Client | Reqwest | Latest | API requests | +| WebSocket | WebSocket crate | Latest | Real-time messaging | +| Utilities | UUID | Latest | Unique identifiers | ## Project Structure ``` -tauri-crossplatform-app/ +frontend-runner-alphahuman/ ├── .claude/ # Claude AI configuration │ ├── rules/ # Modular documentation │ └── agents/ # Subagent configurations ├── src/ # React frontend source +│ ├── lib/ # Core libraries +│ │ ├── ai/ # AI system (memory, constitution, entities) +│ │ └── mcp/ # Model Context Protocol implementation +│ ├── components/ # React components +│ │ └── settings/ # Settings modal system +│ ├── store/ # Redux state management +│ ├── services/ # API clients and services +│ └── pages/ # Application pages ├── src-tauri/ # Rust backend source │ ├── gen/ # Generated platform code │ │ ├── android/ # Android project │ │ └── apple/ # iOS/macOS project │ ├── icons/ # Application icons │ └── src/ # Rust source code +├── skills/ # Skills submodule (GitHub synced) ├── public/ # Static assets +│ └── lottie/ # Animation files +├── .github/workflows/ # CI/CD pipelines └── dist/ # Build output ``` ## Key Configuration Files -- `tauri.conf.json` - Tauri configuration -- `Cargo.toml` - Rust dependencies -- `package.json` - Node.js dependencies -- `vite.config.ts` - Vite build configuration -- `tsconfig.json` - TypeScript configuration +- `tauri.conf.json` - Tauri configuration (app identifier: com.alphahuman.app) +- `Cargo.toml` - Rust dependencies and workspace configuration +- `package.json` - Node.js dependencies and scripts +- `vite.config.ts` - Vite build configuration with Node.js polyfills +- `tsconfig.json` - TypeScript configuration with strict settings +- `eslint.config.js` - ESLint configuration with ES modules +- `.prettierrc` - Code formatting rules +- `.husky/` - Git hooks for pre-commit/pre-push quality checks +- `CLAUDE.md` - Main project documentation for Claude Code diff --git a/.claude/rules/02-development-commands.md b/.claude/rules/02-development-commands.md index d6f18aaad..3e7215263 100644 --- a/.claude/rules/02-development-commands.md +++ b/.claude/rules/02-development-commands.md @@ -13,53 +13,75 @@ Before running any commands, ensure you have: ### Desktop Development ```bash -# Start development server (hot-reload) -npm run tauri dev +# Frontend dev server only (port 1420) +yarn dev -# Build for production -npm run tauri build +# Desktop dev with hot-reload (starts Vite + Tauri) +yarn tauri dev + +# Production build (TypeScript compile + Vite build + Tauri bundle) +yarn tauri build + +# Debug build with .app bundle (required for deep link testing on macOS) +yarn tauri build --debug --bundles app +yarn macos:dev ``` ### Android Development ```bash # Initialize Android project (first time) -npm run tauri android init +yarn tauri android init # Start Android development -npm run tauri android dev +yarn tauri android dev # Build Android APK/AAB -npm run tauri android build +yarn tauri android build ``` ### iOS Development ```bash # Initialize iOS project (first time) -npm run tauri ios init +yarn tauri ios init # Start iOS development -npm run tauri ios dev +yarn tauri ios dev # Build iOS app -npm run tauri ios build +yarn tauri ios build ``` ### Frontend Only ```bash # Install dependencies -npm install +yarn install # Start Vite dev server only -npm run dev +yarn dev # Build frontend only -npm run build +yarn build # Preview production build -npm run preview +yarn preview +``` + +### Code Quality + +```bash +# Run linting and formatting checks +yarn lint +yarn format + +# TypeScript compilation check +yarn typecheck + +# Rust checks +cargo check --manifest-path src-tauri/Cargo.toml +cargo clippy --manifest-path src-tauri/Cargo.toml ``` ## Stopping Development Servers @@ -67,7 +89,7 @@ npm run preview ### Desktop (Tauri Dev) ```bash -# In the terminal running `npm run tauri dev`: +# In the terminal running `yarn tauri dev`: Ctrl + C # If process is stuck, force kill: @@ -86,7 +108,7 @@ taskkill /PID /F # Kill by PID ### Android Dev Server ```bash -# In the terminal running `npm run tauri android dev`: +# In the terminal running `yarn tauri android dev`: Ctrl + C # If emulator/device is stuck: @@ -108,7 +130,7 @@ taskkill /F /IM java.exe # Kills Gradle processes ### iOS Dev Server ```bash -# In the terminal running `npm run tauri ios dev`: +# In the terminal running `yarn tauri ios dev`: Ctrl + C # If simulator is stuck: @@ -129,7 +151,7 @@ pkill -f "cargo" ### Frontend Only (Vite) ```bash -# In the terminal running `npm run dev`: +# In the terminal running `yarn dev`: Ctrl + C # If port 1420 is still occupied: @@ -156,10 +178,10 @@ Get-Process | Where-Object {$_.ProcessName -match "tauri|vite|cargo|node"} | Sto ## Build Targets -| Platform | Command | Output | -| -------- | ----------------------------- | ------------------- | -| Windows | `npm run tauri build` | `.msi`, `.exe` | -| macOS | `npm run tauri build` | `.dmg`, `.app` | -| Linux | `npm run tauri build` | `.deb`, `.AppImage` | -| Android | `npm run tauri android build` | `.apk`, `.aab` | -| iOS | `npm run tauri ios build` | `.ipa` | +| Platform | Command | Output | +| -------- | -------------------------- | ------------------- | +| Windows | `yarn tauri build` | `.msi`, `.exe` | +| macOS | `yarn tauri build` | `.dmg`, `.app` | +| Linux | `yarn tauri build` | `.deb`, `.AppImage` | +| Android | `yarn tauri android build` | `.apk`, `.aab` | +| iOS | `yarn tauri ios build` | `.ipa` | diff --git a/.claude/rules/08-frontend-guide.md b/.claude/rules/08-frontend-guide.md index 15ba858b2..fb3eea29f 100644 --- a/.claude/rules/08-frontend-guide.md +++ b/.claude/rules/08-frontend-guide.md @@ -38,14 +38,24 @@ src/ │ ├── authSlice.ts # Authentication state │ ├── socketSlice.ts # Socket connection state │ ├── userSlice.ts # User profile state +│ ├── aiSlice.ts # AI system state +│ ├── skillsSlice.ts # Skills management state +│ ├── teamSlice.ts # Team collaboration state │ └── telegram/ # Telegram state management ├── services/ # Service layer (singletons) │ ├── apiClient.ts # HTTP REST client │ ├── socketService.ts # Socket.io client │ └── mtprotoService.ts # Telegram MTProto service -├── lib/mcp/ # Model Context Protocol system -│ ├── transport.ts # Socket.io JSON-RPC transport -│ └── telegram/ # 99 Telegram MCP tools +├── lib/ # Core libraries +│ ├── ai/ # AI system architecture +│ │ ├── memory/ # Memory management with encryption +│ │ ├── constitution/ # AI behavior rules +│ │ ├── entities/ # Entity graph management +│ │ ├── sessions/ # Session capture and transcripts +│ │ └── providers/ # AI provider abstractions +│ └── mcp/ # Model Context Protocol system +│ ├── transport.ts # Socket.io JSON-RPC transport +│ └── telegram/ # 99 Telegram MCP tools ├── pages/ # Route components │ ├── Welcome.tsx # Landing page │ ├── Login.tsx # Authentication @@ -56,11 +66,18 @@ src/ │ ├── ProtectedRoute.tsx # Auth-gated routes │ ├── PublicRoute.tsx # Guest-only routes │ ├── ConnectionIndicator.tsx # Status indicators +│ ├── SkillsGrid.tsx # Skills catalog and management +│ ├── DownloadScreen.tsx # Multi-platform download system │ └── settings/ # Settings modal system │ ├── SettingsModal.tsx # Main container with routing │ ├── SettingsLayout.tsx # Modal wrapper with portal │ ├── SettingsHome.tsx # Main menu with profile -│ ├── panels/ConnectionsPanel.tsx # Connection management +│ ├── panels/ # Settings panels +│ │ ├── ConnectionsPanel.tsx # Connection management +│ │ ├── TeamPanel.tsx # Team management +│ │ ├── TeamMembersPanel.tsx # Member roles & permissions +│ │ ├── TeamInvitesPanel.tsx # Invitation system +│ │ └── BillingPanel.tsx # Premium features and billing │ ├── components/ # Menu items, header, back button │ └── hooks/ # Navigation and animation hooks └── utils/ # Utilities and config @@ -70,15 +87,31 @@ src/ ### Recent Architecture Changes -- **Settings Modal System**: Complete URL-based modal system with clean white design - - Modal routes: `/settings`, `/settings/connections` overlaying existing content - - Component structure: SettingsModal, SettingsLayout, ConnectionsPanel, hooks - - Redux integration: auth, user, telegram state for profile and connection management -- **HashRouter**: Switched from BrowserRouter for better desktop app compatibility -- **165+ TypeScript files**: Comprehensive component library with settings modal system -- **Provider chain**: Redux → PersistGate → Socket → Telegram → HashRouter → Routes -- **MCP Integration**: 99 Telegram tools for AI-driven interactions -- **Deep Link Auth**: Web-to-desktop handoff using `alphahuman://` scheme +- **Code Quality Infrastructure**: ESLint, Prettier, and Husky hooks for automated quality checks + - Pre-commit/pre-push hooks with TypeScript compilation validation + - Type-only imports standardization and consolidated import statements + - GitHub workflow integration with quality gate checks +- **Advanced AI System**: Comprehensive artificial intelligence platform + - Memory management with encryption, chunking, and hybrid search capabilities + - Constitution-based AI behavior with GitHub integration for rule updates + - Entity graph migration to Neo4j backend for knowledge relationships + - Session capture, transcript management, and tool compression +- **Skills Management Platform**: Dynamic skill loading and management system + - SkillsGrid with setup status indicators and management controls + - GitHub sync integration for skills catalog updates + - Conditional rendering (setup wizard vs management panel) + - Skills submodule with background update synchronization +- **Team Collaboration Features**: Multi-user workspace management system + - TeamPanel, TeamMembersPanel, TeamInvitesPanel for comprehensive team management + - Role-based permissions and invitation system with Redux state management + - Team API integration with CRUD operations and member management +- **Enhanced Settings System**: Expanded modal system with multiple management panels + - Team management, billing, privacy, and advanced configuration panels + - Enhanced URL routing for deep-linking to specific settings sections + - Redux integration across auth, user, telegram, ai, skills, and team slices +- **200+ TypeScript files**: Comprehensive component and library ecosystem +- **Provider chain**: Redux → PersistGate → Socket → Telegram → AI → Skills → HashRouter → Routes +- **Enhanced CI/CD**: Python sidecar support, XGH_TOKEN authentication, GitHub Pages deployment ## React with Tauri diff --git a/.claude/skills-system-troubleshooting.md b/.claude/skills-system-troubleshooting.md new file mode 100644 index 000000000..dec13019a --- /dev/null +++ b/.claude/skills-system-troubleshooting.md @@ -0,0 +1,160 @@ +# Skills System Troubleshooting Guide + +## Overview + +The Skills System is a Python-based plugin architecture that allows AI agents to have domain-specific knowledge, tools, and automated behaviors. Skills run as isolated Python subprocesses and communicate with the main Tauri application via JSON-RPC. + +## Common Issue: "Setup Failed" with Exit Code 1 + +### Symptoms + +- Skills modal shows "Setup Failed" with "Skill process exited with code: 1" +- Console shows `ModuleNotFoundError: No module named 'pydantic'` +- Error paths like `/Users/cyrus/alphahuman/skills/skills/telegram/` +- Python import failures and subprocess stderr messages + +### Root Cause Analysis + +**Primary Issue: Missing Skills Git Submodule** +The main cause is that the `skills` Git submodule is not initialized. The system expects skills to be available in the `skills/skills/` directory structure but finds an empty directory. + +**Secondary Issues:** + +1. **Missing Python Virtual Environment**: No `.venv` directory in the skills folder +2. **Missing Python Dependencies**: Core packages like `pydantic`, `telethon`, `mcp` not installed +3. **Incorrect Python Paths**: PYTHONPATH configuration issues + +### Skills System Architecture + +``` +skills/ # Git submodule root +├── .venv/ # Python virtual environment +├── requirements.txt # Shared dependencies +├── skills/ # Individual skill packages +│ ├── telegram/ # Telegram skill +│ │ ├── skill.py # Main skill logic +│ │ ├── manifest.json # Skill metadata +│ │ ├── requirements.txt # Skill-specific dependencies +│ │ └── ... +│ ├── browser/ # Browser automation skill +│ ├── calendar/ # Calendar integration skill +│ └── ... # Other skills +└── ... +``` + +### Solution Steps + +#### 1. Initialize Git Submodule + +```bash +git submodule init +git submodule update +``` + +This downloads the skills repository from `https://github.com/alphahumanxyz/skills`. + +#### 2. Create Python Virtual Environment + +```bash +cd skills +python3 -m venv .venv +.venv/bin/pip install --upgrade pip +``` + +#### 3. Install Dependencies + +```bash +.venv/bin/pip install -r requirements.txt +``` + +This installs: + +- **Core Dependencies**: `mcp>=1.0.0`, `pydantic>=2.0`, `aiosqlite>=0.20.0` +- **Skill-Specific Dependencies**: Each skill's requirements.txt (telegram, browser, etc.) + +#### 4. Verify Installation + +```bash +# Test core imports +.venv/bin/python -c "import pydantic, mcp; print('✅ Core dependencies OK')" + +# Test skill import +.venv/bin/python -c "import skills.telegram; print('✅ Telegram skill OK')" +``` + +### How Skills System Works + +#### Development vs Production Paths + +- **Development**: Skills in git submodule at `./skills/skills/` +- **Production**: Skills in `~/.alphahuman/skills/` +- **Configuration**: `src/lib/skills/paths.ts` handles path resolution + +#### Skill Execution Process + +1. **Discovery**: `SkillProvider` scans for skill manifests +2. **Registration**: Skills registered in Redux store +3. **Startup**: Python subprocess spawned with proper environment +4. **Communication**: JSON-RPC transport over stdin/stdout +5. **Setup**: Interactive setup flow if required + +#### Environment Variables + +The system automatically configures: + +- **PYTHONPATH**: Includes skills directory and virtual environment +- **Telegram API**: `TELEGRAM_API_ID`, `TELEGRAM_API_HASH` +- **Working Directory**: Skills submodule root + +### Verification Commands + +```bash +# Check submodule status +git submodule status + +# Verify skills directory structure +ls -la skills/skills/telegram/ + +# Check virtual environment +ls -la skills/.venv/ + +# Test Python environment +cd skills && .venv/bin/python -c "import sys; print('\\n'.join(sys.path))" +``` + +### Prevention + +To prevent this issue in fresh checkouts: + +1. **Always initialize submodules**: + + ```bash + git clone --recurse-submodules + # or after clone: + git submodule update --init --recursive + ``` + +2. **Setup script**: Consider adding to `package.json`: + ```json + { + "scripts": { + "setup": "git submodule update --init && cd skills && python3 -m venv .venv && .venv/bin/pip install -r requirements.txt" + } + } + ``` + +### Related Files + +- **Frontend**: `src/lib/skills/` - Skills management system +- **Backend**: `src-tauri/src/commands/skills.rs` - Rust skill commands +- **Configuration**: `src/utils/config.ts` - Environment variables +- **Providers**: `src/providers/SkillProvider.tsx` - Skills lifecycle + +### Expected Behavior After Fix + +1. Skills modal should show "Connect Telegram" instead of error +2. No more Python import errors in console +3. Skill setup process should work correctly +4. Background GitHub sync should function properly + +This fix resolves the fundamental infrastructure issue preventing skills from loading and running properly. diff --git a/CLAUDE.md b/CLAUDE.md index 4b3e18c8d..cbdcb16cc 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -69,7 +69,7 @@ cargo check --manifest-path src-tauri/Cargo.toml cargo clippy --manifest-path src-tauri/Cargo.toml ``` -No test framework is currently configured. No ESLint or Prettier configuration exists in the repo. +No test framework is currently configured. **ESLint and Prettier are configured** with Husky pre-commit/pre-push hooks for code quality enforcement. ## Architecture @@ -85,6 +85,9 @@ State lives in `src/store/` using Redux Toolkit slices: - **userSlice** — user profile - **socketSlice** — connection status, socket ID - **telegramSlice** — connection/auth status, chats, messages, threads (selectively persisted; loading/error states excluded) +- **aiSlice** — AI system state, memory management, session tracking +- **skillsSlice** — skills catalog, setup status, management state +- **teamSlice** — team management, member invites, permissions Redux Persist stores auth and telegram state (storage backend is configurable; default uses localStorage). The telegram slice has a complex nested structure in `src/store/telegram/` with separate files for types, reducers, extraReducers, and thunks. @@ -165,17 +168,43 @@ Key updates from recent commits: ### Major Additions -- **Settings Modal System** (`60054d8`): Complete URL-based settings modal with clean white design - - Modal infrastructure with backdrop blur and center positioning - - User profile integration with Redux state management - - Connection management panel reusing onboarding components - - URL routing for `/settings` and `/settings/connections` paths - - Mobile responsive design with accessibility features -- **Type Casting Helpers**: Added for Telegram MTProto API (`5a0425c`) -- **Onboarding Refactor**: Updated connection logic and steps (`bd1d240`) -- **MCP Tools Enhancement**: Improved type safety and consistency across Telegram tools (`d0e1191`, `86cc53a`) -- **App Structure**: Refactored MCPProvider integration (`d7d848d`) -- **Big Integer Support**: Consistent handling across all Telegram MCP tools (`0abed4d`) +- **ESLint & Prettier Integration** (`5896966`): Complete code quality toolchain + - ES module syntax for ESLint configuration with enhanced TypeScript support + - Husky pre-commit/pre-push hooks for automatic formatting and linting + - Type-only imports standardization across codebase + - Consolidated import statements and improved code organization + - GitHub workflows updated with Prettier and ESLint checks +- **Advanced Skills System** (`10ec1b3`): Comprehensive skill management platform + - Dynamic skills loading from local directory via Rust integration + - SkillSetupModal with conditional rendering (wizard vs management panel) + - Background GitHub sync for skills catalog updates + - Skills table with setup status indicators and management controls + - Enhanced skill metadata with setup hooks and descriptions +- **Team Management Features** (`10ec1b3`): Multi-user collaboration system + - TeamPanel, TeamMembersPanel, and TeamInvitesPanel components + - Redux state management for teams, members, and invites + - Team API integration with CRUD operations + - Settings modal routing for team management paths + - Role-based permissions and invitation system +- **AI System Enhancements**: Advanced memory and session management + - Hybrid search with encryption for AI memory + - Constitution-based AI behavior with GitHub integration + - Entity graph migration to Neo4j backend + - Session capture and transcript management + - Memory chunking and context formatting +- **Enhanced CI/CD Pipeline** (`b1d7bce`): Production-ready deployment + - XGH_TOKEN authentication for alphahumanxyz/alphahuman releases + - Python sidecar setup and caching for cross-platform builds + - Tauri configuration updates (com.alphahuman.app identifier) + - GitHub Pages deployment with optimized workflows + - Version tagging and environment variable management +- **Device Detection & Download System** (`9d74721`, `b5bccd2`): Enhanced multi-architecture download support + - Optimized asset parsing using Maps for unique architecture links per platform + - Enhanced DownloadScreen.tsx with architecture-specific download options + - Improved device detection for Windows, macOS, Linux, and Android platforms + - Added preference logic for more specific filenames in asset parsing + - Support for multiple architectures (x64, aarch64) with intelligent sorting +- **Version Bump**: Project updated to v0.20.0 (`891517c`) ### Design System Updates @@ -188,16 +217,36 @@ Key updates from recent commits: ### Component Structure -- **165+ TypeScript files** across `src/` directory (added settings modal system) -- **Settings Modal System**: Complete modal infrastructure in `src/components/settings/` +- **200+ TypeScript files** across `src/` directory with comprehensive tooling +- **AI System Architecture** (`src/lib/ai/`): Advanced artificial intelligence platform + - Memory management with encryption, chunking, and hybrid search + - Constitution-based behavior with GitHub integration + - Entity graph with Neo4j backend integration + - Session capture, transcript management, and tool compression + - Provider system with OpenAI integration and custom providers +- **Skills Management System**: Dynamic skill platform with Rust integration + - SkillsGrid.tsx - Skills catalog with setup status and management + - SkillSetupModal.tsx - Conditional wizard/management panel rendering + - SkillProvider.tsx - GitHub sync and local directory integration + - Skills submodule integration with background updates +- **Team Collaboration Features**: Multi-user workspace management + - TeamPanel.tsx - Team overview with member management + - TeamMembersPanel.tsx - Member roles and permissions + - TeamInvitesPanel.tsx - Invitation system with role assignment + - Team API integration with Redux state management +- **Settings Modal System**: Comprehensive configuration interface - SettingsModal.tsx - Main container with URL routing - SettingsLayout.tsx - Modal wrapper with createPortal - - SettingsHome.tsx - Main menu with profile and navigation - - ConnectionsPanel.tsx - Connection management with status indicators + - Enhanced panels: Billing, Team, Connections, Privacy, Profile - Hooks: useSettingsNavigation.ts, useSettingsAnimation.ts -- **Onboarding Flow**: Multi-step process with privacy, analytics, and connection steps -- **Authentication**: Web-to-desktop handoff using `alphahuman://` scheme -- **Connection Management**: Telegram MTProto and Socket.io integration +- **Download System**: Enhanced multi-platform distribution + - DownloadScreen.tsx - Platform detection with architecture support + - deviceDetection.ts - Comprehensive device/architecture utilities + - GitHub API integration for real-time release assets +- **Code Quality Infrastructure**: ESLint, Prettier, and Husky integration + - Pre-commit/pre-push hooks with TypeScript compilation checks + - Standardized type-only imports and consolidated statements + - GitHub workflow integration with automated quality checks ## Git Workflow @@ -205,10 +254,17 @@ Key updates from recent commits: ## Key Patterns +- **Code Quality**: ESLint and Prettier enforce code standards with Husky hooks. Use type-only imports (`import type`) and consolidate imports from same modules. - **No localStorage**: Avoid `localStorage` and `sessionStorage`; use Redux (and persist) for app state. Remove any direct usage when working on affected code. -- **Modal System**: Settings modal uses `createPortal` pattern with URL-based routing. Clean white design (not glass morphism) for system settings. Navigate with `/settings` and `/settings/connections` paths. +- **AI System Integration**: Use `src/lib/ai/` for memory management, constitution loading, entity queries, and session capture. AI providers abstracted through interface pattern. +- **Skills Management**: Skills loaded dynamically from local directory via Rust. Use `SkillProvider` for GitHub sync and `SkillsGrid` for management interface. +- **Team Collaboration**: Team features in `src/components/settings/panels/Team*`. Use Redux `teamSlice` for state management and `teamApi` for backend operations. +- **Device Detection**: Use `deviceDetection.ts` utilities for platform/architecture detection. Support multiple architectures per platform (x64, aarch64) with intelligent preference logic. +- **GitHub Integration**: Fetch release assets via GitHub API (`fetchLatestRelease()`) and parse by architecture (`parseReleaseAssetsByArchitecture()`). Use Maps for efficient unique architecture tracking. +- **Download System**: Platform-specific file type support (.exe/.msi for Windows, .dmg for macOS, .AppImage/.deb/.rpm for Linux, .apk for Android) with fallback links. +- **Modal System**: Settings modal uses `createPortal` pattern with URL-based routing. Clean white design (not glass morphism) for system settings. Navigate with `/settings` paths for different panels. - **Component Reuse**: Connection management reuses `connectOptions` array and components from onboarding flow. Maintains consistent UX patterns across features. -- **Redux Integration**: Settings modal integrates with existing slices - auth for logout, user for profile display, telegram for connection status. No new state management needed. +- **Redux Integration**: Multiple slices (auth, user, telegram, ai, skills, team) with Redux Persist. Use typed hooks and selectors. State functions accept optional `userId` param. - **Node polyfills**: Vite config (`vite.config.ts`) polyfills `buffer`, `process`, `util`, `os`, `crypto`, `stream` for the `telegram` package which requires Node APIs. - **Telegram IDs**: Use `big-integer` library, not native JS numbers (Telegram IDs exceed `Number.MAX_SAFE_INTEGER`). - **MCP tool files**: Each tool in `src/lib/mcp/telegram/tools/` exports a handler conforming to `TelegramMCPToolHandler` interface. Tool names are typed in `src/lib/mcp/telegram/types.ts`. @@ -216,8 +272,7 @@ Key updates from recent commits: - **CORS workaround**: External HTTP requests from the WebView hit CORS. Use Rust `reqwest` via Tauri commands instead of browser `fetch()`. - **Hash Routing**: Uses HashRouter for desktop app compatibility and deep link handling. - **Integration Libraries**: Each integration (Telegram, future Gmail, etc.) lives under `src/lib//` with its own `state/`, `services/`, `api/` subdirectories. Domain-specific services belong in the integration folder, not in `src/services/` (which holds only cross-cutting services like socketService, apiClient). -- **State Layer**: Each integration dispatches Redux changes through state functions in `src/lib//state/` — never import Redux actions directly from services or update handlers. State functions accept an optional `userId` param (falls back to `getCurrentUserId()`). -- **Unit Tests**: All unit tests live in `__tests__/` folders co-located with the code they test. +- **Unit Tests**: All unit tests live in `__tests__/` folders co-located with the code they test. Use Jest with TypeScript support. ## Platform Gotchas diff --git a/package.json b/package.json index a1f80add2..031da05ce 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "alphahuman", "private": true, - "version": "0.19.0", + "version": "0.20.0", "type": "module", "scripts": { "dev": "vite", diff --git a/src/components/DownloadScreen.tsx b/src/components/DownloadScreen.tsx index 42deea0d2..939a7005d 100644 --- a/src/components/DownloadScreen.tsx +++ b/src/components/DownloadScreen.tsx @@ -1,14 +1,14 @@ import { useEffect, useState } from 'react'; import { + type Architecture, + type ArchitectureDownloadLink, detectPlatform, fetchLatestRelease, getDownloadLink, getPlatformDisplayName, parseReleaseAssets, parseReleaseAssetsByArchitecture, - type Architecture, - type ArchitectureDownloadLink, type Platform, type PlatformArchitectureLinks, type PlatformDownloadLinks, @@ -33,7 +33,9 @@ const DownloadScreen = () => { const [selectedPlatform, setSelectedPlatform] = useState(null); const [selectedArchitecture, setSelectedArchitecture] = useState(null); const [releaseLinks, setReleaseLinks] = useState(null); - const [architectureLinks, setArchitectureLinks] = useState(null); + const [architectureLinks, setArchitectureLinks] = useState( + null + ); const [isLoading, setIsLoading] = useState(true); const [error, setError] = useState(null); @@ -63,7 +65,9 @@ const DownloadScreen = () => { const platformArchLinks = archLinks[detected.platform as keyof PlatformArchitectureLinks]; if (platformArchLinks && platformArchLinks.length > 0) { // Prefer detected architecture, otherwise use first available - const preferredLink = platformArchLinks.find(link => link.architecture === detected.architecture) || platformArchLinks[0]; + const preferredLink = + platformArchLinks.find(link => link.architecture === detected.architecture) || + platformArchLinks[0]; setSelectedArchitecture(preferredLink.architecture); } } catch (err) { @@ -88,7 +92,8 @@ const DownloadScreen = () => { return getDownloadLink(selectedPlatform || 'unknown', releaseLinks || undefined); } - const platformArchLinks = architectureLinks[selectedPlatform as keyof PlatformArchitectureLinks]; + const platformArchLinks = + architectureLinks[selectedPlatform as keyof PlatformArchitectureLinks]; if (platformArchLinks && selectedArchitecture) { const link = platformArchLinks.find(l => l.architecture === selectedArchitecture); if (link) { @@ -139,9 +144,7 @@ const DownloadScreen = () => { {error && !isLoading && (
-

- {error}. Using fallback download links. -

+

{error}. Using fallback download links.

)} @@ -209,9 +212,12 @@ const DownloadScreen = () => { {downloadOptions .filter(opt => opt.platform !== selectedPlatform) .map(option => { - const platformArchLinks = architectureLinks?.[option.platform as keyof PlatformArchitectureLinks]; + const platformArchLinks = + architectureLinks?.[option.platform as keyof PlatformArchitectureLinks]; const hasValidLink = platformArchLinks && platformArchLinks.length > 0; - const defaultLink = platformArchLinks?.[0]?.url || getDownloadLink(option.platform, releaseLinks || undefined); + const defaultLink = + platformArchLinks?.[0]?.url || + getDownloadLink(option.platform, releaseLinks || undefined); const hasMultipleArchs = platformArchLinks && platformArchLinks.length > 1; return ( diff --git a/src/components/SkillsGrid.tsx b/src/components/SkillsGrid.tsx index 339b9a6c7..086dd45ef 100644 --- a/src/components/SkillsGrid.tsx +++ b/src/components/SkillsGrid.tsx @@ -408,7 +408,7 @@ export default function SkillsGrid() { setSetupModalOpen(true); }} className="px-4 py-1.5 text-xs font-medium text-primary-300 bg-primary-500/10 border border-primary-500/30 rounded-lg hover:bg-primary-500/20 transition-colors flex-shrink-0 ml-3"> - Configure + {connectionStatus === 'connected' ? 'Manage' : 'Configure'} ); diff --git a/src/components/skills/SkillManagementPanel.tsx b/src/components/skills/SkillManagementPanel.tsx index 664ce0017..70dedadf2 100644 --- a/src/components/skills/SkillManagementPanel.tsx +++ b/src/components/skills/SkillManagementPanel.tsx @@ -145,50 +145,59 @@ export default function SkillManagementPanel({ )} - {/* Action buttons — single row */} -
- {!confirmDisconnect ? ( -
- - {onReconfigure && ( + {/* Action buttons — only show if skill is actually running */} + {connectionStatus !== "offline" && connectionStatus !== "setup_required" ? ( +
+ {!confirmDisconnect ? ( +
- )} - + {onReconfigure && ( + + )} + +
+ ) : ( +
+ + +
+ )} +
+ ) : ( + // Show message for offline skills +
+
+ Skill is offline. Use "Re-run Setup" to reconnect.
- ) : ( -
- - -
- )} -
+
+ )}
); } diff --git a/src/components/skills/SkillSetupModal.tsx b/src/components/skills/SkillSetupModal.tsx index 4233773c5..bf3e7ced2 100644 --- a/src/components/skills/SkillSetupModal.tsx +++ b/src/components/skills/SkillSetupModal.tsx @@ -7,6 +7,7 @@ import { useState, useEffect, useRef } from "react"; import { createPortal } from "react-dom"; import { useAppSelector } from "../../store/hooks"; +import { useSkillConnectionStatus } from "../../lib/skills/hooks"; import SkillSetupWizard from "./SkillSetupWizard"; import SkillManagementPanel from "./SkillManagementPanel"; @@ -27,13 +28,20 @@ export default function SkillSetupModal({ onClose, }: SkillSetupModalProps) { const modalRef = useRef(null); - const setupComplete = useAppSelector( - (state) => state.skills.skills[skillId]?.setupComplete, - ); - // Skills without setup hooks always go straight to manage mode. - const [mode, setMode] = useState<"manage" | "setup">( - !hasSetup || setupComplete ? "manage" : "setup", - ); + const skill = useAppSelector((state) => state.skills.skills[skillId]); + const connectionStatus = useSkillConnectionStatus(skillId); + + // Simplified mode logic: Only show manage mode when skill is actually working + // Everything else (offline, errors, never connected, etc.) goes to setup mode + const [mode, setMode] = useState<"manage" | "setup">(() => { + // Only show manage mode when the skill is actually working + const isWorking = connectionStatus === "connected" || connectionStatus === "connecting"; + + // For skills without setup hooks, still need to check if they're working + // Show manage mode only if skill is currently working + // Everything else goes to setup mode (first-time setup, errors, offline, disconnected) + return isWorking ? "manage" : "setup"; + }); // Handle escape key useEffect(() => { @@ -137,7 +145,7 @@ export default function SkillSetupModal({ setMode("manage") : onClose} + onCancel={skill?.setupComplete ? () => setMode("manage") : onClose} /> )} diff --git a/src/components/skills/SkillSetupWizard.tsx b/src/components/skills/SkillSetupWizard.tsx index 834ae8bb4..958af4d0e 100644 --- a/src/components/skills/SkillSetupWizard.tsx +++ b/src/components/skills/SkillSetupWizard.tsx @@ -30,6 +30,7 @@ export default function SkillSetupWizard({ }: SkillSetupWizardProps) { const [state, setState] = useState({ phase: "loading" }); + // Start the skill (if not running) then start the setup flow on mount useEffect(() => { let cancelled = false; @@ -162,6 +163,7 @@ export default function SkillSetupWizard({ ); + case "step": return ( (); + /** + * Get skill-specific load parameters (e.g., session data for Telegram) + */ + private getSkillLoadParams(_skillId: string): Record { + const params: Record = {}; + + // For now, just return empty params - skill-specific session data + // will be handled through the skill's own setup process + return params; + } + /** * Add a discovered skill manifest to Redux. */ @@ -81,8 +92,9 @@ class SkillManager { store.dispatch(setSkillStatus({ skillId, status: "running" })); - // Load the skill - await runtime.load(); + // Load the skill with additional parameters based on skill type + const loadParams = this.getSkillLoadParams(manifest.id); + await runtime.load(loadParams); // Check if setup is needed const state = store.getState(); @@ -302,6 +314,33 @@ class SkillManager { return store.getState().skills.skills[skillId]?.status; } + /** + * Reload a skill with updated parameters (e.g., after authentication). + */ + async reloadSkill(skillId: string): Promise { + const runtime = this.runtimes.get(skillId); + if (!runtime || !runtime.isRunning) { + return; // Skill not running, nothing to reload + } + + try { + // Get updated load parameters + const loadParams = this.getSkillLoadParams(skillId); + + // Reload the skill with new parameters + await runtime.load(loadParams); + + // Check if skill needs activation + const state = store.getState(); + const skillState = state.skills.skills[skillId]; + if (skillState?.setupComplete) { + await this.activateSkill(skillId); + } + } catch (err) { + console.error(`Error reloading skill ${skillId}:`, err); + } + } + // ----------------------------------------------------------------------- // Reverse RPC handling // ----------------------------------------------------------------------- diff --git a/src/lib/skills/runtime.ts b/src/lib/skills/runtime.ts index b97d5212f..cd978c5f8 100644 --- a/src/lib/skills/runtime.ts +++ b/src/lib/skills/runtime.ts @@ -38,6 +38,7 @@ export class SkillRuntime { this.transport.onReverseRpc(handler); } + /** * Spawn the skill subprocess. * Uses absolute cwd from the backend so the sidecar finds the skills package. @@ -94,9 +95,9 @@ export class SkillRuntime { } /** - * Send skill/load with manifest + data dir. + * Send skill/load with manifest + data dir + session data. */ - async load(): Promise { + async load(additionalParams?: Record): Promise { // Use absolute path from Rust to avoid cwd-relative ambiguity const dataDir = await invoke("skill_data_dir", { skillId: this.manifest.id, @@ -104,6 +105,7 @@ export class SkillRuntime { await this.transport.request("skill/load", { manifest: this.manifest, dataDir, + ...additionalParams, }); } diff --git a/src/utils/deviceDetection.ts b/src/utils/deviceDetection.ts index dda5d7dbc..d3a208f8b 100644 --- a/src/utils/deviceDetection.ts +++ b/src/utils/deviceDetection.ts @@ -141,7 +141,9 @@ export function detectPlatform(): PlatformInfo { * Fetch the latest release from GitHub */ export async function fetchLatestRelease(): Promise { - const response = await fetch('https://api.github.com/repos/alphahumanxyz/alphahuman/releases/latest'); + const response = await fetch( + 'https://api.github.com/repos/alphahumanxyz/alphahuman/releases/latest' + ); if (!response.ok) { throw new Error(`Failed to fetch release: ${response.statusText}`); } @@ -185,7 +187,9 @@ export function getArchitectureDisplayName(arch: Architecture): string { /** * Parse GitHub release assets and map them to platforms with architecture support */ -export function parseReleaseAssetsByArchitecture(assets: GitHubReleaseAsset[]): PlatformArchitectureLinks { +export function parseReleaseAssetsByArchitecture( + assets: GitHubReleaseAsset[] +): PlatformArchitectureLinks { const links: PlatformArchitectureLinks = {}; // Use Maps to track unique architectures per platform @@ -212,21 +216,39 @@ export function parseReleaseAssetsByArchitecture(assets: GitHubReleaseAsset[]): }; // Windows: .exe, .msi, .zip (Windows) - if (name.includes('windows') || name.includes('.exe') || name.includes('.msi') || (name.includes('.zip') && !name.includes('macos'))) { + if ( + name.includes('windows') || + name.includes('.exe') || + name.includes('.msi') || + (name.includes('.zip') && !name.includes('macos')) + ) { // Only add if this architecture doesn't exist yet, or prefer more specific filenames - if (!windowsMap.has(architecture) || (name.includes('windows') && !windowsMap.get(architecture)?.fileName.toLowerCase().includes('windows'))) { + if ( + !windowsMap.has(architecture) || + (name.includes('windows') && + !windowsMap.get(architecture)?.fileName.toLowerCase().includes('windows')) + ) { windowsMap.set(architecture, link); } } // macOS: .dmg else if (name.includes('macos') || name.includes('.dmg') || name.includes('darwin')) { // Only add if this architecture doesn't exist yet, or prefer more specific filenames - if (!macosMap.has(architecture) || (name.includes('macos') && !macosMap.get(architecture)?.fileName.toLowerCase().includes('macos'))) { + if ( + !macosMap.has(architecture) || + (name.includes('macos') && + !macosMap.get(architecture)?.fileName.toLowerCase().includes('macos')) + ) { macosMap.set(architecture, link); } } // Linux: .AppImage, .deb, .rpm - else if (name.includes('linux') || name.includes('.appimage') || name.includes('.deb') || name.includes('.rpm')) { + else if ( + name.includes('linux') || + name.includes('.appimage') || + name.includes('.deb') || + name.includes('.rpm') + ) { // Prefer AppImage, then deb, then rpm for the same architecture const existing = linuxMap.get(architecture); if (!existing) { @@ -267,7 +289,10 @@ export function parseReleaseAssetsByArchitecture(assets: GitHubReleaseAsset[]): } // Sort architectures: prefer detected architecture, then x64, then aarch64 - const sortArchitectures = (archLinks: ArchitectureDownloadLink[], preferredArch?: Architecture) => { + const sortArchitectures = ( + archLinks: ArchitectureDownloadLink[], + preferredArch?: Architecture + ) => { return archLinks.sort((a, b) => { if (preferredArch && a.architecture === preferredArch) return -1; if (preferredArch && b.architecture === preferredArch) return 1;