mirror of
https://github.com/soconnor0919/hristudio.git
synced 2025-12-11 06:34: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:
298
public/hristudio-core/plugins/control-flow.json
Normal file
298
public/hristudio-core/plugins/control-flow.json
Normal file
@@ -0,0 +1,298 @@
|
||||
{
|
||||
"blockSetId": "control-flow",
|
||||
"name": "Control Flow",
|
||||
"description": "Logic blocks for conditionals, loops, timing, and experiment flow control",
|
||||
"version": "1.0.0",
|
||||
"pluginApiVersion": "1.0",
|
||||
"hriStudioVersion": ">=0.1.0",
|
||||
"trustLevel": "official",
|
||||
"category": "control-flow",
|
||||
|
||||
"author": {
|
||||
"name": "HRIStudio Team",
|
||||
"email": "support@hristudio.com",
|
||||
"organization": "HRIStudio"
|
||||
},
|
||||
|
||||
"documentation": {
|
||||
"mainUrl": "https://docs.hristudio.org/blocks/control-flow",
|
||||
"description": "Control flow blocks manage the execution sequence of experiments. They provide timing, conditionals, loops, and logical operations to create sophisticated experimental protocols."
|
||||
},
|
||||
|
||||
"blocks": [
|
||||
{
|
||||
"id": "wait",
|
||||
"name": "wait",
|
||||
"description": "Pause execution for a specified duration",
|
||||
"category": "control",
|
||||
"shape": "action",
|
||||
"icon": "Clock",
|
||||
"color": "#f97316",
|
||||
"nestable": false,
|
||||
"parameters": [
|
||||
{
|
||||
"id": "seconds",
|
||||
"name": "Duration (s)",
|
||||
"type": "number",
|
||||
"value": 1,
|
||||
"min": 0.1,
|
||||
"max": 300,
|
||||
"step": 0.1,
|
||||
"description": "Time to wait in seconds"
|
||||
},
|
||||
{
|
||||
"id": "show_countdown",
|
||||
"name": "Show Countdown",
|
||||
"type": "boolean",
|
||||
"value": false,
|
||||
"description": "Display countdown timer to wizard"
|
||||
}
|
||||
],
|
||||
"execution": {
|
||||
"type": "delay",
|
||||
"blocking": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "repeat",
|
||||
"name": "repeat",
|
||||
"description": "Execute contained blocks multiple times",
|
||||
"category": "control",
|
||||
"shape": "control",
|
||||
"icon": "RotateCcw",
|
||||
"color": "#f97316",
|
||||
"nestable": true,
|
||||
"parameters": [
|
||||
{
|
||||
"id": "times",
|
||||
"name": "Repeat Count",
|
||||
"type": "number",
|
||||
"value": 3,
|
||||
"min": 1,
|
||||
"max": 100,
|
||||
"step": 1,
|
||||
"description": "Number of times to repeat"
|
||||
},
|
||||
{
|
||||
"id": "delay_between",
|
||||
"name": "Delay Between (s)",
|
||||
"type": "number",
|
||||
"value": 0,
|
||||
"min": 0,
|
||||
"max": 60,
|
||||
"step": 0.1,
|
||||
"description": "Optional delay between repetitions"
|
||||
}
|
||||
],
|
||||
"execution": {
|
||||
"type": "loop",
|
||||
"blocking": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "if_condition",
|
||||
"name": "if",
|
||||
"description": "Execute blocks conditionally based on a condition",
|
||||
"category": "control",
|
||||
"shape": "control",
|
||||
"icon": "GitBranch",
|
||||
"color": "#f97316",
|
||||
"nestable": true,
|
||||
"parameters": [
|
||||
{
|
||||
"id": "condition_type",
|
||||
"name": "Condition",
|
||||
"type": "select",
|
||||
"value": "participant_speaks",
|
||||
"options": [
|
||||
"participant_speaks",
|
||||
"participant_silent",
|
||||
"object_detected",
|
||||
"timer_elapsed",
|
||||
"wizard_input",
|
||||
"random_chance",
|
||||
"custom"
|
||||
],
|
||||
"description": "Type of condition to evaluate"
|
||||
},
|
||||
{
|
||||
"id": "condition_value",
|
||||
"name": "Condition Value",
|
||||
"type": "text",
|
||||
"value": "",
|
||||
"placeholder": "Enter condition details",
|
||||
"description": "Additional parameters for the condition"
|
||||
},
|
||||
{
|
||||
"id": "probability",
|
||||
"name": "Probability (%)",
|
||||
"type": "number",
|
||||
"value": 50,
|
||||
"min": 0,
|
||||
"max": 100,
|
||||
"step": 1,
|
||||
"description": "Probability for random chance condition"
|
||||
}
|
||||
],
|
||||
"execution": {
|
||||
"type": "conditional",
|
||||
"blocking": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "parallel",
|
||||
"name": "run in parallel",
|
||||
"description": "Execute multiple blocks simultaneously",
|
||||
"category": "control",
|
||||
"shape": "control",
|
||||
"icon": "Zap",
|
||||
"color": "#f97316",
|
||||
"nestable": true,
|
||||
"parameters": [
|
||||
{
|
||||
"id": "wait_for_all",
|
||||
"name": "Wait for All",
|
||||
"type": "boolean",
|
||||
"value": true,
|
||||
"description": "Wait for all parallel blocks to complete"
|
||||
},
|
||||
{
|
||||
"id": "timeout",
|
||||
"name": "Timeout (s)",
|
||||
"type": "number",
|
||||
"value": 60,
|
||||
"min": 1,
|
||||
"max": 600,
|
||||
"step": 1,
|
||||
"description": "Maximum time to wait for completion"
|
||||
}
|
||||
],
|
||||
"execution": {
|
||||
"type": "parallel",
|
||||
"blocking": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "sequence",
|
||||
"name": "sequence",
|
||||
"description": "Execute blocks in strict sequential order",
|
||||
"category": "control",
|
||||
"shape": "control",
|
||||
"icon": "List",
|
||||
"color": "#f97316",
|
||||
"nestable": true,
|
||||
"parameters": [
|
||||
{
|
||||
"id": "stop_on_error",
|
||||
"name": "Stop on Error",
|
||||
"type": "boolean",
|
||||
"value": true,
|
||||
"description": "Stop sequence if any block fails"
|
||||
},
|
||||
{
|
||||
"id": "delay_between",
|
||||
"name": "Delay Between (s)",
|
||||
"type": "number",
|
||||
"value": 0,
|
||||
"min": 0,
|
||||
"max": 10,
|
||||
"step": 0.1,
|
||||
"description": "Optional delay between blocks"
|
||||
}
|
||||
],
|
||||
"execution": {
|
||||
"type": "sequence",
|
||||
"blocking": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "random_choice",
|
||||
"name": "random choice",
|
||||
"description": "Randomly select one path from multiple options",
|
||||
"category": "control",
|
||||
"shape": "control",
|
||||
"icon": "Shuffle",
|
||||
"color": "#f97316",
|
||||
"nestable": true,
|
||||
"parameters": [
|
||||
{
|
||||
"id": "seed",
|
||||
"name": "Random Seed",
|
||||
"type": "text",
|
||||
"value": "",
|
||||
"placeholder": "Optional seed for reproducibility",
|
||||
"description": "Seed for reproducible randomization"
|
||||
},
|
||||
{
|
||||
"id": "weights",
|
||||
"name": "Weights",
|
||||
"type": "text",
|
||||
"value": "1,1",
|
||||
"placeholder": "1,1,1 (comma-separated)",
|
||||
"description": "Relative weights for each choice"
|
||||
}
|
||||
],
|
||||
"execution": {
|
||||
"type": "random_branch",
|
||||
"blocking": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "try_catch",
|
||||
"name": "try / catch",
|
||||
"description": "Execute blocks with error handling",
|
||||
"category": "control",
|
||||
"shape": "control",
|
||||
"icon": "Shield",
|
||||
"color": "#f97316",
|
||||
"nestable": true,
|
||||
"parameters": [
|
||||
{
|
||||
"id": "retry_count",
|
||||
"name": "Retry Count",
|
||||
"type": "number",
|
||||
"value": 0,
|
||||
"min": 0,
|
||||
"max": 5,
|
||||
"step": 1,
|
||||
"description": "Number of times to retry on failure"
|
||||
},
|
||||
{
|
||||
"id": "continue_on_error",
|
||||
"name": "Continue on Error",
|
||||
"type": "boolean",
|
||||
"value": false,
|
||||
"description": "Continue execution even if all retries fail"
|
||||
}
|
||||
],
|
||||
"execution": {
|
||||
"type": "error_handling",
|
||||
"blocking": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "break",
|
||||
"name": "break",
|
||||
"description": "Exit from the current loop or sequence",
|
||||
"category": "control",
|
||||
"shape": "action",
|
||||
"icon": "Square",
|
||||
"color": "#f97316",
|
||||
"nestable": false,
|
||||
"parameters": [
|
||||
{
|
||||
"id": "break_type",
|
||||
"name": "Break Type",
|
||||
"type": "select",
|
||||
"value": "loop",
|
||||
"options": ["loop", "sequence", "trial", "experiment"],
|
||||
"description": "Scope of the break operation"
|
||||
}
|
||||
],
|
||||
"execution": {
|
||||
"type": "break",
|
||||
"blocking": false
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
115
public/hristudio-core/plugins/events.json
Normal file
115
public/hristudio-core/plugins/events.json
Normal file
@@ -0,0 +1,115 @@
|
||||
{
|
||||
"blockSetId": "events",
|
||||
"name": "Event Triggers",
|
||||
"description": "Blocks that initiate and respond to experiment events",
|
||||
"version": "1.0.0",
|
||||
"pluginApiVersion": "1.0",
|
||||
"hriStudioVersion": ">=0.1.0",
|
||||
"trustLevel": "official",
|
||||
"category": "events",
|
||||
|
||||
"author": {
|
||||
"name": "HRIStudio Team",
|
||||
"email": "support@hristudio.com",
|
||||
"organization": "HRIStudio"
|
||||
},
|
||||
|
||||
"documentation": {
|
||||
"mainUrl": "https://docs.hristudio.org/blocks/events",
|
||||
"description": "Event blocks are the starting points for experiment sequences. They respond to trial states, participant actions, and system events."
|
||||
},
|
||||
|
||||
"blocks": [
|
||||
{
|
||||
"id": "when_trial_starts",
|
||||
"name": "when trial starts",
|
||||
"description": "Triggered when the trial begins execution",
|
||||
"category": "event",
|
||||
"shape": "hat",
|
||||
"icon": "Play",
|
||||
"color": "#22c55e",
|
||||
"nestable": false,
|
||||
"parameters": [],
|
||||
"execution": {
|
||||
"trigger": "trial_start",
|
||||
"blocking": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "when_participant_speaks",
|
||||
"name": "when participant speaks",
|
||||
"description": "Triggered when participant speech is detected",
|
||||
"category": "event",
|
||||
"shape": "hat",
|
||||
"icon": "Mic",
|
||||
"color": "#22c55e",
|
||||
"nestable": false,
|
||||
"parameters": [
|
||||
{
|
||||
"id": "duration_threshold",
|
||||
"name": "Min Duration (s)",
|
||||
"type": "number",
|
||||
"value": 0.5,
|
||||
"min": 0.1,
|
||||
"max": 10,
|
||||
"step": 0.1,
|
||||
"description": "Minimum speech duration to trigger event"
|
||||
}
|
||||
],
|
||||
"execution": {
|
||||
"trigger": "speech_detected",
|
||||
"blocking": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "when_timer_expires",
|
||||
"name": "when timer expires",
|
||||
"description": "Triggered after a specified time delay",
|
||||
"category": "event",
|
||||
"shape": "hat",
|
||||
"icon": "Timer",
|
||||
"color": "#22c55e",
|
||||
"nestable": false,
|
||||
"parameters": [
|
||||
{
|
||||
"id": "delay",
|
||||
"name": "Delay (s)",
|
||||
"type": "number",
|
||||
"value": 5,
|
||||
"min": 0.1,
|
||||
"max": 300,
|
||||
"step": 0.1,
|
||||
"description": "Time delay before triggering"
|
||||
}
|
||||
],
|
||||
"execution": {
|
||||
"trigger": "timer",
|
||||
"blocking": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "when_key_pressed",
|
||||
"name": "when key pressed",
|
||||
"description": "Triggered when wizard presses a specific key",
|
||||
"category": "event",
|
||||
"shape": "hat",
|
||||
"icon": "Keyboard",
|
||||
"color": "#22c55e",
|
||||
"nestable": false,
|
||||
"parameters": [
|
||||
{
|
||||
"id": "key",
|
||||
"name": "Key",
|
||||
"type": "select",
|
||||
"value": "space",
|
||||
"options": ["space", "enter", "1", "2", "3", "4", "5", "escape"],
|
||||
"description": "Key that triggers the event"
|
||||
}
|
||||
],
|
||||
"execution": {
|
||||
"trigger": "keypress",
|
||||
"blocking": false
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
51
public/hristudio-core/plugins/index.json
Normal file
51
public/hristudio-core/plugins/index.json
Normal file
@@ -0,0 +1,51 @@
|
||||
{
|
||||
"plugins": [
|
||||
{
|
||||
"id": "events",
|
||||
"name": "Event Triggers",
|
||||
"description": "Blocks that initiate and respond to experiment events",
|
||||
"version": "1.0.0",
|
||||
"category": "events",
|
||||
"file": "events.json",
|
||||
"blockCount": 4,
|
||||
"lastUpdated": "2025-02-13T00:00:00Z",
|
||||
"tags": ["events", "triggers", "trial-start", "participant-interaction"]
|
||||
},
|
||||
{
|
||||
"id": "wizard-actions",
|
||||
"name": "Wizard Actions",
|
||||
"description": "Actions performed by the human wizard during experiment execution",
|
||||
"version": "1.0.0",
|
||||
"category": "wizard-actions",
|
||||
"file": "wizard-actions.json",
|
||||
"blockCount": 6,
|
||||
"lastUpdated": "2025-02-13T00:00:00Z",
|
||||
"tags": ["wizard", "human", "speech", "gestures", "observation"]
|
||||
},
|
||||
{
|
||||
"id": "control-flow",
|
||||
"name": "Control Flow",
|
||||
"description": "Logic blocks for conditionals, loops, timing, and experiment flow control",
|
||||
"version": "1.0.0",
|
||||
"category": "control-flow",
|
||||
"file": "control-flow.json",
|
||||
"blockCount": 8,
|
||||
"lastUpdated": "2025-02-13T00:00:00Z",
|
||||
"tags": ["logic", "conditionals", "loops", "timing", "flow-control"]
|
||||
},
|
||||
{
|
||||
"id": "observation",
|
||||
"name": "Observation & Sensing",
|
||||
"description": "Data collection and behavioral observation blocks for capturing experiment metrics",
|
||||
"version": "1.0.0",
|
||||
"category": "sensors",
|
||||
"file": "observation.json",
|
||||
"blockCount": 9,
|
||||
"lastUpdated": "2025-02-13T00:00:00Z",
|
||||
"tags": ["observation", "data-collection", "sensors", "measurement", "recording"]
|
||||
}
|
||||
],
|
||||
"total": 4,
|
||||
"version": "1.0.0",
|
||||
"lastUpdated": "2025-02-13T00:00:00Z"
|
||||
}
|
||||
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
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
240
public/hristudio-core/plugins/wizard-actions.json
Normal file
240
public/hristudio-core/plugins/wizard-actions.json
Normal file
@@ -0,0 +1,240 @@
|
||||
{
|
||||
"blockSetId": "wizard-actions",
|
||||
"name": "Wizard Actions",
|
||||
"description": "Actions performed by the human wizard during experiment execution",
|
||||
"version": "1.0.0",
|
||||
"pluginApiVersion": "1.0",
|
||||
"hriStudioVersion": ">=0.1.0",
|
||||
"trustLevel": "official",
|
||||
"category": "wizard-actions",
|
||||
|
||||
"author": {
|
||||
"name": "HRIStudio Team",
|
||||
"email": "support@hristudio.com",
|
||||
"organization": "HRIStudio"
|
||||
},
|
||||
|
||||
"documentation": {
|
||||
"mainUrl": "https://docs.hristudio.org/blocks/wizard-actions",
|
||||
"description": "Wizard action blocks define behaviors that the human experimenter performs during trials. These create prompts and interfaces for the wizard to follow the experimental protocol."
|
||||
},
|
||||
|
||||
"blocks": [
|
||||
{
|
||||
"id": "wizard_say",
|
||||
"name": "say",
|
||||
"description": "Wizard speaks to the participant",
|
||||
"category": "wizard",
|
||||
"shape": "action",
|
||||
"icon": "MessageSquare",
|
||||
"color": "#a855f7",
|
||||
"nestable": false,
|
||||
"parameters": [
|
||||
{
|
||||
"id": "message",
|
||||
"name": "Message",
|
||||
"type": "text",
|
||||
"value": "",
|
||||
"placeholder": "What should the wizard say?",
|
||||
"description": "Text that the wizard will speak to the participant"
|
||||
},
|
||||
{
|
||||
"id": "tone",
|
||||
"name": "Tone",
|
||||
"type": "select",
|
||||
"value": "neutral",
|
||||
"options": ["neutral", "friendly", "encouraging", "instructional", "questioning"],
|
||||
"description": "Suggested tone for delivery"
|
||||
}
|
||||
],
|
||||
"execution": {
|
||||
"type": "wizard_prompt",
|
||||
"blocking": true,
|
||||
"timeout": 30000
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "wizard_gesture",
|
||||
"name": "gesture",
|
||||
"description": "Wizard performs a physical gesture",
|
||||
"category": "wizard",
|
||||
"shape": "action",
|
||||
"icon": "Hand",
|
||||
"color": "#a855f7",
|
||||
"nestable": false,
|
||||
"parameters": [
|
||||
{
|
||||
"id": "type",
|
||||
"name": "Gesture",
|
||||
"type": "select",
|
||||
"value": "wave",
|
||||
"options": ["wave", "point", "nod", "thumbs_up", "beckon", "stop_hand", "applaud"],
|
||||
"description": "Type of gesture to perform"
|
||||
},
|
||||
{
|
||||
"id": "direction",
|
||||
"name": "Direction",
|
||||
"type": "select",
|
||||
"value": "forward",
|
||||
"options": ["forward", "left", "right", "up", "down", "participant", "robot"],
|
||||
"description": "Direction or target of the gesture"
|
||||
}
|
||||
],
|
||||
"execution": {
|
||||
"type": "wizard_prompt",
|
||||
"blocking": true,
|
||||
"timeout": 15000
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "wizard_show_object",
|
||||
"name": "show object",
|
||||
"description": "Wizard presents or demonstrates an object",
|
||||
"category": "wizard",
|
||||
"shape": "action",
|
||||
"icon": "Package",
|
||||
"color": "#a855f7",
|
||||
"nestable": false,
|
||||
"parameters": [
|
||||
{
|
||||
"id": "object",
|
||||
"name": "Object",
|
||||
"type": "text",
|
||||
"value": "",
|
||||
"placeholder": "Name of object to show",
|
||||
"description": "Description of the object to present"
|
||||
},
|
||||
{
|
||||
"id": "action",
|
||||
"name": "Action",
|
||||
"type": "select",
|
||||
"value": "hold_up",
|
||||
"options": ["hold_up", "demonstrate", "point_to", "place_on_table", "hand_to_participant"],
|
||||
"description": "How to present the object"
|
||||
}
|
||||
],
|
||||
"execution": {
|
||||
"type": "wizard_prompt",
|
||||
"blocking": true,
|
||||
"timeout": 20000
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "wizard_record_note",
|
||||
"name": "record note",
|
||||
"description": "Wizard records an observation or note",
|
||||
"category": "wizard",
|
||||
"shape": "action",
|
||||
"icon": "PenTool",
|
||||
"color": "#a855f7",
|
||||
"nestable": false,
|
||||
"parameters": [
|
||||
{
|
||||
"id": "note_type",
|
||||
"name": "Note Type",
|
||||
"type": "select",
|
||||
"value": "observation",
|
||||
"options": ["observation", "participant_response", "technical_issue", "protocol_deviation", "other"],
|
||||
"description": "Category of note being recorded"
|
||||
},
|
||||
{
|
||||
"id": "prompt",
|
||||
"name": "Prompt",
|
||||
"type": "text",
|
||||
"value": "",
|
||||
"placeholder": "What should the wizard note?",
|
||||
"description": "Guidance for what to observe or record"
|
||||
}
|
||||
],
|
||||
"execution": {
|
||||
"type": "wizard_prompt",
|
||||
"blocking": true,
|
||||
"timeout": 60000
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "wizard_wait_for_response",
|
||||
"name": "wait for response",
|
||||
"description": "Wizard waits for participant to respond",
|
||||
"category": "wizard",
|
||||
"shape": "action",
|
||||
"icon": "Clock",
|
||||
"color": "#a855f7",
|
||||
"nestable": false,
|
||||
"parameters": [
|
||||
{
|
||||
"id": "response_type",
|
||||
"name": "Response Type",
|
||||
"type": "select",
|
||||
"value": "verbal",
|
||||
"options": ["verbal", "gesture", "action", "button_press", "any"],
|
||||
"description": "Type of response to wait for"
|
||||
},
|
||||
{
|
||||
"id": "timeout",
|
||||
"name": "Timeout (s)",
|
||||
"type": "number",
|
||||
"value": 30,
|
||||
"min": 1,
|
||||
"max": 300,
|
||||
"step": 1,
|
||||
"description": "Maximum time to wait for response"
|
||||
},
|
||||
{
|
||||
"id": "prompt_text",
|
||||
"name": "Prompt",
|
||||
"type": "text",
|
||||
"value": "",
|
||||
"placeholder": "Optional prompt for participant",
|
||||
"description": "Text to display to guide participant response"
|
||||
}
|
||||
],
|
||||
"execution": {
|
||||
"type": "wizard_prompt",
|
||||
"blocking": true,
|
||||
"timeout": 300000
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "wizard_rate_interaction",
|
||||
"name": "rate interaction",
|
||||
"description": "Wizard provides a subjective rating",
|
||||
"category": "wizard",
|
||||
"shape": "action",
|
||||
"icon": "Star",
|
||||
"color": "#a855f7",
|
||||
"nestable": false,
|
||||
"parameters": [
|
||||
{
|
||||
"id": "rating_type",
|
||||
"name": "Rating Type",
|
||||
"type": "select",
|
||||
"value": "engagement",
|
||||
"options": ["engagement", "comprehension", "comfort", "success", "naturalness", "custom"],
|
||||
"description": "Aspect being rated"
|
||||
},
|
||||
{
|
||||
"id": "scale",
|
||||
"name": "Scale",
|
||||
"type": "select",
|
||||
"value": "1-5",
|
||||
"options": ["1-5", "1-7", "1-10", "0-100"],
|
||||
"description": "Rating scale to use"
|
||||
},
|
||||
{
|
||||
"id": "custom_label",
|
||||
"name": "Custom Label",
|
||||
"type": "text",
|
||||
"value": "",
|
||||
"placeholder": "Label for custom rating type",
|
||||
"description": "Description for custom rating (if selected)"
|
||||
}
|
||||
],
|
||||
"execution": {
|
||||
"type": "wizard_prompt",
|
||||
"blocking": true,
|
||||
"timeout": 30000
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
66
public/hristudio-core/repository.json
Normal file
66
public/hristudio-core/repository.json
Normal file
@@ -0,0 +1,66 @@
|
||||
{
|
||||
"id": "hristudio-core",
|
||||
"name": "HRIStudio Core Blocks",
|
||||
"description": "Essential system blocks for experiment design including control flow, wizard actions, and basic functionality",
|
||||
"urls": {
|
||||
"git": "https://github.com/soconnor0919/hristudio-core",
|
||||
"repository": "https://core.hristudio.com"
|
||||
},
|
||||
"official": true,
|
||||
"trust": "official",
|
||||
"apiVersion": "1.0",
|
||||
"pluginApiVersion": "1.0",
|
||||
"author": {
|
||||
"name": "HRIStudio Team",
|
||||
"email": "support@hristudio.com",
|
||||
"url": "https://hristudio.com",
|
||||
"organization": "HRIStudio"
|
||||
},
|
||||
"maintainers": [
|
||||
{
|
||||
"name": "Sean O'Connor",
|
||||
"url": "https://github.com/soconnor0919"
|
||||
}
|
||||
],
|
||||
"homepage": "https://hristudio.org/core",
|
||||
"license": "MIT",
|
||||
"defaultBranch": "main",
|
||||
"lastUpdated": "2025-02-13T00:00:00Z",
|
||||
"categories": [
|
||||
{
|
||||
"id": "events",
|
||||
"name": "Event Triggers",
|
||||
"description": "Blocks that initiate experiment sequences"
|
||||
},
|
||||
{
|
||||
"id": "wizard-actions",
|
||||
"name": "Wizard Actions",
|
||||
"description": "Actions performed by the human wizard"
|
||||
},
|
||||
{
|
||||
"id": "control-flow",
|
||||
"name": "Control Flow",
|
||||
"description": "Logic blocks for conditionals, loops, and timing"
|
||||
},
|
||||
{
|
||||
"id": "sensors",
|
||||
"name": "Observation & Sensing",
|
||||
"description": "Data collection and behavioral observation blocks"
|
||||
}
|
||||
],
|
||||
"compatibility": {
|
||||
"hristudio": {
|
||||
"min": "0.1.0",
|
||||
"recommended": "0.1.0"
|
||||
}
|
||||
},
|
||||
"assets": {
|
||||
"icon": "assets/core-icon.png",
|
||||
"logo": "assets/core-logo.png",
|
||||
"banner": "assets/core-banner.png"
|
||||
},
|
||||
"tags": ["official", "core", "essential", "wizard-of-oz"],
|
||||
"stats": {
|
||||
"plugins": 4
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user