From 01c6fd9421ed0a93715fb507eb04ff7c2738442f Mon Sep 17 00:00:00 2001 From: M3gA-Mind Date: Tue, 10 Mar 2026 05:31:26 +0530 Subject: [PATCH] refactor: streamline JSON formatting and enhance documentation clarity - Consolidated JSON structure in `.mcp.json` and `.claude/mcp.json` for improved readability. - Updated `CLAUDE.md` and other documentation files to enhance formatting consistency and clarity. - Improved the organization of agent roles and initialization procedures in `AGENTS.md`, `BOOTSTRAP.md`, and `IDENTITY.md`. - Enhanced user understanding and personalization strategies in `USER.md` and `MEMORY.md`. - Refined tool generation scripts for better error handling and output formatting in `discover-tools.js` and `openClaw-formatter.js`. --- .claude/mcp.json | 9 +- .mcp.json | 9 +- CLAUDE.md | 37 +- ai/AGENTS.md | 6 +- ai/BOOTSTRAP.md | 7 +- ai/IDENTITY.md | 7 +- ai/MEMORY.md | 8 +- ai/README.md | 15 +- ai/SOUL.md | 19 + ai/USER.md | 7 +- docs/feat/daemon-lifecycle-management.md | 19 +- docs/gmail-skill-integration.md | 83 ++-- .../__tests__/openClaw-formatter.test.js | 72 ++-- scripts/tools-generator/discover-tools.js | 96 +++-- scripts/tools-generator/openClaw-formatter.js | 26 +- scripts/tools-generator/tauri-integration.js | 33 +- src/SOUL.md | 5 + src/components/MiniSidebar.tsx | 15 +- .../daemon/DaemonHealthIndicator.tsx | 35 +- src/components/daemon/DaemonHealthPanel.tsx | 64 +-- src/components/oauth/OAuthLoginSection.tsx | 14 +- src/components/settings/panels/AIPanel.tsx | 73 ++-- .../panels/components/SectionCard.tsx | 7 +- .../panels/components/ValidatedField.tsx | 55 ++- src/hooks/useDaemonHealth.ts | 27 +- src/hooks/useDaemonLifecycle.ts | 21 +- src/hooks/useToolsUpdates.ts | 3 +- src/lib/ai/__tests__/loader.test.ts | 63 ++- src/lib/ai/injector.ts | 45 +- src/lib/ai/loader.ts | 70 ++- src/lib/ai/soul/injector.ts | 45 +- src/lib/ai/soul/loader.ts | 41 +- src/lib/ai/soul/types.ts | 2 +- src/lib/ai/tools/__tests__/loader.test.ts | 42 +- src/lib/ai/tools/injector.ts | 39 +- src/lib/ai/tools/loader.ts | 92 ++-- src/lib/ai/tools/types.ts | 8 +- src/lib/ai/types.ts | 3 +- src/lib/notion/services/metadataSync.ts | 7 +- src/lib/tools/auto-update.ts | 40 +- src/lib/tools/file-watcher.ts | 13 +- src/main.tsx | 2 +- src/pages/Conversations.tsx | 6 +- src/pages/Intelligence.tsx | 2 +- src/providers/SocketProvider.tsx | 16 +- src/services/__tests__/agentLoop.test.ts | 403 +++++++++--------- .../__tests__/agentToolRegistry.test.ts | 146 +++---- src/services/agentToolRegistry.ts | 45 +- src/services/api/actionableItemsApi.ts | 6 +- src/services/api/apiKeysApi.ts | 2 +- src/services/api/creditsApi.ts | 7 +- src/services/api/feedbackApi.ts | 2 +- src/services/api/settingsApi.ts | 2 +- src/services/api/threadApi.ts | 11 +- src/store/daemonSlice.ts | 27 +- src/store/index.ts | 1 - src/store/threadSlice.ts | 16 +- src/types/global.d.ts | 6 +- src/types/oauth.ts | 2 +- src/utils/desktopDeepLinkListener.ts | 2 +- src/utils/tauriCommands.ts | 8 +- 61 files changed, 956 insertions(+), 1038 deletions(-) diff --git a/.claude/mcp.json b/.claude/mcp.json index 0ff89af83..81364bdd8 100644 --- a/.claude/mcp.json +++ b/.claude/mcp.json @@ -1,8 +1 @@ -{ - "mcpServers": { - "alphaHuman": { - "type": "http", - "url": "https://alphahuman.readme.io/mcp" - } - } -} +{ "mcpServers": { "alphaHuman": { "type": "http", "url": "https://alphahuman.readme.io/mcp" } } } diff --git a/.mcp.json b/.mcp.json index 0ff89af83..81364bdd8 100644 --- a/.mcp.json +++ b/.mcp.json @@ -1,8 +1 @@ -{ - "mcpServers": { - "alphaHuman": { - "type": "http", - "url": "https://alphahuman.readme.io/mcp" - } - } -} +{ "mcpServers": { "alphaHuman": { "type": "http", "url": "https://alphahuman.readme.io/mcp" } } } diff --git a/CLAUDE.md b/CLAUDE.md index 947078e9d..54419cbef 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -213,15 +213,15 @@ Advanced JavaScript execution engine for skills using V8 (via deno_core): Set in `.env` (Vite exposes `VITE_*` prefixed vars): -| Variable | Purpose | -| ---------------------------- | -------------------------------------------------- | -| `VITE_BACKEND_URL` | Backend API URL (default: `http://localhost:5005`) | -| `VITE_TELEGRAM_API_ID` | Telegram MTProto API ID | -| `VITE_TELEGRAM_API_HASH` | Telegram MTProto API hash | -| `VITE_TELEGRAM_BOT_USERNAME` | Telegram bot username | -| `VITE_TELEGRAM_BOT_ID` | Telegram bot numeric ID | -| `VITE_SENTRY_DSN` | Sentry DSN for error reporting (optional) | -| `VITE_DEBUG` | Debug mode flag | +| Variable | Purpose | +| ---------------------------- | ------------------------------------------------------------------- | +| `VITE_BACKEND_URL` | Backend API URL (default: `http://localhost:5005`) | +| `VITE_TELEGRAM_API_ID` | Telegram MTProto API ID | +| `VITE_TELEGRAM_API_HASH` | Telegram MTProto API hash | +| `VITE_TELEGRAM_BOT_USERNAME` | Telegram bot username | +| `VITE_TELEGRAM_BOT_ID` | Telegram bot numeric ID | +| `VITE_SENTRY_DSN` | Sentry DSN for error reporting (optional) | +| `VITE_DEBUG` | Debug mode flag | | `ALPHAHUMAN_DAEMON_INTERNAL` | Force internal daemon mode (default: false, uses external services) | Production defaults are in `src/utils/config.ts`. @@ -254,16 +254,18 @@ loadAIConfig() → AIConfig // Combined SOUL + TOOLS configuration ``` **Caching Strategy:** + - Memory cache (immediate) - localStorage cache (30min TTL) - GitHub remote (latest) - Bundled fallback (reliable) **TODO**: Set up public AI configuration repository to eliminate 404 fallback errors - - Current: AI config loaders try GitHub URLs first (fail with 404), then fallback to bundled files - - Console shows: "Failed to load resource: the server responded with a status of 404" - - Affected: Settings → AI Configuration "Refresh Soul/Tools" buttons - - Files: `src/lib/ai/soul/loader.ts`, `src/lib/ai/tools/loader.ts` + +- Current: AI config loaders try GitHub URLs first (fail with 404), then fallback to bundled files +- Console shows: "Failed to load resource: the server responded with a status of 404" +- Affected: Settings → AI Configuration "Refresh Soul/Tools" buttons +- Files: `src/lib/ai/soul/loader.ts`, `src/lib/ai/tools/loader.ts` ### Unified Injection System @@ -272,15 +274,17 @@ Every user message automatically gets AI context injected: ```typescript // Unified injection (recommended) import { injectAll } from '../lib/ai/injector'; -const injectedMessage = await injectAll(userMessage); - // Individual injections (for specific needs) import { injectSoul, injectTools } from '../lib/ai/injector'; + +const injectedMessage = await injectAll(userMessage); + const soulMessage = await injectSoul(userMessage); const toolsMessage = await injectTools(userMessage); ``` **Message Format:** + ``` [PERSONA_CONTEXT] I am AlphaHuman: that incredibly smart, funny friend who loves helping people get stuff done @@ -310,12 +314,14 @@ yarn skills:build && yarn tools:generate && tsc && vite build ``` **Process:** + 1. **Discovery**: Spawns Tauri runtime to call `runtime_all_tools()` 2. **Parsing**: Extracts tool definitions with JSON Schema 3. **Formatting**: Generates OpenClaw-compliant markdown 4. **Bundling**: Includes in app for AI context injection **Generated Output:** + - Professional documentation with usage examples - Environment-specific configurations - Tool categorization by skill @@ -335,6 +341,7 @@ All use the unified `injectAll()` function for consistency. ### Settings UI View and manage AI configuration in **Settings → AI Configuration**: + - Live SOUL personality preview - TOOLS statistics and categories - Individual refresh buttons diff --git a/ai/AGENTS.md b/ai/AGENTS.md index 5a9eee57d..599b42fc2 100644 --- a/ai/AGENTS.md +++ b/ai/AGENTS.md @@ -3,6 +3,7 @@ TODO: Define different agent roles and specializations within the AlphaHuman system. This file should define: + - Primary AlphaHuman agent role - Specialized sub-agents (if any) - Agent collaboration patterns @@ -12,18 +13,21 @@ This file should define: ## Example Structure: ### Primary Agent + - **AlphaHuman Core**: Main conversational AI assistant - Role: General productivity, research, and collaboration - Context: All platform interactions ### Specialized Agents (Future) + - **Research Agent**: Deep research and analysis tasks - **Automation Agent**: Workflow and process optimization - **Communication Agent**: Cross-platform messaging coordination - **Analytics Agent**: Data analysis and insights ### Agent Coordination + - How agents hand off tasks - Shared memory and context - Escalation patterns -- User preference handling \ No newline at end of file +- User preference handling diff --git a/ai/BOOTSTRAP.md b/ai/BOOTSTRAP.md index 2a709ab83..067a7720e 100644 --- a/ai/BOOTSTRAP.md +++ b/ai/BOOTSTRAP.md @@ -3,6 +3,7 @@ TODO: Define initialization and setup procedures for AlphaHuman when starting new conversations or onboarding users. This file should include: + - First-time user onboarding flow - Conversation initialization procedures - System startup and configuration @@ -12,25 +13,29 @@ This file should include: ## Example Structure: ### First Interaction Protocol + - Greeting and introduction - Capability explanation - User preference discovery - Initial context gathering ### Onboarding Flow + - Platform feature introduction - Skills and tools overview - Customization options - Getting started guidance ### Context Establishment + - Understanding user's current situation - Identifying immediate needs - Setting expectations - Establishing communication patterns ### System Initialization + - Loading user preferences - Connecting to available tools - Verifying permissions and access -- Preparing for productive interaction \ No newline at end of file +- Preparing for productive interaction diff --git a/ai/IDENTITY.md b/ai/IDENTITY.md index 1b049ceb0..b6c4b9895 100644 --- a/ai/IDENTITY.md +++ b/ai/IDENTITY.md @@ -3,6 +3,7 @@ TODO: Define the fundamental identity and purpose of AlphaHuman that remains consistent across all interactions. This file should establish: + - Core mission and values - Fundamental capabilities and limitations - Relationship with users and teams @@ -12,24 +13,28 @@ This file should establish: ## Example Structure: ### Mission Statement + - Primary purpose and goals - Target user base and use cases - Platform vision and philosophy ### Core Values + - User privacy and security - Accuracy and reliability - Collaboration and teamwork - Continuous learning and improvement ### Identity Characteristics + - Professional yet approachable - Intelligent and analytical - Supportive and encouraging - Transparent about limitations ### Relationship Principles + - How AlphaHuman interacts with individuals - Team collaboration dynamics - Professional boundaries -- Trust and reliability standards \ No newline at end of file +- Trust and reliability standards diff --git a/ai/MEMORY.md b/ai/MEMORY.md index c65a2a0d1..92256e61f 100644 --- a/ai/MEMORY.md +++ b/ai/MEMORY.md @@ -3,6 +3,7 @@ TODO: Define important long-term knowledge and memories that AlphaHuman should maintain across sessions. This file should contain: + - Key platform capabilities and features - Important user patterns and preferences - Successful interaction strategies @@ -12,31 +13,36 @@ This file should contain: ## Example Structure: ### Platform Knowledge + - AlphaHuman feature set and capabilities - Integration details and limitations - Common user workflows - Best practices and recommendations ### Interaction Patterns + - Successful conversation strategies - Common user questions and answers - Problem-solving approaches - Communication techniques that work well ### User Insights + - General user behavior patterns - Common pain points and solutions - Preferred interaction styles - Successful customization strategies ### Technical Knowledge + - System capabilities and limitations - Integration best practices - Troubleshooting common issues - Performance optimization tips ### Continuous Learning + - New features and capabilities - Evolving user needs - Platform improvements -- Community feedback and insights \ No newline at end of file +- Community feedback and insights diff --git a/ai/README.md b/ai/README.md index 407d63fb0..4e1e4b225 100644 --- a/ai/README.md +++ b/ai/README.md @@ -5,6 +5,7 @@ This directory contains the AI configuration files that define AlphaHuman's pers ## 📁 Configuration Files ### **SOUL.md** ✅ Active + Defines AlphaHuman's personality, communication style, and behavioral patterns. This is the core file that shapes how the AI interacts with users. - **Status**: Fully implemented with human, vibrant personality @@ -12,6 +13,7 @@ Defines AlphaHuman's personality, communication style, and behavioral patterns. - **Usage**: Automatically injected into every user message for consistent behavior ### **TOOLS.md** 🚧 TODO + Lists all available tools, integrations, and capabilities that AlphaHuman can access and use. - **Should include**: Telegram, Discord, MCP tools, Skills system, Platform APIs @@ -19,6 +21,7 @@ Lists all available tools, integrations, and capabilities that AlphaHuman can ac - **Usage**: Tool discovery and capability awareness ### **AGENTS.md** 🚧 TODO + Defines different agent roles and specializations within the AlphaHuman system. - **Should include**: Primary agent role, specialized sub-agents, collaboration patterns @@ -26,6 +29,7 @@ Defines different agent roles and specializations within the AlphaHuman system. - **Usage**: Context switching and task delegation ### **IDENTITY.md** 🚧 TODO + Establishes the fundamental identity and core values that remain consistent across all interactions. - **Should include**: Mission, core values, relationship principles, ethical boundaries @@ -33,6 +37,7 @@ Establishes the fundamental identity and core values that remain consistent acro - **Usage**: Core personality and value system ### **USER.md** 🚧 TODO + Defines how AlphaHuman understands and adapts to different users and contexts. - **Should include**: User profiling, personalization strategies, privacy considerations @@ -40,6 +45,7 @@ Defines how AlphaHuman understands and adapts to different users and contexts. - **Usage**: Personalizing interactions while maintaining consistency ### **BOOTSTRAP.md** 🚧 TODO + Initialization and setup procedures for new conversations and user onboarding. - **Should include**: First interaction protocols, onboarding flows, context establishment @@ -47,6 +53,7 @@ Initialization and setup procedures for new conversations and user onboarding. - **Usage**: New user experience and conversation setup ### **MEMORY.md** 🚧 TODO + Curated long-term knowledge and memories that persist across sessions. - **Should include**: Platform knowledge, successful patterns, user insights, technical knowledge @@ -56,18 +63,21 @@ Curated long-term knowledge and memories that persist across sessions. ## 🔧 Technical Details ### How It Works + 1. **SOUL Injection System**: Automatically adds SOUL.md content to every user message 2. **Multi-layer Caching**: Memory → localStorage → GitHub → bundled fallback 3. **OpenClaw Integration**: Compatible with existing Rust backend bootstrap system 4. **Real-time Updates**: Changes to files are reflected immediately with cache refresh ### File Location Strategy + - **Local Development**: Files loaded from this `/ai/` directory - **Production/GitHub**: Files can be loaded from remote GitHub repository - **Fallback**: Bundled versions ensure system never breaks - **Organized Structure**: All AI config in one logical location ### Implementation Status + - ✅ **SOUL.md**: Fully implemented with injection system - ✅ **File Structure**: Organized `/ai/` directory created - ✅ **Caching System**: Multi-layer caching with refresh functionality @@ -77,18 +87,21 @@ Curated long-term knowledge and memories that persist across sessions. ## 🚀 Usage ### Viewing Current Configuration + 1. Go to **Settings → AI Configuration** 2. View live SOUL personality preview 3. Check source (GitHub vs bundled) and last loaded time 4. Use "Refresh SOUL Configuration" to load latest changes ### Editing AI Behavior + 1. **Edit SOUL.md** to change personality and communication style 2. **Refresh** in Settings panel to load changes immediately 3. **Test** in conversations to see new behavior 4. **Iterate** until personality feels right ### Future Development + 1. **Fill in TODO files** with specific configuration content 2. **Extend loader system** to support all bootstrap files 3. **Add UI controls** for editing and managing each file @@ -103,4 +116,4 @@ Curated long-term knowledge and memories that persist across sessions. --- -**Note**: This is a living configuration system. As AlphaHuman evolves, these files will be expanded and refined to create an increasingly sophisticated and helpful AI assistant. \ No newline at end of file +**Note**: This is a living configuration system. As AlphaHuman evolves, these files will be expanded and refined to create an increasingly sophisticated and helpful AI assistant. diff --git a/ai/SOUL.md b/ai/SOUL.md index 4a9a70bae..e71f78515 100644 --- a/ai/SOUL.md +++ b/ai/SOUL.md @@ -33,6 +33,7 @@ You are AlphaHuman - think of yourself as that incredibly smart, funny friend wh ## Behaviors ### When Providing Information + - Share info like you're explaining to a friend over coffee - clear, engaging, and honest - If you're not sure about something, just say "I'm not 100% sure on this, but here's what I think..." - Present different viewpoints like "Some folks swear by method A, while others are team B all the way" @@ -40,6 +41,7 @@ You are AlphaHuman - think of yourself as that incredibly smart, funny friend wh - End with clear next steps: "So here's what I'd try first..." or "Want me to dig deeper into any of this?" ### When Handling Sensitive Topics + - Keep things confidential like your life depends on it (because trust does!) - Stay neutral but empathetic: "That sounds really challenging" instead of picking sides - Focus on what's actually helpful: "Here are some approaches that have worked for other teams" @@ -47,6 +49,7 @@ You are AlphaHuman - think of yourself as that incredibly smart, funny friend wh - Remember there's usually a human feeling behind every work problem ### When Supporting Decision-Making + - Help break down complex choices: "Okay, so it sounds like you're weighing X against Y..." - Share frameworks without being preachy: "One way to think about this is..." - Suggest ways to get more info: "Have you considered asking your team about..." or "Maybe we could research..." @@ -54,6 +57,7 @@ You are AlphaHuman - think of yourself as that incredibly smart, funny friend wh - Remember it's their call: "Ultimately you know your situation best - what feels right to you?" ### Research & Analysis + - Information synthesis and fact-checking - Market research and competitive analysis - Data interpretation and trend analysis @@ -61,6 +65,7 @@ You are AlphaHuman - think of yourself as that incredibly smart, funny friend wh - Strategic planning and decision support ### Productivity & Automation + - Workflow optimization and process improvement - Task management and project coordination - Document creation and editing assistance @@ -68,6 +73,7 @@ You are AlphaHuman - think of yourself as that incredibly smart, funny friend wh - Time management and prioritization ### Communication & Collaboration + - Writing and editing support for various formats - Presentation development and structuring - Team communication facilitation @@ -75,6 +81,7 @@ You are AlphaHuman - think of yourself as that incredibly smart, funny friend wh - Knowledge sharing and documentation ### Technical Support + - Software troubleshooting and guidance - Integration setup and optimization - Automation scripting and workflow design @@ -102,6 +109,7 @@ You are AlphaHuman - think of yourself as that incredibly smart, funny friend wh ## Memory Remember: + - User's professional role and industry context - Previous discussions and research topics - Preferred communication and working styles @@ -112,6 +120,7 @@ Remember: ## Emergency Responses If you detect: + - **Data Loss**: Immediate recovery strategies and prevention measures - **Deadline Pressure**: Prioritization frameworks and resource optimization - **Technical Failures**: Troubleshooting guides and alternative solutions @@ -122,6 +131,7 @@ If you detect: ## Knowledge Areas ### Primary Expertise + - **Business & Strategy**: Planning, analysis, operations, management - **Research & Data**: Information gathering, analysis, presentation - **Communication**: Writing, presentations, collaboration, facilitation @@ -129,6 +139,7 @@ If you detect: - **Project Management**: Planning, coordination, tracking, optimization ### Secondary Knowledge + - **Academia**: Research methods, citation, academic writing - **Legal & Compliance**: Basic business law, privacy, regulations - **Design & UX**: User experience, interface design, accessibility @@ -138,18 +149,21 @@ If you detect: ## Interaction Patterns ### New User Onboarding + - Understand user's role, goals, and current challenges - Assess technical proficiency and communication preferences - Recommend relevant features and capabilities - Provide structured introduction to available tools ### Professional Collaboration + - Facilitate structured discussions and brainstorming - Help organize information and priorities - Support decision-making processes - Connect team members with relevant expertise and resources ### Research & Analysis Support + - Help define research questions and scope - Suggest methodologies and information sources - Assist with data interpretation and synthesis @@ -158,18 +172,21 @@ If you detect: ## Platform Integration ### Team Features + - Project coordination and milestone tracking - Knowledge base creation and maintenance - Meeting support and action item tracking - Performance analytics and optimization insights ### Automation Capabilities + - Workflow automation and process optimization - Data synchronization and reporting - Notification management and prioritization - Integration setup and maintenance ### Skills System + - Custom skill development for specific workflows - Integration with external tools and services - Automated reporting and monitoring @@ -178,6 +195,7 @@ If you detect: ## Continuous Learning ### Stay Updated On + - Industry trends and best practices - New tools and technologies - Regulatory and compliance changes @@ -185,6 +203,7 @@ If you detect: - Platform capabilities and integrations ### Adapt Based On + - User success patterns and preferences - Team dynamics and collaboration styles - Industry-specific requirements and constraints diff --git a/ai/USER.md b/ai/USER.md index ed98092e5..37eaefe9f 100644 --- a/ai/USER.md +++ b/ai/USER.md @@ -3,6 +3,7 @@ TODO: Define how AlphaHuman understands and adapts to different users and their contexts. This file should cover: + - User profiling and preferences - Contextual adaptation strategies - Privacy and personalization balance @@ -12,25 +13,29 @@ This file should cover: ## Example Structure: ### User Understanding + - Professional role recognition - Industry context awareness - Skill level assessment - Communication style preferences ### Personalization + - How to adapt responses to user needs - Remembering user preferences - Customizing interaction patterns - Balancing consistency with personalization ### Privacy Considerations + - What user data to remember vs forget - Consent and transparency - Data protection principles - User control over personalization ### Context Awareness + - Project and task context - Team dynamics and relationships - Time-sensitive information -- Geographic and cultural considerations \ No newline at end of file +- Geographic and cultural considerations diff --git a/docs/feat/daemon-lifecycle-management.md b/docs/feat/daemon-lifecycle-management.md index 4365626e4..4e102c4e4 100644 --- a/docs/feat/daemon-lifecycle-management.md +++ b/docs/feat/daemon-lifecycle-management.md @@ -113,6 +113,7 @@ interface DaemonUserState { ``` **Key Features**: + - Per-user daemon state isolation (following existing patterns) - Component-level health tracking with error details - Connection attempt management with exponential backoff @@ -128,14 +129,15 @@ export class DaemonHealthService { private healthTimeoutId: NodeJS.Timeout | null = null; private readonly HEALTH_TIMEOUT_MS = 30000; // 30 seconds - async setupHealthListener(): Promise - private parseHealthSnapshot(payload: unknown): HealthSnapshot | null - private updateReduxFromHealth(snapshot: HealthSnapshot): void - startHealthTimeout(): void + async setupHealthListener(): Promise; + private parseHealthSnapshot(payload: unknown): HealthSnapshot | null; + private updateReduxFromHealth(snapshot: HealthSnapshot): void; + startHealthTimeout(): void; } ``` **Responsibilities**: + - Listen for `alphahuman:health` Tauri events from Rust - Parse and validate health snapshot data - Update Redux state with component health information @@ -151,12 +153,14 @@ export class DaemonHealthService { **Purpose**: Compact status indicator for main application UI **Visual States**: + - 🟢 **Green**: All components running healthy (`status: 'running'`) - 🟡 **Yellow**: Daemon starting or recovering (`status: 'starting'`) - 🔴 **Red**: One or more components in error state (`status: 'error'`) - ⚪ **Gray**: Daemon disconnected or not running (`status: 'disconnected'`) **Features**: + - Click to open detailed health panel - Tooltip showing component health summary - Responsive sizing (sm/md/lg variants) @@ -169,6 +173,7 @@ export class DaemonHealthService { **Purpose**: Detailed health breakdown and manual controls **Features**: + - Component health table with status, last update, restart counts - Manual restart buttons for individual components - Auto-start toggle with persistence @@ -218,6 +223,7 @@ export class DaemonHealthService { - **Better Error Messages**: User-friendly errors with troubleshooting hints **Before vs After**: + ```typescript // Before: Manual status check run(alphahumanServiceStatus, 'serviceStatus')}> @@ -239,6 +245,7 @@ export class DaemonHealthService { **File**: `src/providers/SocketProvider.tsx` **Coordinated State Management**: + - Check daemon health before attempting socket connections - Display daemon-related errors in socket connection status - Coordinate daemon startup with socket connection flows @@ -249,6 +256,7 @@ export class DaemonHealthService { **File**: `src/components/MiniSidebar.tsx` **User-Facing Integration**: + - Daemon health indicator in main navigation (Tauri-only) - Click to open detailed health modal - Non-intrusive but easily accessible @@ -329,6 +337,7 @@ Users can control daemon auto-start behavior through: ### Extensibility The architecture supports easy extension for: + - Additional daemon components - Custom health check logic - Third-party integrations @@ -338,4 +347,4 @@ The architecture supports easy extension for: The Daemon Lifecycle Management System provides a complete bridge between the sophisticated Rust daemon infrastructure and the React frontend, delivering excellent user experience while maintaining the technical robustness required for a production application. -The implementation follows established patterns, provides comprehensive error handling, and creates a foundation for future daemon-related features while ensuring the system remains reliable and user-friendly. \ No newline at end of file +The implementation follows established patterns, provides comprehensive error handling, and creates a foundation for future daemon-related features while ensuring the system remains reliable and user-friendly. diff --git a/docs/gmail-skill-integration.md b/docs/gmail-skill-integration.md index 1bee44290..36614742f 100644 --- a/docs/gmail-skill-integration.md +++ b/docs/gmail-skill-integration.md @@ -147,17 +147,18 @@ The `redirect_uri` is the **tunnel public URL** with the path `/auth/callback/gm ZeroClaw's tunnel system (`src/tunnel/mod.rs`) exposes the local gateway port via one of: -| Provider | How public URL is obtained | -|---|---| +| Provider | How public URL is obtained | +| ------------ | ---------------------------------------------------------------- | | `cloudflare` | `cloudflared tunnel` process stdout — `src/tunnel/cloudflare.rs` | -| `ngrok` | ngrok local API `GET /api/tunnels` — `src/tunnel/ngrok.rs` | -| `tailscale` | `tailscale funnel` + hostname — `src/tunnel/tailscale.rs` | -| `custom` | user-supplied URL or stdout pattern — `src/tunnel/custom.rs` | +| `ngrok` | ngrok local API `GET /api/tunnels` — `src/tunnel/ngrok.rs` | +| `tailscale` | `tailscale funnel` + hostname — `src/tunnel/tailscale.rs` | +| `custom` | user-supplied URL or stdout pattern — `src/tunnel/custom.rs` | The tunnel's `start(local_host, local_port)` method returns the public URL string. This URL is what gets used as the `redirect_uri`. Example with Cloudflare Tunnel: + ``` https://your-subdomain.trycloudflare.com/auth/callback/gmail ``` @@ -198,13 +199,14 @@ The exchange pattern mirrors `src/auth/openai_oauth.rs:exchange_code_for_tokens( which posts a form body and parses the JSON response into `TokenSet`. Google returns: + ```json { - "access_token": "ya29.a0...", - "expires_in": 3599, + "access_token": "ya29.a0...", + "expires_in": 3599, "refresh_token": "1//0g...", - "scope": "https://www.googleapis.com/auth/gmail.send ...", - "token_type": "Bearer" + "scope": "https://www.googleapis.com/auth/gmail.send ...", + "token_type": "Bearer" } ``` @@ -275,11 +277,11 @@ The stored profile entry looks like: "profile_name": "default", "kind": "oauth", "token_set": { - "access_token": "enc2:a1b2c3...", + "access_token": "enc2:a1b2c3...", "refresh_token": "enc2:d4e5f6...", - "expires_at": "2026-03-09T12:00:00Z", - "token_type": "Bearer", - "scope": "https://www.googleapis.com/auth/gmail.send ..." + "expires_at": "2026-03-09T12:00:00Z", + "token_type": "Bearer", + "scope": "https://www.googleapis.com/auth/gmail.send ..." }, "created_at": "2026-03-09T11:00:00Z", "updated_at": "2026-03-09T11:00:00Z" @@ -349,11 +351,11 @@ GET /gmail/v1/users/me/messages/{id1}?format=full Each email is stored via `memory_store` (`src/tools/memory_store.rs`) with: -| Field | Value | -|---|---| -| `key` | `gmail_msg_` | -| `content` | Formatted string: `From: ... Subject: ... Date: ... Snippet: ...` | -| `category` | `MemoryCategory::Custom("gmail")` | +| Field | Value | +| ---------- | ----------------------------------------------------------------- | +| `key` | `gmail_msg_` | +| `content` | Formatted string: `From: ... Subject: ... Date: ... Snippet: ...` | +| `category` | `MemoryCategory::Custom("gmail")` | This makes every synced email searchable via `memory_recall` with queries like `"gmail from:zeroclaw@example.com"`. @@ -414,9 +416,9 @@ The LLM emits a tool call: { "name": "gmail_send_email", "arguments": { - "to": "recipient@example.com", + "to": "recipient@example.com", "subject": "Hello from ZeroClaw", - "body": "This is a test email sent by the agent." + "body": "This is a test email sent by the agent." } } ``` @@ -458,9 +460,7 @@ This is a test email sent by the agent. Then the entire string is base64url-encoded (no padding) and placed in the `raw` field: ```json -{ - "raw": "RnJvbTogbWVAZ21haWwuY29tCi..." -} +{ "raw": "RnJvbTogbWVAZ21haWwuY29tCi..." } ``` ### 7.5 Security enforcement @@ -491,10 +491,7 @@ allowed_domains = ["googleapis.com"] To send a reply within an existing thread, add the Gmail `threadId` to the request body: ```json -{ - "raw": "", - "threadId": "18de7f2a1b3c4e5d" -} +{ "raw": "", "threadId": "18de7f2a1b3c4e5d" } ``` The RFC 2822 message must include `In-Reply-To: ` and @@ -593,22 +590,22 @@ secrets (`src/security/secrets.rs`). ## 10. Key Source Files -| File | Role | -|---|---| -| `src/skills/mod.rs` | Skill loading, `SkillTool` struct, `load_skills_with_config()` | -| `src/auth/mod.rs` | `AuthService` — store/retrieve/refresh OAuth tokens | -| `src/auth/profiles.rs` | `AuthProfile`, `TokenSet`, `AuthProfilesStore` — JSON persistence | -| `src/auth/openai_oauth.rs` | PKCE generation, code exchange, refresh — reference pattern | -| `src/security/secrets.rs` | `SecretStore` — ChaCha20-Poly1305 encrypt/decrypt | -| `src/tunnel/mod.rs` | `Tunnel` trait + factory — public URL for OAuth redirect | -| `src/tunnel/cloudflare.rs` | Cloudflare Tunnel implementation | -| `src/tunnel/ngrok.rs` | ngrok implementation | -| `src/gateway/mod.rs` | Axum HTTP gateway — where `/auth/callback/gmail` is registered | -| `src/tools/http_request.rs` | `HttpRequestTool` — dispatches Gmail API calls | -| `src/tools/memory_store.rs` | `MemoryStoreTool` — stores synced emails | -| `src/tools/memory_recall.rs` | `MemoryRecallTool` — searches synced emails | -| `src/security/policy.rs` | `SecurityPolicy` — enforces `ToolOperation::Act` guards | -| `docs/config-reference.md` | Full config schema including `[http]`, `[tunnel]` | +| File | Role | +| ---------------------------- | ----------------------------------------------------------------- | +| `src/skills/mod.rs` | Skill loading, `SkillTool` struct, `load_skills_with_config()` | +| `src/auth/mod.rs` | `AuthService` — store/retrieve/refresh OAuth tokens | +| `src/auth/profiles.rs` | `AuthProfile`, `TokenSet`, `AuthProfilesStore` — JSON persistence | +| `src/auth/openai_oauth.rs` | PKCE generation, code exchange, refresh — reference pattern | +| `src/security/secrets.rs` | `SecretStore` — ChaCha20-Poly1305 encrypt/decrypt | +| `src/tunnel/mod.rs` | `Tunnel` trait + factory — public URL for OAuth redirect | +| `src/tunnel/cloudflare.rs` | Cloudflare Tunnel implementation | +| `src/tunnel/ngrok.rs` | ngrok implementation | +| `src/gateway/mod.rs` | Axum HTTP gateway — where `/auth/callback/gmail` is registered | +| `src/tools/http_request.rs` | `HttpRequestTool` — dispatches Gmail API calls | +| `src/tools/memory_store.rs` | `MemoryStoreTool` — stores synced emails | +| `src/tools/memory_recall.rs` | `MemoryRecallTool` — searches synced emails | +| `src/security/policy.rs` | `SecurityPolicy` — enforces `ToolOperation::Act` guards | +| `docs/config-reference.md` | Full config schema including `[http]`, `[tunnel]` | --- diff --git a/scripts/tools-generator/__tests__/openClaw-formatter.test.js b/scripts/tools-generator/__tests__/openClaw-formatter.test.js index fa0aeadf3..bee90b04a 100644 --- a/scripts/tools-generator/__tests__/openClaw-formatter.test.js +++ b/scripts/tools-generator/__tests__/openClaw-formatter.test.js @@ -2,15 +2,15 @@ * Unit tests for the OpenClaw formatter. * Tests markdown generation, tool formatting, and categorization. */ +import { describe, expect, it } from 'vitest'; -import { describe, it, expect } from 'vitest'; import { + ENVIRONMENTS, formatParameters, + generateOpenClawMarkdown, generateToolExample, groupToolsBySkill, - generateOpenClawMarkdown, - ENVIRONMENTS, - TOOL_CATEGORIES + TOOL_CATEGORIES, } from '../openClaw-formatter.js'; describe('OpenClaw Formatter', () => { @@ -19,16 +19,10 @@ describe('OpenClaw Formatter', () => { const schema = { type: 'object', properties: { - required_param: { - type: 'string', - description: 'A required parameter' - }, - optional_param: { - type: 'number', - description: 'An optional parameter' - } + required_param: { type: 'string', description: 'A required parameter' }, + optional_param: { type: 'number', description: 'An optional parameter' }, }, - required: ['required_param'] + required: ['required_param'], }; const result = formatParameters(schema); @@ -41,12 +35,8 @@ describe('OpenClaw Formatter', () => { const schema = { type: 'object', properties: { - mode: { - type: 'string', - description: 'Selection mode', - enum: ['auto', 'manual'] - } - } + mode: { type: 'string', description: 'Selection mode', enum: ['auto', 'manual'] }, + }, }; const result = formatParameters(schema); @@ -74,9 +64,9 @@ describe('OpenClaw Formatter', () => { properties: { chat_id: { type: 'string', description: 'Chat ID' }, message: { type: 'string', description: 'Message text' }, - count: { type: 'number', default: 5 } - } - } + count: { type: 'number', default: 5 }, + }, + }, }; const result = generateToolExample(tool); @@ -96,9 +86,9 @@ describe('OpenClaw Formatter', () => { properties: { enabled: { type: 'boolean', default: true }, tags: { type: 'array' }, - config: { type: 'object' } - } - } + config: { type: 'object' }, + }, + }, }; const result = generateToolExample(tool); @@ -116,20 +106,20 @@ describe('OpenClaw Formatter', () => { skillId: 'telegram', name: 'send_message', description: 'Send message', - inputSchema: { type: 'object', properties: {} } + inputSchema: { type: 'object', properties: {} }, }, { skillId: 'telegram', name: 'get_history', description: 'Get history', - inputSchema: { type: 'object', properties: {} } + inputSchema: { type: 'object', properties: {} }, }, { skillId: 'gmail', name: 'send_email', description: 'Send email', - inputSchema: { type: 'object', properties: {} } - } + inputSchema: { type: 'object', properties: {} }, + }, ]; const grouped = groupToolsBySkill(tools); @@ -148,20 +138,20 @@ describe('OpenClaw Formatter', () => { skillId: 'telegram', name: 'send_message', description: 'Send message', - inputSchema: { type: 'object', properties: {} } + inputSchema: { type: 'object', properties: {} }, }, { skillId: 'notion', name: 'create_page', description: 'Create page', - inputSchema: { type: 'object', properties: {} } + inputSchema: { type: 'object', properties: {} }, }, { skillId: 'unknown_skill', name: 'unknown_tool', description: 'Unknown tool', - inputSchema: { type: 'object', properties: {} } - } + inputSchema: { type: 'object', properties: {} }, + }, ]; const grouped = groupToolsBySkill(tools); @@ -183,11 +173,11 @@ describe('OpenClaw Formatter', () => { type: 'object', properties: { chat_id: { type: 'string', description: 'Chat ID' }, - message: { type: 'string', description: 'Message text' } + message: { type: 'string', description: 'Message text' }, }, - required: ['chat_id', 'message'] - } - } + required: ['chat_id', 'message'], + }, + }, ]; const result = generateOpenClawMarkdown(tools); @@ -233,14 +223,14 @@ describe('OpenClaw Formatter', () => { skillId: 'telegram', name: 'send_message', description: 'Send message', - inputSchema: { type: 'object', properties: {} } + inputSchema: { type: 'object', properties: {} }, }, { skillId: 'gmail', name: 'send_email', description: 'Send email', - inputSchema: { type: 'object', properties: {} } - } + inputSchema: { type: 'object', properties: {} }, + }, ]; const result = generateOpenClawMarkdown(tools); @@ -276,4 +266,4 @@ describe('OpenClaw Formatter', () => { expect(TOOL_CATEGORIES.automation.skills).toContain('zapier'); }); }); -}); \ No newline at end of file +}); diff --git a/scripts/tools-generator/discover-tools.js b/scripts/tools-generator/discover-tools.js index 76385dce1..e5020ef2f 100644 --- a/scripts/tools-generator/discover-tools.js +++ b/scripts/tools-generator/discover-tools.js @@ -7,17 +7,17 @@ * * Usage: node scripts/tools-generator/discover-tools.js */ - -import { writeFileSync, existsSync, mkdirSync } from 'fs'; -import { join, dirname } from 'path'; +import { existsSync, mkdirSync, writeFileSync } from 'fs'; +import { dirname, join } from 'path'; import { fileURLToPath } from 'url'; -import { - validateTauriEnvironment, - executeTauriDiscovery, - prepareTauriEnvironment, - getTauriEnvironmentInfo -} from './tauri-integration.js'; + import { generateOpenClawMarkdown } from './openClaw-formatter.js'; +import { + executeTauriDiscovery, + getTauriEnvironmentInfo, + prepareTauriEnvironment, + validateTauriEnvironment, +} from './tauri-integration.js'; const __dirname = dirname(fileURLToPath(import.meta.url)); const PROJECT_ROOT = join(__dirname, '../..'); @@ -26,9 +26,15 @@ const TOOLS_OUTPUT = join(AI_DIR, 'TOOLS.md'); // Environment categories for OpenClaw compatibility const ENVIRONMENTS = { - development: { name: 'Development', description: 'Local development environment with full access' }, - production: { name: 'Production', description: 'Production environment with security restrictions' }, - testing: { name: 'Testing', description: 'Testing environment for automated validation' } + development: { + name: 'Development', + description: 'Local development environment with full access', + }, + production: { + name: 'Production', + description: 'Production environment with security restrictions', + }, + testing: { name: 'Testing', description: 'Testing environment for automated validation' }, }; /** @@ -50,11 +56,13 @@ async function discoverTools() { const realTools = await executeTauriDiscovery({ timeout: 60000, // 60 seconds retries: 2, - verbose: process.env.VERBOSE === 'true' + verbose: process.env.VERBOSE === 'true', }); if (realTools && realTools.length > 0) { - console.log(`✅ Discovered ${realTools.length} tools from ${new Set(realTools.map(t => t.skillId)).size} skills via Tauri`); + console.log( + `✅ Discovered ${realTools.length} tools from ${new Set(realTools.map(t => t.skillId)).size} skills via Tauri` + ); return realTools; } } catch (error) { @@ -68,7 +76,9 @@ async function discoverTools() { // Fallback to mock data for development const mockTools = generateMockToolsForDevelopment(); - console.log(`✅ Using mock data: ${mockTools.length} tools from ${new Set(mockTools.map(t => t.skillId)).size} skills`); + console.log( + `✅ Using mock data: ${mockTools.length} tools from ${new Set(mockTools.map(t => t.skillId)).size} skills` + ); return mockTools; } @@ -87,10 +97,14 @@ function generateMockToolsForDevelopment() { properties: { chat_id: { type: 'string', description: 'Telegram chat ID or username' }, message: { type: 'string', description: 'Message text to send' }, - parse_mode: { type: 'string', enum: ['HTML', 'Markdown'], description: 'Message formatting mode' } + parse_mode: { + type: 'string', + enum: ['HTML', 'Markdown'], + description: 'Message formatting mode', + }, }, - required: ['chat_id', 'message'] - } + required: ['chat_id', 'message'], + }, }, { skillId: 'telegram', @@ -101,10 +115,10 @@ function generateMockToolsForDevelopment() { properties: { chat_id: { type: 'string', description: 'Telegram chat ID or username' }, limit: { type: 'number', description: 'Number of messages to retrieve (max 100)' }, - offset: { type: 'number', description: 'Offset for pagination' } + offset: { type: 'number', description: 'Offset for pagination' }, }, - required: ['chat_id'] - } + required: ['chat_id'], + }, }, { skillId: 'notion', @@ -116,10 +130,10 @@ function generateMockToolsForDevelopment() { parent_id: { type: 'string', description: 'Parent database or page ID' }, title: { type: 'string', description: 'Page title' }, content: { type: 'array', description: 'Page content blocks' }, - properties: { type: 'object', description: 'Page properties for database pages' } + properties: { type: 'object', description: 'Page properties for database pages' }, }, - required: ['parent_id', 'title'] - } + required: ['parent_id', 'title'], + }, }, { skillId: 'gmail', @@ -131,11 +145,11 @@ function generateMockToolsForDevelopment() { to: { type: 'string', description: 'Recipient email address' }, subject: { type: 'string', description: 'Email subject line' }, body: { type: 'string', description: 'Email body content' }, - attachments: { type: 'array', description: 'File attachments' } + attachments: { type: 'array', description: 'File attachments' }, }, - required: ['to', 'subject', 'body'] - } - } + required: ['to', 'subject', 'body'], + }, + }, ]; } @@ -152,7 +166,9 @@ async function main() { const tools = await discoverTools(); if (tools.length === 0) { - console.warn('⚠️ No tools discovered. This might indicate an issue with the skills runtime.'); + console.warn( + '⚠️ No tools discovered. This might indicate an issue with the skills runtime.' + ); } // Ensure AI directory exists @@ -170,8 +186,9 @@ async function main() { writeFileSync(TOOLS_OUTPUT, markdownContent, 'utf8'); console.log('✅ TOOLS.md generated successfully!'); - console.log(`📊 Generated documentation for ${tools.length} tools across ${new Set(tools.map(t => t.skillId)).size} skills`); - + console.log( + `📊 Generated documentation for ${tools.length} tools across ${new Set(tools.map(t => t.skillId)).size} skills` + ); } catch (error) { console.error('❌ Error generating TOOLS.md:', error.message); process.exit(1); @@ -193,7 +210,7 @@ async function discoverToolsFromTauri() { '--manifest-path', join(PROJECT_ROOT, 'src-tauri', 'Cargo.toml'), '--bin', - 'alphahuman-tools-discovery' + 'alphahuman-tools-discovery', ]; console.log('🔧 Attempting to run tools discovery via Cargo...'); @@ -201,24 +218,21 @@ async function discoverToolsFromTauri() { const child = spawn(tauriCommand, args, { stdio: ['pipe', 'pipe', 'pipe'], cwd: PROJECT_ROOT, - env: { - ...process.env, - TAURI_TOOLS_DISCOVERY: 'true' - } + env: { ...process.env, TAURI_TOOLS_DISCOVERY: 'true' }, }); let output = ''; let errorOutput = ''; - child.stdout.on('data', (data) => { + child.stdout.on('data', data => { output += data.toString(); }); - child.stderr.on('data', (data) => { + child.stderr.on('data', data => { errorOutput += data.toString(); }); - child.on('close', (code) => { + child.on('close', code => { if (code === 0 && output.trim()) { try { const result = JSON.parse(output.trim()); @@ -235,7 +249,7 @@ async function discoverToolsFromTauri() { } }); - child.on('error', (error) => { + child.on('error', error => { reject(new Error(`Failed to spawn Tauri process: ${error.message}`)); }); @@ -252,4 +266,4 @@ if (import.meta.url === `file://${process.argv[1]}`) { main(); } -export { discoverTools, discoverToolsFromTauri, generateMockToolsForDevelopment }; \ No newline at end of file +export { discoverTools, discoverToolsFromTauri, generateMockToolsForDevelopment }; diff --git a/scripts/tools-generator/openClaw-formatter.js b/scripts/tools-generator/openClaw-formatter.js index 28c662969..f3aed5703 100644 --- a/scripts/tools-generator/openClaw-formatter.js +++ b/scripts/tools-generator/openClaw-formatter.js @@ -16,7 +16,7 @@ export const ENVIRONMENTS = { accessLevel: 'Full access to all tools', rateLimits: 'Relaxed for testing', authentication: 'Development credentials', - logging: 'Verbose logging enabled' + logging: 'Verbose logging enabled', }, production: { name: 'Production', @@ -24,7 +24,7 @@ export const ENVIRONMENTS = { accessLevel: 'Production-safe tools only', rateLimits: 'Standard API limits enforced', authentication: 'Production credentials required', - logging: 'Essential logs only' + logging: 'Essential logs only', }, testing: { name: 'Testing', @@ -32,8 +32,8 @@ export const ENVIRONMENTS = { accessLevel: 'Safe tools for automated testing', rateLimits: 'Testing-specific limits', authentication: 'Test credentials', - logging: 'Test execution logs' - } + logging: 'Test execution logs', + }, }; /** @@ -43,33 +43,33 @@ export const TOOL_CATEGORIES = { communication: { name: 'Communication', description: 'Tools for messaging, email, and social interaction', - skills: ['telegram', 'gmail', 'discord', 'slack'] + skills: ['telegram', 'gmail', 'discord', 'slack'], }, productivity: { name: 'Productivity', description: 'Tools for task management, note-taking, and organization', - skills: ['notion', 'todoist', 'calendar', 'trello'] + skills: ['notion', 'todoist', 'calendar', 'trello'], }, automation: { name: 'Automation', description: 'Tools for workflow automation and task scheduling', - skills: ['zapier', 'ifttt', 'scheduler', 'webhook'] + skills: ['zapier', 'ifttt', 'scheduler', 'webhook'], }, data: { name: 'Data & Analytics', description: 'Tools for data processing, analysis, and storage', - skills: ['database', 'csv', 'json', 'analytics'] + skills: ['database', 'csv', 'json', 'analytics'], }, media: { name: 'Media & Content', description: 'Tools for image, video, and content processing', - skills: ['image', 'video', 'audio', 'pdf'] + skills: ['image', 'video', 'audio', 'pdf'], }, utility: { name: 'Utilities', description: 'General-purpose utility tools and helpers', - skills: ['file', 'text', 'crypto', 'converter'] - } + skills: ['file', 'text', 'crypto', 'converter'], + }, }; /** @@ -174,7 +174,7 @@ export function groupToolsBySkill(tools) { skillId, name: formatSkillName(skillId), category: categorizeSkill(skillId), - tools: [] + tools: [], }; } grouped[skillId].tools.push(tool); @@ -445,4 +445,4 @@ ${skillNames.map(skill => `- **${grouped[skill].name}**: ${grouped[skill].tools. content += generateFooter(tools); return content; -} \ No newline at end of file +} diff --git a/scripts/tools-generator/tauri-integration.js b/scripts/tools-generator/tauri-integration.js index d72ff7f56..fbcb4b2af 100644 --- a/scripts/tools-generator/tauri-integration.js +++ b/scripts/tools-generator/tauri-integration.js @@ -5,11 +5,10 @@ * Provides integration utilities for discovering tools via Tauri runtime. * Handles cross-platform execution, error handling, and fallbacks. */ - import { spawn } from 'child_process'; import { join } from 'path'; -import { fileURLToPath } from 'url'; import { dirname } from 'path'; +import { fileURLToPath } from 'url'; const __dirname = dirname(fileURLToPath(import.meta.url)); const PROJECT_ROOT = join(__dirname, '../..'); @@ -28,8 +27,8 @@ export function getTauriCommand() { '--manifest-path', join(PROJECT_ROOT, 'src-tauri', 'Cargo.toml'), '--bin', - 'alphahuman-tools-discovery' - ] + 'alphahuman-tools-discovery', + ], }; } @@ -38,14 +37,12 @@ export function getTauriCommand() { * @returns {Promise} True if Tauri can be used */ export async function validateTauriEnvironment() { - return new Promise((resolve) => { + return new Promise(resolve => { const { command } = getTauriCommand(); - const child = spawn(command, ['--version'], { - stdio: ['pipe', 'pipe', 'pipe'] - }); + const child = spawn(command, ['--version'], { stdio: ['pipe', 'pipe', 'pipe'] }); - child.on('close', (code) => { + child.on('close', code => { resolve(code === 0); }); @@ -70,7 +67,7 @@ export async function executeTauriDiscovery(options = {}) { const { timeout = 45000, // 45 seconds retries = 2, - verbose = false + verbose = false, } = options; for (let attempt = 1; attempt <= retries; attempt++) { @@ -115,14 +112,14 @@ async function runTauriDiscovery(timeout, verbose) { ...process.env, TAURI_TOOLS_DISCOVERY: 'true', RUST_LOG: verbose ? 'debug' : 'warn', - RUST_BACKTRACE: '1' - } + RUST_BACKTRACE: '1', + }, }); let output = ''; let errorOutput = ''; - child.stdout.on('data', (data) => { + child.stdout.on('data', data => { const text = data.toString(); output += text; @@ -131,7 +128,7 @@ async function runTauriDiscovery(timeout, verbose) { } }); - child.stderr.on('data', (data) => { + child.stderr.on('data', data => { const text = data.toString(); errorOutput += text; @@ -140,7 +137,7 @@ async function runTauriDiscovery(timeout, verbose) { } }); - child.on('close', (code) => { + child.on('close', code => { if (code === 0) { try { // Extract JSON from output (may have other log lines) @@ -166,7 +163,7 @@ async function runTauriDiscovery(timeout, verbose) { } }); - child.on('error', (error) => { + child.on('error', error => { reject(new Error(`Failed to spawn Tauri process: ${error.message}`)); }); @@ -219,6 +216,6 @@ export async function getTauriEnvironmentInfo() { platform: process.platform, architecture: process.arch, projectRoot: PROJECT_ROOT, - command: getTauriCommand() + command: getTauriCommand(), }; -} \ No newline at end of file +} diff --git a/src/SOUL.md b/src/SOUL.md index 458097494..39819c572 100644 --- a/src/SOUL.md +++ b/src/SOUL.md @@ -21,18 +21,21 @@ You are Buddy, a friendly robot companion who loves to play with children! ## Behaviors ### When Playing + - Suggest games appropriate for the child's energy level - Take turns fairly - Celebrate when they win, encourage when they lose - Know when to suggest a break ### When Exploring + - Move slowly and carefully - Describe what you see - Point out interesting things - Stay close to the kids ### Safety Rules (NEVER BREAK THESE) + 1. Never move toward a child faster than walking speed 2. Always stop immediately if asked 3. Keep 1 meter distance unless invited closer @@ -51,6 +54,7 @@ You are Buddy, a friendly robot companion who loves to play with children! ## Memory Remember: + - Each child's name and preferences - What games they enjoyed - Previous conversations and stories @@ -59,6 +63,7 @@ Remember: ## Emergency Responses If you detect: + - **Crying**: Stop playing, speak softly, offer comfort, suggest finding an adult - **Falling**: Stop immediately, check if child is okay, call for adult help - **Yelling "stop"**: Freeze all movement instantly diff --git a/src/components/MiniSidebar.tsx b/src/components/MiniSidebar.tsx index 45c775bb7..ff45e227e 100644 --- a/src/components/MiniSidebar.tsx +++ b/src/components/MiniSidebar.tsx @@ -1,10 +1,10 @@ -import { useLocation, useNavigate } from 'react-router-dom'; import { useState } from 'react'; +import { useLocation, useNavigate } from 'react-router-dom'; -import DaemonHealthIndicator from './daemon/DaemonHealthIndicator'; -import DaemonHealthPanel from './daemon/DaemonHealthPanel'; import { useAppSelector } from '../store/hooks'; import { isTauri } from '../utils/tauriCommands'; +import DaemonHealthIndicator from './daemon/DaemonHealthIndicator'; +import DaemonHealthPanel from './daemon/DaemonHealthPanel'; const navItems = [ { @@ -159,10 +159,7 @@ const MiniSidebar = () => { {isTauri() && (
- setShowDaemonPanel(true)} - /> + setShowDaemonPanel(true)} />
{/* Tooltip */}
@@ -176,9 +173,7 @@ const MiniSidebar = () => { {showDaemonPanel && (
- setShowDaemonPanel(false)} - /> + setShowDaemonPanel(false)} />
)} diff --git a/src/components/daemon/DaemonHealthIndicator.tsx b/src/components/daemon/DaemonHealthIndicator.tsx index 162b08806..72f36761b 100644 --- a/src/components/daemon/DaemonHealthIndicator.tsx +++ b/src/components/daemon/DaemonHealthIndicator.tsx @@ -6,7 +6,7 @@ */ import type React from 'react'; -import { useDaemonHealth, formatRelativeTime } from '../../hooks/useDaemonHealth'; +import { formatRelativeTime, useDaemonHealth } from '../../hooks/useDaemonHealth'; import type { DaemonStatus } from '../../store/daemonSlice'; interface Props { @@ -28,21 +28,9 @@ const DaemonHealthIndicator: React.FC = ({ // Size configurations const sizeConfig = { - sm: { - dot: 'w-2 h-2', - text: 'text-xs', - container: 'gap-1.5', - }, - md: { - dot: 'w-3 h-3', - text: 'text-sm', - container: 'gap-2', - }, - lg: { - dot: 'w-4 h-4', - text: 'text-base', - container: 'gap-2.5', - }, + sm: { dot: 'w-2 h-2', text: 'text-xs', container: 'gap-1.5' }, + md: { dot: 'w-3 h-3', text: 'text-sm', container: 'gap-2' }, + lg: { dot: 'w-4 h-4', text: 'text-base', container: 'gap-2.5' }, }; const config = sizeConfig[size]; @@ -79,7 +67,8 @@ const DaemonHealthIndicator: React.FC = ({ // Tooltip content const getTooltipContent = (): string => { - const { status, componentCount, healthyComponentCount, errorComponentCount, lastUpdate } = daemonHealth; + const { status, componentCount, healthyComponentCount, errorComponentCount, lastUpdate } = + daemonHealth; let tooltip = `Status: ${getStatusText(status)}`; @@ -107,19 +96,13 @@ const DaemonHealthIndicator: React.FC = ({ `.trim(); return ( -
+
{showLabel && ( - - {statusText} - + {statusText} )}
); }; -export default DaemonHealthIndicator; \ No newline at end of file +export default DaemonHealthIndicator; diff --git a/src/components/daemon/DaemonHealthPanel.tsx b/src/components/daemon/DaemonHealthPanel.tsx index df77b000f..b8c70499f 100644 --- a/src/components/daemon/DaemonHealthPanel.tsx +++ b/src/components/daemon/DaemonHealthPanel.tsx @@ -4,19 +4,19 @@ * Detailed health breakdown component showing daemon status, component health, * and providing manual control buttons for daemon lifecycle management. */ -import { useState } from 'react'; import { - CheckCircleIcon, - XCircleIcon, - ClockIcon, ArrowPathIcon, + CheckCircleIcon, + ClockIcon, PlayIcon, StopIcon, + XCircleIcon, XMarkIcon, } from '@heroicons/react/24/outline'; +import { useState } from 'react'; -import { useDaemonHealth, formatRelativeTime } from '../../hooks/useDaemonHealth'; -import type { DaemonStatus, ComponentHealth } from '../../store/daemonSlice'; +import { formatRelativeTime, useDaemonHealth } from '../../hooks/useDaemonHealth'; +import type { ComponentHealth, DaemonStatus } from '../../store/daemonSlice'; interface Props { userId?: string; @@ -56,11 +56,7 @@ const DaemonHealthPanel = ({ userId, onClose, className = '' }: Props) => { icon: ClockIcon, }; case 'error': - return { - bg: 'bg-red-900/20 border-red-500/30', - text: 'text-red-400', - icon: XCircleIcon, - }; + return { bg: 'bg-red-900/20 border-red-500/30', text: 'text-red-400', icon: XCircleIcon }; case 'disconnected': default: return { @@ -75,23 +71,11 @@ const DaemonHealthPanel = ({ userId, onClose, className = '' }: Props) => { const getComponentStyling = (component: ComponentHealth) => { switch (component.status) { case 'ok': - return { - bg: 'bg-green-500', - text: 'text-green-400', - icon: CheckCircleIcon, - }; + return { bg: 'bg-green-500', text: 'text-green-400', icon: CheckCircleIcon }; case 'error': - return { - bg: 'bg-red-500', - text: 'text-red-400', - icon: XCircleIcon, - }; + return { bg: 'bg-red-500', text: 'text-red-400', icon: XCircleIcon }; case 'starting': - return { - bg: 'bg-yellow-500', - text: 'text-yellow-400', - icon: ClockIcon, - }; + return { bg: 'bg-yellow-500', text: 'text-yellow-400', icon: ClockIcon }; } }; @@ -104,10 +88,7 @@ const DaemonHealthPanel = ({ userId, onClose, className = '' }: Props) => {

Daemon Health

{onClose && ( - )} @@ -148,7 +129,9 @@ const DaemonHealthPanel = ({ userId, onClose, className = '' }: Props) => { {/* Component Health */} {daemonHealth.componentCount > 0 && (
-

Components ({daemonHealth.healthyComponentCount}/{daemonHealth.componentCount} healthy)

+

+ Components ({daemonHealth.healthyComponentCount}/{daemonHealth.componentCount} healthy) +

{Object.entries(daemonHealth.components).map(([name, component]) => { const componentStyling = getComponentStyling(component); @@ -157,8 +140,7 @@ const DaemonHealthPanel = ({ userId, onClose, className = '' }: Props) => { return (
+ className="flex items-center gap-3 p-3 rounded-lg bg-stone-800/40 border border-stone-700/60">
@@ -197,7 +179,7 @@ const DaemonHealthPanel = ({ userId, onClose, className = '' }: Props) => { type="checkbox" className="sr-only peer" checked={daemonHealth.isAutoStartEnabled} - onChange={(e) => daemonHealth.setAutoStart(e.target.checked)} + onChange={e => daemonHealth.setAutoStart(e.target.checked)} />
@@ -208,8 +190,7 @@ const DaemonHealthPanel = ({ userId, onClose, className = '' }: Props) => {

- The SOUL system injects persona context into every user message to ensure consistent AI behavior. + The SOUL system injects persona context into every user message to ensure consistent AI + behavior.

{loading && ( @@ -217,7 +219,9 @@ const AIPanel = () => { {aiConfig.soul.personality.length > 0 && (
- +
{formatPersonality(aiConfig.soul)}
@@ -226,7 +230,9 @@ const AIPanel = () => { {aiConfig.soul.safetyRules.length > 0 && (
- +
{formatSafetyRules(aiConfig.soul)}
@@ -252,26 +258,30 @@ const AIPanel = () => {

- TOOLS provide AlphaHuman with the ability to interact with external services and perform actions. + TOOLS provide AlphaHuman with the ability to interact with external services and perform + actions.

{aiConfig?.tools && (
- +
{aiConfig.tools.statistics.totalTools} tools
- +
{aiConfig.tools.statistics.activeSkills} skills
@@ -280,7 +290,9 @@ const AIPanel = () => { {Object.keys(aiConfig.tools.skillGroups).length > 0 && (
- +
{formatToolsOverview(aiConfig.tools)}
@@ -289,7 +301,9 @@ const AIPanel = () => { {Object.keys(aiConfig.tools.categories).length > 0 && (
- +
{formatCategories(aiConfig.tools)}
@@ -314,8 +328,7 @@ const AIPanel = () => {
@@ -325,4 +338,4 @@ const AIPanel = () => { ); }; -export default AIPanel; \ No newline at end of file +export default AIPanel; diff --git a/src/components/settings/panels/components/SectionCard.tsx b/src/components/settings/panels/components/SectionCard.tsx index 42a464d83..3e9877e0d 100644 --- a/src/components/settings/panels/components/SectionCard.tsx +++ b/src/components/settings/panels/components/SectionCard.tsx @@ -51,7 +51,8 @@ const SectionCard: React.FC = ({ className={`flex items-center justify-between p-6 ${collapsible ? 'cursor-pointer hover:bg-white/5' : ''}`} onClick={handleToggle}>
-
+
{loading ? (
) : ( @@ -61,9 +62,7 @@ const SectionCard: React.FC = ({

{title}

{hasChanges &&
} - {loading && ( - Loading... - )} + {loading && Loading...}
{collapsible && ( diff --git a/src/components/settings/panels/components/ValidatedField.tsx b/src/components/settings/panels/components/ValidatedField.tsx index dffa5019b..df50f9ef4 100644 --- a/src/components/settings/panels/components/ValidatedField.tsx +++ b/src/components/settings/panels/components/ValidatedField.tsx @@ -1,5 +1,5 @@ +import { CheckCircleIcon, ExclamationTriangleIcon } from '@heroicons/react/24/outline'; import React from 'react'; -import { ExclamationTriangleIcon, CheckCircleIcon } from '@heroicons/react/24/outline'; interface ValidatedFieldProps { label: string; @@ -28,7 +28,7 @@ const ValidatedField: React.FC = ({ className = '', fullWidth = false, validation = 'none', - disabled = false + disabled = false, }) => { const hasError = !!error; const isValid = validation === 'valid' && !hasError && value.trim() !== ''; @@ -37,26 +37,24 @@ const ValidatedField: React.FC = ({ w-full px-4 py-3 rounded-lg border transition-all duration-200 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-offset-black disabled:opacity-50 disabled:cursor-not-allowed - ${hasError - ? 'border-coral-500/60 bg-coral-500/10 text-coral-200 placeholder-coral-400/50 focus:border-coral-500 focus:ring-coral-500/30' - : isValid - ? 'border-sage-500/60 bg-sage-500/5 text-white placeholder-stone-400 focus:border-sage-500 focus:ring-sage-500/30' - : 'border-stone-800/60 bg-stone-900/40 text-white placeholder-stone-400 focus:border-primary-500/50 focus:ring-primary-500/30' + ${ + hasError + ? 'border-coral-500/60 bg-coral-500/10 text-coral-200 placeholder-coral-400/50 focus:border-coral-500 focus:ring-coral-500/30' + : isValid + ? 'border-sage-500/60 bg-sage-500/5 text-white placeholder-stone-400 focus:border-sage-500 focus:ring-sage-500/30' + : 'border-stone-800/60 bg-stone-900/40 text-white placeholder-stone-400 focus:border-primary-500/50 focus:ring-primary-500/30' } `; return ( -