diff --git a/harnessed_reasoning/config_functions.py b/harnessed_reasoning/config_functions.py new file mode 100644 index 0000000..07d4e48 --- /dev/null +++ b/harnessed_reasoning/config_functions.py @@ -0,0 +1,122 @@ +from typing import Dict, Any +from datetime import datetime +import uuid + + +async def hermes_get_reasoning_config(context: Dict[str, Any]) -> Dict[str, Any]: + """ + Get reasoning configuration for current user + + Args: + context: Request context containing user information + + Returns: + Configuration data for the current user + """ + from .core import HermesReasoningEngine + engine = HermesReasoningEngine() + user_id = engine._get_current_user_id(context) + + # Query database for user configuration + sql = """ + SELECT * FROM harnessed_reasoning_config + WHERE user_id = %(user_id)s + ORDER BY created_at DESC + LIMIT 1 + """ + try: + rows = await engine.db.sql(sql, {"user_id": user_id}) + if rows: + config = rows[0] + # Convert string booleans to actual booleans for UI + config["enable_cross_session_search"] = config["enable_cross_session_search"] == "1" + config["enable_skill_auto_loading"] = config["enable_skill_auto_loading"] == "1" + config["enable_error_recovery"] = config["enable_error_recovery"] == "1" + return {"success": True, "config": config} + else: + # Return default configuration + default_config = { + "id": f"default_{user_id}", + "user_id": user_id, + "max_reasoning_steps": 10, + "max_tool_calls_per_step": 5, + "enable_cross_session_search": True, + "enable_skill_auto_loading": True, + "safety_mode": "strict", + "max_context_tokens": 4000, + "enable_error_recovery": True, + "max_recovery_attempts": 3, + "created_at": datetime.now().isoformat(), + "updated_at": datetime.now().isoformat() + } + return {"success": True, "config": default_config} + except Exception as e: + return {"success": False, "error": str(e)} + + +async def hermes_save_reasoning_config(context: Dict[str, Any], config_data: Dict[str, Any]) -> Dict[str, Any]: + """ + Save reasoning configuration for current user + + Args: + context: Request context containing user information + config_data: Configuration data to save + + Returns: + Success status + """ + from .core import HermesReasoningEngine + engine = HermesReasoningEngine() + user_id = engine._get_current_user_id(context) + + # Convert boolean to string for database storage + config_data["enable_cross_session_search"] = "1" if config_data.get("enable_cross_session_search") else "0" + config_data["enable_skill_auto_loading"] = "1" if config_data.get("enable_skill_auto_loading") else "0" + config_data["enable_error_recovery"] = "1" if config_data.get("enable_error_recovery") else "0" + config_data["user_id"] = user_id + config_data["updated_at"] = datetime.now().isoformat() + + # Check if config already exists + sql_check = "SELECT id FROM harnessed_reasoning_config WHERE user_id = %(user_id)s" + try: + rows = await engine.db.sql(sql_check, {"user_id": user_id}) + if rows: + # Update existing config + config_data["id"] = rows[0]["id"] + config_data["created_at"] = rows[0]["created_at"] # Keep original created_at + sql_update = """ + UPDATE harnessed_reasoning_config SET + max_reasoning_steps = %(max_reasoning_steps)s, + max_tool_calls_per_step = %(max_tool_calls_per_step)s, + enable_cross_session_search = %(enable_cross_session_search)s, + enable_skill_auto_loading = %(enable_skill_auto_loading)s, + safety_mode = %(safety_mode)s, + max_context_tokens = %(max_context_tokens)s, + enable_error_recovery = %(enable_error_recovery)s, + max_recovery_attempts = %(max_recovery_attempts)s, + updated_at = %(updated_at)s + WHERE id = %(id)s + """ + await engine.db.sql(sql_update, config_data) + else: + # Create new config + config_data["id"] = str(uuid.uuid4()).replace("-", "")[:32] + config_data["created_at"] = config_data["updated_at"] + sql_insert = """ + INSERT INTO harnessed_reasoning_config ( + id, user_id, max_reasoning_steps, max_tool_calls_per_step, + enable_cross_session_search, enable_skill_auto_loading, safety_mode, + max_context_tokens, enable_error_recovery, max_recovery_attempts, + created_at, updated_at + ) VALUES ( + %(id)s, %(user_id)s, %(max_reasoning_steps)s, %(max_tool_calls_per_step)s, + %(enable_cross_session_search)s, %(enable_skill_auto_loading)s, %(safety_mode)s, + %(max_context_tokens)s, %(enable_error_recovery)s, %(max_recovery_attempts)s, + %(created_at)s, %(updated_at)s + ) + """ + await engine.db.sql(sql_insert, config_data) + + return {"success": True} + except Exception as e: + return {"success": False, "error": str(e)} diff --git a/harnessed_reasoning/init.py b/harnessed_reasoning/init.py new file mode 100644 index 0000000..f7ec39a --- /dev/null +++ b/harnessed_reasoning/init.py @@ -0,0 +1,18 @@ +from ahserver.serverenv import ServerEnv +from .core import ( + hermes_reason_and_execute, + hermes_get_reasoning_session, + hermes_list_reasoning_sessions, + hermes_get_reasoning_config +) +from .config_functions import ( + hermes_save_reasoning_config +) + +def load_harnessed_reasoning(): + env = ServerEnv() + env.hermes_reason_and_execute = hermes_reason_and_execute + env.hermes_get_reasoning_session = hermes_get_reasoning_session + env.hermes_list_reasoning_sessions = hermes_list_reasoning_sessions + env.hermes_get_reasoning_config = hermes_get_reasoning_config + env.hermes_save_reasoning_config = hermes_save_reasoning_config \ No newline at end of file diff --git a/models/harnessed_reasoning_config.json b/models/harnessed_reasoning_config.json new file mode 100644 index 0000000..38f304b --- /dev/null +++ b/models/harnessed_reasoning_config.json @@ -0,0 +1,105 @@ +{ + "summary": [ + { + "name": "harnessed_reasoning_config", + "title": "Hermes Reasoning module configuration settings", + "primary": "id" + } + ], + "fields": [ + { + "name": "id", + "title": "Unique configuration identifier", + "type": "str", + "length": 32, + "nullable": "no" + }, + { + "name": "user_id", + "title": "User ID for multi-user isolation", + "type": "str", + "length": 32, + "nullable": "no" + }, + { + "name": "max_reasoning_steps", + "title": "Maximum reasoning steps per task", + "type": "int", + "nullable": "no", + "default": "10" + }, + { + "name": "max_tool_calls_per_step", + "title": "Maximum tool calls per reasoning step", + "type": "int", + "nullable": "no", + "default": "5" + }, + { + "name": "enable_cross_session_search", + "title": "Enable automatic session search", + "type": "str", + "length": "1", + "nullable": "no", + "default": "1" + }, + { + "name": "enable_skill_auto_loading", + "title": "Enable automatic skill loading", + "type": "str", + "length": "1", + "nullable": "no", + "default": "1" + }, + { + "name": "safety_mode", + "title": "Safety mode: strict, moderate, lenient", + "type": "str", + "length": "20", + "nullable": "no", + "default": "strict" + }, + { + "name": "max_context_tokens", + "title": "Maximum tokens for reasoning context", + "type": "int", + "nullable": "no", + "default": "4000" + }, + { + "name": "enable_error_recovery", + "title": "Enable automatic error recovery", + "type": "str", + "length": "1", + "nullable": "no", + "default": "1" + }, + { + "name": "max_recovery_attempts", + "title": "Maximum recovery attempts per error", + "type": "int", + "nullable": "no", + "default": "3" + }, + { + "name": "created_at", + "title": "Creation timestamp", + "type": "timestamp", + "nullable": "no" + }, + { + "name": "updated_at", + "title": "Last update timestamp", + "type": "timestamp", + "nullable": "no" + } + ], + "indexes": [ + { + "name": "idx_user_config", + "idxtype": "index", + "idxfields": ["user_id"] + } + ], + "codes": [] +} \ No newline at end of file diff --git a/skill/SKILL.md b/skill/SKILL.md new file mode 100644 index 0000000..2730081 --- /dev/null +++ b/skill/SKILL.md @@ -0,0 +1,94 @@ +--- +name: harnessed-reasoning-module-implementation +version: 1.0.0 +description: Complete production-ready implementation of Hermes Reasoning Engine module with advanced reasoning capabilities, planning, tool coordination, error recovery, and cross-session intelligence. +trigger_conditions: + - User requests to implement or extend Hermes Reasoning functionality + - Task involves AI reasoning engine development + - Need for context-aware reasoning with safety checks +--- + +# Harnessed Reasoning Module Implementation Guide + +## Overview + +This skill provides the complete implementation of the **Harnessed Reasoning** module, which implements advanced reasoning capabilities for the Hermes Agent ecosystem: + +- **Context-aware reasoning**: Combines memory, sessions, and skills for intelligent decision-making +- **Task decomposition**: Breaks complex requests into executable subtasks +- **Tool selection**: Automatically selects appropriate tools for each subtask +- **Safety checks**: Multi-level safety validation (strict/moderate/lenient modes) +- **Error recovery**: Automatic recovery strategies for failed tool executions +- **Cross-session intelligence**: Leverages past sessions for better reasoning +- **Multi-user isolation**: Complete user separation with proper authentication + +## Module Structure + +``` +harnessed_reasoning/ +├── harnessed_reasoning/ # Python package +│ ├── __init__.py # Empty (Python package marker) +│ ├── init.py # Module initialization with load_harnessed_reasoning() +│ ├── core.py # Core reasoning engine (HermesReasoningEngine class) +│ └── config_functions.py # Configuration get/save functions +├── wwwroot/ # Frontend resources (.ui files) +├── models/ # Database table definitions (JSON) +├── json/ # CRUD operation definitions (JSON) +├── init/ # Initialization data +├── skill/ # This skill documentation +├── pyproject.toml # Python packaging +└── README.md # Module documentation +``` + +## Database Tables + +- **harnessed_reasoning_config**: User-specific reasoning configuration +- **harnessed_reasoning_sessions**: Reasoning session records with execution plans + +## Key Features + +### 1. Reasoning Engine +- Configurable max reasoning steps and tool calls per step +- Intelligent context gathering from memory, sessions, and skills +- Keyword-based tool selection and parameter inference +- Confidence scoring for execution plans + +### 2. Safety System +- Three safety modes: strict, moderate, lenient +- Dangerous command detection for terminal actions +- Path traversal protection for file operations +- User preference enforcement + +### 3. Error Recovery +- Automatic retry with exponential backoff +- Context-aware recovery strategies (e.g., file not found -> search for similar files) +- Configurable max recovery attempts + +## Configuration + +```python +class ReasoningConfig: + max_reasoning_steps: int = 10 + max_tool_calls_per_step: int = 5 + enable_cross_session_search: bool = True + enable_skill_auto_loading: bool = True + safety_mode: str = "strict" + max_context_tokens: int = 4000 + enable_error_recovery: bool = True + max_recovery_attempts: int = 3 +``` + +## Exposed Functions + +- `hermes_reason_and_execute(request, execute_immediately)` - Main entry point +- `hermes_get_reasoning_session(session_id)` - Retrieve session by ID +- `hermes_list_reasoning_sessions(limit, offset)` - List user sessions +- `hermes_get_reasoning_config()` - Get default configuration +- `hermes_save_reasoning_config(context, config_data)` - Save user configuration + +## Related Skills + +- [module-development-spec](module-development-spec): Module development workflow +- [bricks-framework](bricks-framework): Frontend development framework +- [sqlor-database-module](sqlor-database-module): Database integration patterns +- [harnessed-agent-skill-architecture](harnessed-agent-skill-architecture): Dual skill architecture diff --git a/wwwroot/ios_design.css b/wwwroot/ios_design.css new file mode 100644 index 0000000..2e24515 --- /dev/null +++ b/wwwroot/ios_design.css @@ -0,0 +1,114 @@ +/* + * iOS Design System for Hermes Modules + * iPhone-style UI with Apple HIG principles + * Applied via inline options and direct element styling + */ + +/* === iOS Design Tokens === */ +body { + background-color: #F2F2F7 !important; + font-family: -apple-system, BlinkMacSystemFont, 'SF Pro Display', 'SF Pro Text', 'Helvetica Neue', sans-serif !important; + -webkit-font-smoothing: antialiased; + margin: 0; + padding: 0; +} + +/* === iOS Navigation Bar === */ +.ios-navbar { + background-color: rgba(249, 249, 249, 0.94) !important; + backdrop-filter: blur(20px); + -webkit-backdrop-filter: blur(20px); + border-bottom: 0.5px solid rgba(60, 60, 67, 0.3) !important; +} + +.ios-navbar-title { + font-size: 34px !important; + font-weight: 700 !important; + color: #000000 !important; + letter-spacing: 0.37px; +} + +.ios-navbar-subtitle { + font-size: 13px !important; + font-weight: 400 !important; + color: rgba(60, 60, 67, 0.6) !important; +} + +/* === iOS Card === */ +.ios-card { + background-color: #FFFFFF !important; + border-radius: 12px !important; + padding: 16px !important; + margin: 8px 16px !important; + box-shadow: 0 1px 3px rgba(0,0,0,0.04), 0 1px 2px rgba(0,0,0,0.06) !important; + border: none !important; +} + +/* === iOS Scroll Area === */ +.ios-scroll-area { + -webkit-overflow-scrolling: touch; +} + +/* === iOS Tab Bar === */ +.ios-tabbar { + background-color: rgba(249, 249, 249, 0.94) !important; + backdrop-filter: blur(20px); + -webkit-backdrop-filter: blur(20px); + border-top: 0.5px solid rgba(60, 60, 67, 0.3) !important; +} + +/* === iOS Stat Card === */ +.ios-stat-card { + background: linear-gradient(135deg, #007AFF, #5856D6) !important; + border-radius: 16px !important; + color: #FFFFFF !important; +} + +.ios-stat-value { + font-size: 34px !important; + font-weight: 700 !important; +} + +.ios-stat-label { + font-size: 13px !important; + font-weight: 500 !important; + opacity: 0.8; +} + +/* === iOS Group === */ +.ios-group { + background-color: #FFFFFF !important; + border-radius: 12px !important; + margin: 8px 16px !important; + overflow: hidden; +} + +/* === iOS Button === */ +.ios-btn { + background-color: #007AFF !important; + color: #FFFFFF !important; + border: none !important; + border-radius: 12px !important; + font-size: 17px !important; + font-weight: 600 !important; +} + +.ios-btn-secondary { + background-color: rgba(0, 122, 255, 0.12) !important; + color: #007AFF !important; +} + +/* === iOS Badge === */ +.ios-badge { + background-color: #FF3B30 !important; + color: #FFFFFF !important; + border-radius: 10px !important; + font-size: 12px !important; + font-weight: 600 !important; +} + +/* === iOS Status Dots === */ +.ios-status-active { color: #34C759 !important; } +.ios-status-pending { color: #FF9500 !important; } +.ios-status-failed { color: #FF3B30 !important; } +.ios-status-inactive { color: #8E8E93 !important; }