mirror of
https://github.com/soconnor0919/hristudio.git
synced 2025-12-11 14:44:44 -05:00
feat: implement complete plugin store repository synchronization system
• Fix repository sync implementation in admin API (was TODO placeholder) - Add full fetch/parse logic for repository.json and plugin index - Implement robot matching by name/manufacturer patterns - Handle plugin creation/updates with proper error handling - Add comprehensive TypeScript typing throughout • Fix plugin store installation state detection - Add getStudyPlugins API integration to check installed plugins - Update PluginCard component with isInstalled prop and correct button states - Fix repository name display using metadata.repositoryId mapping - Show "Installed" (disabled) vs "Install" (enabled) based on actual state • Resolve admin access and authentication issues - Add missing administrator role to user system roles table - Fix admin route access for repository management - Enable repository sync functionality in admin dashboard • Add repository metadata integration - Update plugin records with proper repositoryId references - Add metadata field to robots.plugins.list API response - Enable repository name display for all plugins from metadata • Fix TypeScript compliance across plugin system - Replace unsafe 'any' types with proper interfaces - Add type definitions for repository and plugin data structures - Use nullish coalescing operators for safer null handling - Remove unnecessary type assertions • Integrate live repository at https://repo.hristudio.com - Successfully loads 3 robot plugins (TurtleBot3 Burger/Waffle, NAO) - Complete ROS2 action definitions with parameter schemas - Trust level categorization (official, verified, community) - Platform and documentation metadata preservation • Update documentation and development workflow - Document plugin repository system in work_in_progress.md - Update quick-reference.md with repository sync examples - Add plugin installation and management guidance - Remove problematic test script with TypeScript errors BREAKING CHANGE: Plugin store now requires repository sync for robot plugins. Run repository sync in admin dashboard after deployment to populate plugin store. Closes: Plugin store repository integration Resolves: Installation state detection and repository name display Fixes: Admin authentication and TypeScript compliance issues
This commit is contained in:
477
public/hristudio-core/plugins/observation.json
Normal file
477
public/hristudio-core/plugins/observation.json
Normal file
@@ -0,0 +1,477 @@
|
||||
{
|
||||
"blockSetId": "observation",
|
||||
"name": "Observation & Sensing",
|
||||
"description": "Data collection and behavioral observation blocks for capturing experiment metrics",
|
||||
"version": "1.0.0",
|
||||
"pluginApiVersion": "1.0",
|
||||
"hriStudioVersion": ">=0.1.0",
|
||||
"trustLevel": "official",
|
||||
"category": "sensors",
|
||||
|
||||
"author": {
|
||||
"name": "HRIStudio Team",
|
||||
"email": "support@hristudio.com",
|
||||
"organization": "HRIStudio"
|
||||
},
|
||||
|
||||
"documentation": {
|
||||
"mainUrl": "https://docs.hristudio.org/blocks/observation",
|
||||
"description": "Observation blocks enable systematic data collection during experiments. They capture behavioral observations, sensor readings, and interaction metrics for later analysis."
|
||||
},
|
||||
|
||||
"blocks": [
|
||||
{
|
||||
"id": "observe_behavior",
|
||||
"name": "observe behavior",
|
||||
"description": "Record behavioral observations during the trial",
|
||||
"category": "sensor",
|
||||
"shape": "action",
|
||||
"icon": "Eye",
|
||||
"color": "#16a34a",
|
||||
"nestable": false,
|
||||
"parameters": [
|
||||
{
|
||||
"id": "behavior_type",
|
||||
"name": "Behavior Type",
|
||||
"type": "select",
|
||||
"value": "engagement",
|
||||
"options": [
|
||||
"engagement",
|
||||
"attention",
|
||||
"confusion",
|
||||
"comfort",
|
||||
"compliance",
|
||||
"interaction_quality",
|
||||
"task_performance",
|
||||
"emotional_state",
|
||||
"custom"
|
||||
],
|
||||
"description": "Category of behavior being observed"
|
||||
},
|
||||
{
|
||||
"id": "custom_behavior",
|
||||
"name": "Custom Behavior",
|
||||
"type": "text",
|
||||
"value": "",
|
||||
"placeholder": "Describe custom behavior",
|
||||
"description": "Description for custom behavior type"
|
||||
},
|
||||
{
|
||||
"id": "duration",
|
||||
"name": "Observation Duration (s)",
|
||||
"type": "number",
|
||||
"value": 5,
|
||||
"min": 1,
|
||||
"max": 300,
|
||||
"step": 1,
|
||||
"description": "How long to observe the behavior"
|
||||
},
|
||||
{
|
||||
"id": "rating_scale",
|
||||
"name": "Rating Scale",
|
||||
"type": "select",
|
||||
"value": "1-5",
|
||||
"options": ["1-3", "1-5", "1-7", "1-10", "0-100", "boolean", "notes_only"],
|
||||
"description": "Scale for quantifying the observation"
|
||||
}
|
||||
],
|
||||
"execution": {
|
||||
"type": "observation",
|
||||
"blocking": true,
|
||||
"data_capture": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "measure_response_time",
|
||||
"name": "measure response time",
|
||||
"description": "Measure time between stimulus and participant response",
|
||||
"category": "sensor",
|
||||
"shape": "action",
|
||||
"icon": "Stopwatch",
|
||||
"color": "#16a34a",
|
||||
"nestable": false,
|
||||
"parameters": [
|
||||
{
|
||||
"id": "stimulus_type",
|
||||
"name": "Stimulus",
|
||||
"type": "select",
|
||||
"value": "robot_action",
|
||||
"options": [
|
||||
"robot_action",
|
||||
"wizard_speech",
|
||||
"visual_cue",
|
||||
"audio_cue",
|
||||
"touch",
|
||||
"custom"
|
||||
],
|
||||
"description": "Type of stimulus that starts the timer"
|
||||
},
|
||||
{
|
||||
"id": "response_type",
|
||||
"name": "Response Type",
|
||||
"type": "select",
|
||||
"value": "verbal",
|
||||
"options": [
|
||||
"verbal",
|
||||
"gesture",
|
||||
"movement",
|
||||
"button_press",
|
||||
"eye_contact",
|
||||
"any_action",
|
||||
"custom"
|
||||
],
|
||||
"description": "Type of response that stops the timer"
|
||||
},
|
||||
{
|
||||
"id": "timeout",
|
||||
"name": "Timeout (s)",
|
||||
"type": "number",
|
||||
"value": 30,
|
||||
"min": 1,
|
||||
"max": 300,
|
||||
"step": 1,
|
||||
"description": "Maximum time to wait for response"
|
||||
}
|
||||
],
|
||||
"execution": {
|
||||
"type": "timing_measurement",
|
||||
"blocking": true,
|
||||
"data_capture": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "count_events",
|
||||
"name": "count events",
|
||||
"description": "Count occurrences of specific events or behaviors",
|
||||
"category": "sensor",
|
||||
"shape": "action",
|
||||
"icon": "Hash",
|
||||
"color": "#16a34a",
|
||||
"nestable": false,
|
||||
"parameters": [
|
||||
{
|
||||
"id": "event_type",
|
||||
"name": "Event Type",
|
||||
"type": "select",
|
||||
"value": "verbal_utterances",
|
||||
"options": [
|
||||
"verbal_utterances",
|
||||
"gestures",
|
||||
"eye_contact",
|
||||
"interruptions",
|
||||
"questions_asked",
|
||||
"task_attempts",
|
||||
"errors",
|
||||
"custom"
|
||||
],
|
||||
"description": "Type of event to count"
|
||||
},
|
||||
{
|
||||
"id": "custom_event",
|
||||
"name": "Custom Event",
|
||||
"type": "text",
|
||||
"value": "",
|
||||
"placeholder": "Describe custom event",
|
||||
"description": "Description for custom event type"
|
||||
},
|
||||
{
|
||||
"id": "counting_period",
|
||||
"name": "Counting Period (s)",
|
||||
"type": "number",
|
||||
"value": 60,
|
||||
"min": 5,
|
||||
"max": 600,
|
||||
"step": 5,
|
||||
"description": "Duration to count events"
|
||||
},
|
||||
{
|
||||
"id": "auto_detect",
|
||||
"name": "Auto Detection",
|
||||
"type": "boolean",
|
||||
"value": false,
|
||||
"description": "Attempt automatic detection (if supported)"
|
||||
}
|
||||
],
|
||||
"execution": {
|
||||
"type": "event_counting",
|
||||
"blocking": true,
|
||||
"data_capture": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "record_audio",
|
||||
"name": "record audio",
|
||||
"description": "Capture audio recording during interaction",
|
||||
"category": "sensor",
|
||||
"shape": "action",
|
||||
"icon": "Mic",
|
||||
"color": "#16a34a",
|
||||
"nestable": false,
|
||||
"parameters": [
|
||||
{
|
||||
"id": "duration",
|
||||
"name": "Duration (s)",
|
||||
"type": "number",
|
||||
"value": 30,
|
||||
"min": 1,
|
||||
"max": 600,
|
||||
"step": 1,
|
||||
"description": "Length of audio recording"
|
||||
},
|
||||
{
|
||||
"id": "quality",
|
||||
"name": "Quality",
|
||||
"type": "select",
|
||||
"value": "standard",
|
||||
"options": ["low", "standard", "high", "lossless"],
|
||||
"description": "Audio recording quality"
|
||||
},
|
||||
{
|
||||
"id": "channels",
|
||||
"name": "Channels",
|
||||
"type": "select",
|
||||
"value": "mono",
|
||||
"options": ["mono", "stereo", "multi"],
|
||||
"description": "Audio channel configuration"
|
||||
},
|
||||
{
|
||||
"id": "auto_transcribe",
|
||||
"name": "Auto Transcribe",
|
||||
"type": "boolean",
|
||||
"value": false,
|
||||
"description": "Automatically transcribe speech to text"
|
||||
}
|
||||
],
|
||||
"execution": {
|
||||
"type": "audio_recording",
|
||||
"blocking": true,
|
||||
"data_capture": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "capture_video",
|
||||
"name": "capture video",
|
||||
"description": "Record video of the interaction",
|
||||
"category": "sensor",
|
||||
"shape": "action",
|
||||
"icon": "Video",
|
||||
"color": "#16a34a",
|
||||
"nestable": false,
|
||||
"parameters": [
|
||||
{
|
||||
"id": "duration",
|
||||
"name": "Duration (s)",
|
||||
"type": "number",
|
||||
"value": 30,
|
||||
"min": 1,
|
||||
"max": 600,
|
||||
"step": 1,
|
||||
"description": "Length of video recording"
|
||||
},
|
||||
{
|
||||
"id": "camera",
|
||||
"name": "Camera",
|
||||
"type": "select",
|
||||
"value": "primary",
|
||||
"options": ["primary", "secondary", "overhead", "robot_pov", "all"],
|
||||
"description": "Which camera(s) to use"
|
||||
},
|
||||
{
|
||||
"id": "resolution",
|
||||
"name": "Resolution",
|
||||
"type": "select",
|
||||
"value": "720p",
|
||||
"options": ["480p", "720p", "1080p", "4K"],
|
||||
"description": "Video resolution"
|
||||
},
|
||||
{
|
||||
"id": "framerate",
|
||||
"name": "Frame Rate",
|
||||
"type": "select",
|
||||
"value": "30fps",
|
||||
"options": ["15fps", "30fps", "60fps", "120fps"],
|
||||
"description": "Video frame rate"
|
||||
}
|
||||
],
|
||||
"execution": {
|
||||
"type": "video_recording",
|
||||
"blocking": true,
|
||||
"data_capture": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "log_event",
|
||||
"name": "log event",
|
||||
"description": "Record a timestamped event in the trial log",
|
||||
"category": "sensor",
|
||||
"shape": "action",
|
||||
"icon": "FileText",
|
||||
"color": "#16a34a",
|
||||
"nestable": false,
|
||||
"parameters": [
|
||||
{
|
||||
"id": "event_name",
|
||||
"name": "Event Name",
|
||||
"type": "text",
|
||||
"value": "",
|
||||
"placeholder": "Name of the event",
|
||||
"description": "Short identifier for the event"
|
||||
},
|
||||
{
|
||||
"id": "event_data",
|
||||
"name": "Event Data",
|
||||
"type": "text",
|
||||
"value": "",
|
||||
"placeholder": "Additional data or notes",
|
||||
"description": "Optional additional information"
|
||||
},
|
||||
{
|
||||
"id": "severity",
|
||||
"name": "Severity",
|
||||
"type": "select",
|
||||
"value": "info",
|
||||
"options": ["debug", "info", "warning", "error", "critical"],
|
||||
"description": "Importance level of the event"
|
||||
},
|
||||
{
|
||||
"id": "category",
|
||||
"name": "Category",
|
||||
"type": "select",
|
||||
"value": "experiment",
|
||||
"options": [
|
||||
"experiment",
|
||||
"participant",
|
||||
"robot",
|
||||
"wizard",
|
||||
"technical",
|
||||
"protocol",
|
||||
"custom"
|
||||
],
|
||||
"description": "Category for organizing events"
|
||||
}
|
||||
],
|
||||
"execution": {
|
||||
"type": "event_logging",
|
||||
"blocking": false,
|
||||
"data_capture": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "survey_question",
|
||||
"name": "survey question",
|
||||
"description": "Present a survey question to the participant",
|
||||
"category": "sensor",
|
||||
"shape": "action",
|
||||
"icon": "HelpCircle",
|
||||
"color": "#16a34a",
|
||||
"nestable": false,
|
||||
"parameters": [
|
||||
{
|
||||
"id": "question",
|
||||
"name": "Question",
|
||||
"type": "text",
|
||||
"value": "",
|
||||
"placeholder": "Enter your question",
|
||||
"description": "The question to ask the participant"
|
||||
},
|
||||
{
|
||||
"id": "response_type",
|
||||
"name": "Response Type",
|
||||
"type": "select",
|
||||
"value": "likert_5",
|
||||
"options": [
|
||||
"likert_5",
|
||||
"likert_7",
|
||||
"yes_no",
|
||||
"multiple_choice",
|
||||
"text_input",
|
||||
"numeric",
|
||||
"slider"
|
||||
],
|
||||
"description": "Type of response interface"
|
||||
},
|
||||
{
|
||||
"id": "options",
|
||||
"name": "Options",
|
||||
"type": "text",
|
||||
"value": "",
|
||||
"placeholder": "Option1,Option2,Option3",
|
||||
"description": "Comma-separated options for multiple choice"
|
||||
},
|
||||
{
|
||||
"id": "required",
|
||||
"name": "Required",
|
||||
"type": "boolean",
|
||||
"value": true,
|
||||
"description": "Whether a response is required to continue"
|
||||
}
|
||||
],
|
||||
"execution": {
|
||||
"type": "survey_question",
|
||||
"blocking": true,
|
||||
"data_capture": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "physiological_measure",
|
||||
"name": "physiological measure",
|
||||
"description": "Capture physiological data from connected sensors",
|
||||
"category": "sensor",
|
||||
"shape": "action",
|
||||
"icon": "Activity",
|
||||
"color": "#16a34a",
|
||||
"nestable": false,
|
||||
"parameters": [
|
||||
{
|
||||
"id": "measure_type",
|
||||
"name": "Measure Type",
|
||||
"type": "select",
|
||||
"value": "heart_rate",
|
||||
"options": [
|
||||
"heart_rate",
|
||||
"skin_conductance",
|
||||
"eye_tracking",
|
||||
"eeg",
|
||||
"emg",
|
||||
"blood_pressure",
|
||||
"temperature",
|
||||
"custom"
|
||||
],
|
||||
"description": "Type of physiological measurement"
|
||||
},
|
||||
{
|
||||
"id": "duration",
|
||||
"name": "Measurement Duration (s)",
|
||||
"type": "number",
|
||||
"value": 10,
|
||||
"min": 1,
|
||||
"max": 300,
|
||||
"step": 1,
|
||||
"description": "How long to collect data"
|
||||
},
|
||||
{
|
||||
"id": "sampling_rate",
|
||||
"name": "Sampling Rate (Hz)",
|
||||
"type": "number",
|
||||
"value": 100,
|
||||
"min": 1,
|
||||
"max": 1000,
|
||||
"step": 1,
|
||||
"description": "Data collection frequency"
|
||||
},
|
||||
{
|
||||
"id": "baseline",
|
||||
"name": "Baseline Measurement",
|
||||
"type": "boolean",
|
||||
"value": false,
|
||||
"description": "Mark this as a baseline measurement"
|
||||
}
|
||||
],
|
||||
"execution": {
|
||||
"type": "physiological_data",
|
||||
"blocking": true,
|
||||
"data_capture": true
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user