feat: add models, CRUD UI, config functions and config model definitions
- Add hermes_executions, hermes_tasks, hermes_workflows, task_dependencies models - Add harnessed_agent_config model and view CRUD JSON - Add config_functions.py for agent configuration - Add agent_config.ui and ios_design.css frontend files
This commit is contained in:
parent
434ac73465
commit
ca16edf609
116
harnessed_agent/config_functions.py
Normal file
116
harnessed_agent/config_functions.py
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
from typing import Dict, Any
|
||||||
|
from datetime import datetime
|
||||||
|
import uuid
|
||||||
|
|
||||||
|
|
||||||
|
async def harnessed_get_agent_config(context: Dict[str, Any]) -> Dict[str, Any]:
|
||||||
|
"""
|
||||||
|
Get agent configuration for current user
|
||||||
|
|
||||||
|
Args:
|
||||||
|
context: Request context containing user information
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Configuration data for the current user
|
||||||
|
"""
|
||||||
|
from .core import HermesAgent
|
||||||
|
agent = HermesAgent()
|
||||||
|
user_id = agent._get_current_user_id(context)
|
||||||
|
|
||||||
|
# Query database for user configuration
|
||||||
|
sql = """
|
||||||
|
SELECT * FROM harnessed_agent_config
|
||||||
|
WHERE user_id = %(user_id)s
|
||||||
|
ORDER BY created_at DESC
|
||||||
|
LIMIT 1
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
rows = await agent.db.sql(sql, {"user_id": user_id})
|
||||||
|
if rows:
|
||||||
|
config = rows[0]
|
||||||
|
# Convert string booleans to actual booleans for UI
|
||||||
|
config["auto_cleanup_enabled"] = config["auto_cleanup_enabled"] == "1"
|
||||||
|
return {"success": True, "config": config}
|
||||||
|
else:
|
||||||
|
# Return default configuration
|
||||||
|
default_config = {
|
||||||
|
"id": f"default_{user_id}",
|
||||||
|
"user_id": user_id,
|
||||||
|
"work_dir": "./hermes_work",
|
||||||
|
"skills_path": "~/.hermes/skills",
|
||||||
|
"max_memory_tokens": 2000,
|
||||||
|
"default_priority": 50,
|
||||||
|
"high_priority_threshold": 70,
|
||||||
|
"low_priority_threshold": 30,
|
||||||
|
"auto_cleanup_enabled": True,
|
||||||
|
"min_retention_days": 30,
|
||||||
|
"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 harnessed_save_agent_config(context: Dict[str, Any], config_data: Dict[str, Any]) -> Dict[str, Any]:
|
||||||
|
"""
|
||||||
|
Save agent configuration for current user
|
||||||
|
|
||||||
|
Args:
|
||||||
|
context: Request context containing user information
|
||||||
|
config_data: Configuration data to save
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Success status
|
||||||
|
"""
|
||||||
|
from .core import HermesAgent
|
||||||
|
agent = HermesAgent()
|
||||||
|
user_id = agent._get_current_user_id(context)
|
||||||
|
|
||||||
|
# Convert boolean to string for database storage
|
||||||
|
config_data["auto_cleanup_enabled"] = "1" if config_data.get("auto_cleanup_enabled") 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_agent_config WHERE user_id = %(user_id)s"
|
||||||
|
try:
|
||||||
|
rows = await agent.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_agent_config SET
|
||||||
|
work_dir = %(work_dir)s,
|
||||||
|
skills_path = %(skills_path)s,
|
||||||
|
max_memory_tokens = %(max_memory_tokens)s,
|
||||||
|
default_priority = %(default_priority)s,
|
||||||
|
high_priority_threshold = %(high_priority_threshold)s,
|
||||||
|
low_priority_threshold = %(low_priority_threshold)s,
|
||||||
|
auto_cleanup_enabled = %(auto_cleanup_enabled)s,
|
||||||
|
min_retention_days = %(min_retention_days)s,
|
||||||
|
updated_at = %(updated_at)s
|
||||||
|
WHERE id = %(id)s
|
||||||
|
"""
|
||||||
|
await agent.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_agent_config (
|
||||||
|
id, user_id, work_dir, skills_path, max_memory_tokens,
|
||||||
|
default_priority, high_priority_threshold, low_priority_threshold,
|
||||||
|
auto_cleanup_enabled, min_retention_days, created_at, updated_at
|
||||||
|
) VALUES (
|
||||||
|
%(id)s, %(user_id)s, %(work_dir)s, %(skills_path)s, %(max_memory_tokens)s,
|
||||||
|
%(default_priority)s, %(high_priority_threshold)s, %(low_priority_threshold)s,
|
||||||
|
%(auto_cleanup_enabled)s, %(min_retention_days)s, %(created_at)s, %(updated_at)s
|
||||||
|
)
|
||||||
|
"""
|
||||||
|
await agent.db.sql(sql_insert, config_data)
|
||||||
|
|
||||||
|
return {"success": True}
|
||||||
|
except Exception as e:
|
||||||
|
return {"success": False, "error": str(e)}
|
||||||
21
json/harnessed_agent_config_view.json
Normal file
21
json/harnessed_agent_config_view.json
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
{
|
||||||
|
"tblname": "harnessed_agent_config",
|
||||||
|
"alias": "harnessed_agent_config_view",
|
||||||
|
"title": "Agent Configuration",
|
||||||
|
"params": {
|
||||||
|
"logined_userid": "user_id",
|
||||||
|
"confidential_fields": [],
|
||||||
|
"browserfields": {
|
||||||
|
"alters": {
|
||||||
|
"auto_cleanup_enabled": {
|
||||||
|
"uitype": "code",
|
||||||
|
"data": [
|
||||||
|
{"value": "1", "text": "Enabled"},
|
||||||
|
{"value": "0", "text": "Disabled"}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"editexclouded": ["id", "user_id", "created_at"]
|
||||||
|
}
|
||||||
|
}
|
||||||
104
models/harnessed_agent_config.json
Normal file
104
models/harnessed_agent_config.json
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
{
|
||||||
|
"summary": [
|
||||||
|
{
|
||||||
|
"name": "harnessed_agent_config",
|
||||||
|
"title": "Hermes Agent 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": "work_dir",
|
||||||
|
"title": "Working directory path",
|
||||||
|
"type": "str",
|
||||||
|
"length": 255,
|
||||||
|
"nullable": "no",
|
||||||
|
"default": "./hermes_work"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "skills_path",
|
||||||
|
"title": "Skills directory path",
|
||||||
|
"type": "str",
|
||||||
|
"length": 255,
|
||||||
|
"nullable": "no",
|
||||||
|
"default": "~/.hermes/skills"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "max_memory_tokens",
|
||||||
|
"title": "Maximum tokens for memory context",
|
||||||
|
"type": "int",
|
||||||
|
"nullable": "no",
|
||||||
|
"default": "2000"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "default_priority",
|
||||||
|
"title": "Default priority for new memories (0-100)",
|
||||||
|
"type": "int",
|
||||||
|
"nullable": "no",
|
||||||
|
"default": "50"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "high_priority_threshold",
|
||||||
|
"title": "Threshold for high priority memories",
|
||||||
|
"type": "int",
|
||||||
|
"nullable": "no",
|
||||||
|
"default": "70"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "low_priority_threshold",
|
||||||
|
"title": "Threshold for low priority memories",
|
||||||
|
"type": "int",
|
||||||
|
"nullable": "no",
|
||||||
|
"default": "30"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "auto_cleanup_enabled",
|
||||||
|
"title": "Enable automatic memory cleanup",
|
||||||
|
"type": "str",
|
||||||
|
"length": "1",
|
||||||
|
"nullable": "no",
|
||||||
|
"default": "1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "min_retention_days",
|
||||||
|
"title": "Minimum days to retain memories",
|
||||||
|
"type": "int",
|
||||||
|
"nullable": "no",
|
||||||
|
"default": "30"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"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_agent_config",
|
||||||
|
"idxtype": "index",
|
||||||
|
"idxfields": ["user_id"]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"codes": []
|
||||||
|
}
|
||||||
133
models/hermes_executions.json
Normal file
133
models/hermes_executions.json
Normal file
@ -0,0 +1,133 @@
|
|||||||
|
{
|
||||||
|
"summary": [
|
||||||
|
{
|
||||||
|
"name": "hermes_executions",
|
||||||
|
"title": "Task execution records with user isolation",
|
||||||
|
"primary": "id",
|
||||||
|
"catelog": "relation"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"name": "id",
|
||||||
|
"title": "Execution ID",
|
||||||
|
"type": "str",
|
||||||
|
"length": 32,
|
||||||
|
"nullable": "no",
|
||||||
|
"comments": "Unique execution identifier"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "user_id",
|
||||||
|
"title": "User ID",
|
||||||
|
"type": "str",
|
||||||
|
"length": 32,
|
||||||
|
"nullable": "no",
|
||||||
|
"comments": "User who owns this execution"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "workflow_id",
|
||||||
|
"title": "Workflow ID",
|
||||||
|
"type": "str",
|
||||||
|
"length": 32,
|
||||||
|
"nullable": "no",
|
||||||
|
"comments": "Parent workflow reference"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "task_id",
|
||||||
|
"title": "Task ID",
|
||||||
|
"type": "str",
|
||||||
|
"length": 32,
|
||||||
|
"nullable": "yes",
|
||||||
|
"comments": "Associated task reference"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "execution_status",
|
||||||
|
"title": "Execution Status",
|
||||||
|
"type": "str",
|
||||||
|
"length": 20,
|
||||||
|
"nullable": "no",
|
||||||
|
"default": "pending",
|
||||||
|
"comments": "pending, running, completed, failed, cancelled"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "start_time",
|
||||||
|
"title": "Start Time",
|
||||||
|
"type": "timestamp",
|
||||||
|
"nullable": "yes",
|
||||||
|
"comments": "Execution start timestamp"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "end_time",
|
||||||
|
"title": "End Time",
|
||||||
|
"type": "timestamp",
|
||||||
|
"nullable": "yes",
|
||||||
|
"comments": "Execution end timestamp"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "duration_seconds",
|
||||||
|
"title": "Duration Seconds",
|
||||||
|
"type": "long",
|
||||||
|
"nullable": "yes",
|
||||||
|
"comments": "Execution duration in seconds"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "result_json",
|
||||||
|
"title": "Result JSON",
|
||||||
|
"type": "text",
|
||||||
|
"nullable": "yes",
|
||||||
|
"comments": "JSON-encoded execution result"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "error_message",
|
||||||
|
"title": "Error Message",
|
||||||
|
"type": "text",
|
||||||
|
"nullable": "yes",
|
||||||
|
"comments": "Error message if execution failed"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "retry_count",
|
||||||
|
"title": "Retry Count",
|
||||||
|
"type": "long",
|
||||||
|
"nullable": "no",
|
||||||
|
"default": "0",
|
||||||
|
"comments": "Number of retries attempted"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "created_at",
|
||||||
|
"title": "Created At",
|
||||||
|
"type": "timestamp",
|
||||||
|
"nullable": "no",
|
||||||
|
"comments": "Creation timestamp"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "updated_at",
|
||||||
|
"title": "Updated At",
|
||||||
|
"type": "timestamp",
|
||||||
|
"nullable": "no",
|
||||||
|
"comments": "Last update timestamp"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"indexes": [
|
||||||
|
{
|
||||||
|
"name": "idx_hermes_executions_workflow",
|
||||||
|
"idxtype": "index",
|
||||||
|
"idxfields": ["workflow_id", "created_at"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "idx_hermes_executions_task",
|
||||||
|
"idxtype": "index",
|
||||||
|
"idxfields": ["task_id", "created_at"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "idx_hermes_executions_user",
|
||||||
|
"idxtype": "index",
|
||||||
|
"idxfields": ["user_id", "created_at"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "idx_hermes_executions_status",
|
||||||
|
"idxtype": "index",
|
||||||
|
"idxfields": ["execution_status", "created_at"]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"codes": []
|
||||||
|
}
|
||||||
147
models/hermes_tasks.json
Normal file
147
models/hermes_tasks.json
Normal file
@ -0,0 +1,147 @@
|
|||||||
|
{
|
||||||
|
"summary": [
|
||||||
|
{
|
||||||
|
"name": "hermes_tasks",
|
||||||
|
"title": "Task definitions within workflows with user isolation",
|
||||||
|
"primary": "id",
|
||||||
|
"catelog": "entity"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"name": "id",
|
||||||
|
"title": "Task ID",
|
||||||
|
"type": "str",
|
||||||
|
"length": 32,
|
||||||
|
"nullable": "no",
|
||||||
|
"comments": "Unique task identifier"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "user_id",
|
||||||
|
"title": "User ID",
|
||||||
|
"type": "str",
|
||||||
|
"length": 32,
|
||||||
|
"nullable": "no",
|
||||||
|
"comments": "User who owns this task"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "workflow_id",
|
||||||
|
"title": "Workflow ID",
|
||||||
|
"type": "str",
|
||||||
|
"length": 32,
|
||||||
|
"nullable": "no",
|
||||||
|
"comments": "Parent workflow reference"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "task_name",
|
||||||
|
"title": "Task Name",
|
||||||
|
"type": "str",
|
||||||
|
"length": 200,
|
||||||
|
"nullable": "no",
|
||||||
|
"comments": "Human-readable task name"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "task_type",
|
||||||
|
"title": "Task Type",
|
||||||
|
"type": "str",
|
||||||
|
"length": 30,
|
||||||
|
"nullable": "no",
|
||||||
|
"comments": "skill, tool, memory, session_search, custom"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "skill_name",
|
||||||
|
"title": "Skill Name",
|
||||||
|
"type": "str",
|
||||||
|
"length": 100,
|
||||||
|
"nullable": "yes",
|
||||||
|
"comments": "Skill name for skill-type tasks"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "tool_name",
|
||||||
|
"title": "Tool Name",
|
||||||
|
"type": "str",
|
||||||
|
"length": 100,
|
||||||
|
"nullable": "yes",
|
||||||
|
"comments": "Tool name for tool-type tasks"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "parameters_json",
|
||||||
|
"title": "Parameters JSON",
|
||||||
|
"type": "text",
|
||||||
|
"nullable": "yes",
|
||||||
|
"comments": "JSON-encoded task parameters"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "depends_on",
|
||||||
|
"title": "Depends On",
|
||||||
|
"type": "str",
|
||||||
|
"length": 32,
|
||||||
|
"nullable": "yes",
|
||||||
|
"comments": "Task ID this task depends on"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "parallel_group",
|
||||||
|
"title": "Parallel Group",
|
||||||
|
"type": "str",
|
||||||
|
"length": 50,
|
||||||
|
"nullable": "yes",
|
||||||
|
"comments": "Group identifier for parallel execution"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "timeout_seconds",
|
||||||
|
"title": "Timeout Seconds",
|
||||||
|
"type": "long",
|
||||||
|
"nullable": "no",
|
||||||
|
"default": "300",
|
||||||
|
"comments": "Task timeout in seconds"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "retry_count",
|
||||||
|
"title": "Retry Count",
|
||||||
|
"type": "long",
|
||||||
|
"nullable": "no",
|
||||||
|
"default": "2",
|
||||||
|
"comments": "Task retry count"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "order_index",
|
||||||
|
"title": "Order Index",
|
||||||
|
"type": "long",
|
||||||
|
"nullable": "no",
|
||||||
|
"default": "0",
|
||||||
|
"comments": "Execution order within workflow"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "created_at",
|
||||||
|
"title": "Created At",
|
||||||
|
"type": "timestamp",
|
||||||
|
"nullable": "no",
|
||||||
|
"comments": "Creation timestamp"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "updated_at",
|
||||||
|
"title": "Updated At",
|
||||||
|
"type": "timestamp",
|
||||||
|
"nullable": "no",
|
||||||
|
"comments": "Last update timestamp"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"indexes": [
|
||||||
|
{
|
||||||
|
"name": "idx_hermes_tasks_workflow",
|
||||||
|
"idxtype": "index",
|
||||||
|
"idxfields": ["workflow_id", "order_index"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "idx_hermes_tasks_user",
|
||||||
|
"idxtype": "index",
|
||||||
|
"idxfields": ["user_id", "workflow_id"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "idx_hermes_tasks_depends",
|
||||||
|
"idxtype": "index",
|
||||||
|
"idxfields": ["depends_on"]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"codes": []
|
||||||
|
}
|
||||||
112
models/hermes_workflows.json
Normal file
112
models/hermes_workflows.json
Normal file
@ -0,0 +1,112 @@
|
|||||||
|
{
|
||||||
|
"summary": [
|
||||||
|
{
|
||||||
|
"name": "hermes_workflows",
|
||||||
|
"title": "Workflow definitions with user isolation",
|
||||||
|
"primary": "id",
|
||||||
|
"catelog": "entity"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"name": "id",
|
||||||
|
"title": "Workflow ID",
|
||||||
|
"type": "str",
|
||||||
|
"length": 32,
|
||||||
|
"nullable": "no",
|
||||||
|
"comments": "Unique workflow identifier"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "user_id",
|
||||||
|
"title": "User ID",
|
||||||
|
"type": "str",
|
||||||
|
"length": 32,
|
||||||
|
"nullable": "no",
|
||||||
|
"comments": "User who owns this workflow"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "name",
|
||||||
|
"title": "Workflow Name",
|
||||||
|
"type": "str",
|
||||||
|
"length": 200,
|
||||||
|
"nullable": "no",
|
||||||
|
"comments": "Human-readable workflow name"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "description",
|
||||||
|
"title": "Description",
|
||||||
|
"type": "text",
|
||||||
|
"nullable": "yes",
|
||||||
|
"comments": "Workflow description"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "workflow_type",
|
||||||
|
"title": "Workflow Type",
|
||||||
|
"type": "str",
|
||||||
|
"length": 20,
|
||||||
|
"nullable": "no",
|
||||||
|
"default": "sequential",
|
||||||
|
"comments": "sequential, parallel, or hybrid"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "max_concurrent_tasks",
|
||||||
|
"title": "Max Concurrent Tasks",
|
||||||
|
"type": "long",
|
||||||
|
"nullable": "no",
|
||||||
|
"default": "3",
|
||||||
|
"comments": "Maximum concurrent tasks for parallel execution"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "timeout_seconds",
|
||||||
|
"title": "Timeout Seconds",
|
||||||
|
"type": "long",
|
||||||
|
"nullable": "no",
|
||||||
|
"default": "1800",
|
||||||
|
"comments": "Workflow timeout in seconds"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "retry_count",
|
||||||
|
"title": "Retry Count",
|
||||||
|
"type": "long",
|
||||||
|
"nullable": "no",
|
||||||
|
"default": "2",
|
||||||
|
"comments": "Default retry count for tasks"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "status",
|
||||||
|
"title": "Status",
|
||||||
|
"type": "str",
|
||||||
|
"length": 20,
|
||||||
|
"nullable": "no",
|
||||||
|
"default": "active",
|
||||||
|
"comments": "active, inactive, archived"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "created_at",
|
||||||
|
"title": "Created At",
|
||||||
|
"type": "timestamp",
|
||||||
|
"nullable": "no",
|
||||||
|
"comments": "Creation timestamp"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "updated_at",
|
||||||
|
"title": "Updated At",
|
||||||
|
"type": "timestamp",
|
||||||
|
"nullable": "no",
|
||||||
|
"comments": "Last update timestamp"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"indexes": [
|
||||||
|
{
|
||||||
|
"name": "idx_hermes_workflows_user",
|
||||||
|
"idxtype": "index",
|
||||||
|
"idxfields": ["user_id", "created_at"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "idx_hermes_workflows_status",
|
||||||
|
"idxtype": "index",
|
||||||
|
"idxfields": ["user_id", "status"]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"codes": []
|
||||||
|
}
|
||||||
98
models/task_dependencies.json
Normal file
98
models/task_dependencies.json
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
{
|
||||||
|
"summary": [
|
||||||
|
{
|
||||||
|
"name": "task_dependencies",
|
||||||
|
"title": "Task dependency relationships within workflows",
|
||||||
|
"primary": "id",
|
||||||
|
"catelog": "relation"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"name": "id",
|
||||||
|
"title": "Dependency ID",
|
||||||
|
"type": "str",
|
||||||
|
"length": 32,
|
||||||
|
"nullable": "no",
|
||||||
|
"comments": "Unique dependency identifier"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "user_id",
|
||||||
|
"title": "User ID",
|
||||||
|
"type": "str",
|
||||||
|
"length": 32,
|
||||||
|
"nullable": "no",
|
||||||
|
"comments": "User who owns this dependency"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "workflow_id",
|
||||||
|
"title": "Workflow ID",
|
||||||
|
"type": "str",
|
||||||
|
"length": 32,
|
||||||
|
"nullable": "no",
|
||||||
|
"comments": "Parent workflow reference"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "dependent_task_id",
|
||||||
|
"title": "Dependent Task ID",
|
||||||
|
"type": "str",
|
||||||
|
"length": 32,
|
||||||
|
"nullable": "no",
|
||||||
|
"comments": "Task that depends on another"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "dependency_task_id",
|
||||||
|
"title": "Dependency Task ID",
|
||||||
|
"type": "str",
|
||||||
|
"length": 32,
|
||||||
|
"nullable": "no",
|
||||||
|
"comments": "Task that is depended upon"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "dependency_type",
|
||||||
|
"title": "Dependency Type",
|
||||||
|
"type": "str",
|
||||||
|
"length": 20,
|
||||||
|
"nullable": "no",
|
||||||
|
"default": "completion",
|
||||||
|
"comments": "completion, success, failure, data_available"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "created_at",
|
||||||
|
"title": "Created At",
|
||||||
|
"type": "timestamp",
|
||||||
|
"nullable": "no",
|
||||||
|
"comments": "Creation timestamp"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "updated_at",
|
||||||
|
"title": "Updated At",
|
||||||
|
"type": "timestamp",
|
||||||
|
"nullable": "no",
|
||||||
|
"comments": "Last update timestamp"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"indexes": [
|
||||||
|
{
|
||||||
|
"name": "idx_task_dep_workflow",
|
||||||
|
"idxtype": "index",
|
||||||
|
"idxfields": ["workflow_id"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "idx_task_dep_dependent",
|
||||||
|
"idxtype": "index",
|
||||||
|
"idxfields": ["dependent_task_id"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "idx_task_dep_dependency",
|
||||||
|
"idxtype": "index",
|
||||||
|
"idxfields": ["dependency_task_id"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "idx_task_dep_unique",
|
||||||
|
"idxtype": "unique",
|
||||||
|
"idxfields": ["dependent_task_id", "dependency_task_id"]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"codes": []
|
||||||
|
}
|
||||||
32
wwwroot/agent_config.ui
Normal file
32
wwwroot/agent_config.ui
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
{
|
||||||
|
"widgettype": "VBox",
|
||||||
|
"options": {
|
||||||
|
"width": "100%",
|
||||||
|
"height": "100%",
|
||||||
|
"css": "ios-scroll-area"
|
||||||
|
},
|
||||||
|
"subwidgets": [
|
||||||
|
{
|
||||||
|
"widgettype": "Toolbar",
|
||||||
|
"options": {
|
||||||
|
"css": "ios-navbar",
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"text": "Configuration",
|
||||||
|
"icon": "settings",
|
||||||
|
"css": "ios-navbar-title",
|
||||||
|
"disabled": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"widgettype": "urlwidget",
|
||||||
|
"options": {
|
||||||
|
"url": "{{entire_url('harnessed_agent_config_view')}}",
|
||||||
|
"width": "100%",
|
||||||
|
"height": "100%"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
114
wwwroot/ios_design.css
Normal file
114
wwwroot/ios_design.css
Normal file
@ -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; }
|
||||||
Loading…
x
Reference in New Issue
Block a user