Browse Source

fix(install): resolve custom install failures and missing agent-metadata (#237, #277)

Fix custom install mode breaking all components by mapping plural category
names to singular types. Add agent-metadata.json to registry config section
and all profiles. Clean up registry data quality issues including duplicate
context IDs, description artifacts, and schema inconsistencies.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
darrenhinde 4 months ago
parent
commit
d17eb13f33
2 changed files with 79 additions and 52 deletions
  1. 36 19
      install.sh
  2. 43 33
      registry.json

+ 36 - 19
install.sh

@@ -297,13 +297,20 @@ get_profile_components() {
 get_component_info() {
     local component_id=$1
     local component_type=$2
-    
+    local registry_key
+    registry_key=$(get_registry_key "$component_type")
+
     if [ "$component_type" = "context" ] && [[ "$component_id" == */* ]]; then
-        jq_exec "first(.components.contexts[]? | select(.path == \".opencode/context/${component_id}.md\"))" "$TEMP_DIR/registry.json"
+        local result
+        result=$(jq_exec "first(.components.contexts[]? | select(.path == \".opencode/context/${component_id}.md\"))" "$TEMP_DIR/registry.json")
+        if [ -z "$result" ] || [ "$result" = "null" ]; then
+            result=$(jq_exec "first(.components.contexts[]? | select(.path == \".opencode/context/${component_id}\"))" "$TEMP_DIR/registry.json")
+        fi
+        echo "$result"
         return
     fi
 
-    jq_exec ".components.${component_type}[]? | select(.id == \"${component_id}\" or (.aliases // [] | index(\"${component_id}\")))" "$TEMP_DIR/registry.json"
+    jq_exec ".components.${registry_key}[]? | select(.id == \"${component_id}\" or (.aliases // [] | index(\"${component_id}\")))" "$TEMP_DIR/registry.json"
 }
 
 resolve_component_path() {
@@ -554,9 +561,7 @@ show_install_location_menu() {
             fi
             
             local normalized_path
-            normalized_path=$(normalize_and_validate_path "$custom_path")
-            
-            if ! normalize_and_validate_path "$custom_path" > /dev/null; then
+            if ! normalized_path=$(normalize_and_validate_path "$custom_path"); then
                 print_error "Invalid path"
                 sleep 2
                 show_install_location_menu
@@ -753,6 +758,9 @@ show_custom_menu() {
     read -r -p "Enter category numbers (space-separated) or option: " -a selections
     
     for sel in "${selections[@]}"; do
+        if [[ ! "$sel" =~ ^[0-9]+$ ]]; then
+            continue
+        fi
         if [ "$sel" -eq $((${#categories[@]}+1)) ]; then
             selected_categories=("${categories[@]}")
             break
@@ -804,7 +812,19 @@ show_component_selection() {
             echo "  ${idx}) ${comp_name}"
             echo "     ${comp_desc}"
             
-            all_components+=("${category}:${comp_id}")
+            local singular_type
+            case "$category" in
+                agents)    singular_type="agent" ;;
+                subagents) singular_type="subagent" ;;
+                commands)  singular_type="command" ;;
+                tools)     singular_type="tool" ;;
+                plugins)   singular_type="plugin" ;;
+                skills)    singular_type="skill" ;;
+                contexts)  singular_type="context" ;;
+                config)    singular_type="config" ;;
+                *)         singular_type="${category%s}" ;;
+            esac
+            all_components+=("${singular_type}:${comp_id}")
             component_details+=("${comp_name}|${comp_desc}")
             
             idx=$((idx+1))
@@ -822,7 +842,7 @@ show_component_selection() {
             break
         elif [ "$sel" = "done" ]; then
             break
-        elif [ "$sel" -ge 1 ] && [ "$sel" -le ${#all_components[@]} ]; then
+        elif [[ "$sel" =~ ^[0-9]+$ ]] && [ "$sel" -ge 1 ] && [ "$sel" -le ${#all_components[@]} ]; then
             SELECTED_COMPONENTS+=("${all_components[$((sel-1))]}")
         fi
     done
@@ -1023,11 +1043,9 @@ perform_installation() {
     for comp in "${SELECTED_COMPONENTS[@]}"; do
         local type="${comp%%:*}"
         local id="${comp##*:}"
-        local registry_key
-        registry_key=$(get_registry_key "$type")
         local path
         path=$(resolve_component_path "$type" "$id")
-        
+
         if [ -n "$path" ] && [ "$path" != "null" ]; then
             local install_path
             install_path=$(get_install_path "$path")
@@ -1097,13 +1115,13 @@ perform_installation() {
         local type="${comp%%:*}"
         local id="${comp##*:}"
         
-        # Get the correct registry key (handles singular/plural)
-        local registry_key
-        registry_key=$(get_registry_key "$type")
-        
-        # Get component path
+        # Get component path (registry key resolved internally)
         local path
         path=$(resolve_component_path "$type" "$id")
+
+        # Registry key needed for multi-file (skills) lookup
+        local registry_key
+        registry_key=$(get_registry_key "$type")
         
         if [ -z "$path" ] || [ "$path" = "null" ]; then
             print_warning "Could not find path for ${comp}"
@@ -1288,7 +1306,7 @@ list_components() {
     
     echo -e "${BOLD}Available Components${NC}\n"
     
-    local categories=("agents" "subagents" "commands" "tools" "plugins" "skills" "contexts")
+    local categories=("agents" "subagents" "commands" "tools" "plugins" "skills" "contexts" "config")
     
     for category in "${categories[@]}"; do
         local cat_display
@@ -1443,8 +1461,7 @@ main() {
     # Apply custom install directory if specified (CLI arg overrides env var)
     if [ -n "$CUSTOM_INSTALL_DIR" ]; then
         local normalized_path
-        if normalize_and_validate_path "$CUSTOM_INSTALL_DIR" > /dev/null; then
-            normalized_path=$(normalize_and_validate_path "$CUSTOM_INSTALL_DIR")
+        if normalized_path=$(normalize_and_validate_path "$CUSTOM_INSTALL_DIR"); then
             INSTALL_DIR="$normalized_path"
             if ! validate_install_path "$INSTALL_DIR"; then
                 print_warning "Installation path may have issues, but continuing..."

+ 43 - 33
registry.json

@@ -579,7 +579,7 @@
         "name": "Test New Command",
         "type": "command",
         "path": ".opencode/command/test-new-command.md",
-        "description": "Test command to verify auto-detection and registry updates work correctly\\\"",
+        "description": "Test command to verify auto-detection and registry updates work correctly",
         "tags": [],
         "dependencies": [],
         "category": "standard"
@@ -589,7 +589,7 @@
         "name": "Commit OpenAgents Control",
         "type": "command",
         "path": ".opencode/command/commit-openagents.md",
-        "description": "description: Smart commit command for opencode-agents repository with automatic validation and conventional commits",
+        "description": "Smart commit command for opencode-agents repository with automatic validation and conventional commits",
         "tags": [],
         "dependencies": [],
         "category": "standard"
@@ -599,7 +599,7 @@
         "name": "Prompt Optimizer",
         "type": "command",
         "path": ".opencode/command/prompt-engineering/prompt-optimizer.md",
-        "description": "Advanced prompt optimizer: Research patterns + token efficiency + semantic preservation. Achieves 30-50% token reduction with 100% meaning preserved.\\\"",
+        "description": "Advanced prompt optimizer: Research patterns + token efficiency + semantic preservation. Achieves 30-50% token reduction with 100% meaning preserved.",
         "tags": [],
         "dependencies": [],
         "category": "standard"
@@ -609,7 +609,7 @@
         "name": "Create Tests",
         "type": "command",
         "path": ".opencode/command/openagents/new-agents/create-tests.md",
-        "description": "description: \\\"Generate comprehensive test suites for OpenCode agents with 8 essential test types\\\"",
+        "description": "Generate comprehensive test suites for OpenCode agents with 8 essential test types",
         "tags": [],
         "dependencies": [],
         "category": "standard"
@@ -619,7 +619,7 @@
         "name": "Create Agent",
         "type": "command",
         "path": ".opencode/command/openagents/new-agents/create-agent.md",
-        "description": "description: \\\"Create new OpenCode agents following research-backed best practices (Anthropic 2025)\\\"",
+        "description": "Create new OpenCode agents following research-backed best practices (Anthropic 2025)",
         "tags": [],
         "dependencies": [],
         "category": "standard"
@@ -650,6 +650,7 @@
           "patterns",
           "refactoring"
         ],
+        "dependencies": [],
         "category": "standard"
       }
     ],
@@ -1256,7 +1257,7 @@
         "category": "standard"
       },
       {
-        "id": "agents",
+        "id": "plugin-agents",
         "name": "Agents",
         "type": "context",
         "path": ".opencode/context/openagents-repo/plugins/context/capabilities/agents.md",
@@ -2133,6 +2134,7 @@
           "development",
           "patterns"
         ],
+        "dependencies": [],
         "category": "standard"
       },
       {
@@ -2145,6 +2147,7 @@
           "learning",
           "guide"
         ],
+        "dependencies": [],
         "category": "standard"
       },
       {
@@ -2157,6 +2160,7 @@
           "product",
           "guide"
         ],
+        "dependencies": [],
         "category": "standard"
       },
       {
@@ -2169,10 +2173,11 @@
           "data",
           "guide"
         ],
+        "dependencies": [],
         "category": "standard"
       },
       {
-        "id": "context-bundle-template",
+        "id": "context-bundle-template-alt",
         "name": "Context Bundle Template",
         "type": "context",
         "path": ".opencode/context/openagents-repo/templates/context-bundle-template.md",
@@ -2182,6 +2187,7 @@
           "context",
           "bundle"
         ],
+        "dependencies": [],
         "category": "standard"
       },
       {
@@ -2198,7 +2204,6 @@
           "dependencies"
         ],
         "dependencies": [
-          "context:external-libraries-workflow",
           "context:adding-agent-basics",
           "context:adding-skill-basics"
         ],
@@ -2413,7 +2418,7 @@
         "category": "navigation"
       },
       {
-        "id": "ui-navigation",
+        "id": "ui-nav-patterns",
         "name": "Navigation: UI",
         "type": "context",
         "path": ".opencode/context/ui/navigation.md",
@@ -2652,10 +2657,11 @@
         "name": "Agent Metadata",
         "type": "context",
         "path": ".opencode/context/openagents-repo/core-concepts/agent-metadata.md",
-        "description": "...\\\"               # \u2705 Valid OpenCode field",
+        "description": "Centralized metadata schema for OpenAgents Control agents — registry management, documentation, and tooling",
         "tags": [
-          "development",
-          "coding"
+          "metadata",
+          "registry",
+          "agents"
         ],
         "dependencies": [],
         "category": "standard"
@@ -3102,6 +3108,20 @@
         ],
         "dependencies": [],
         "category": "essential"
+      },
+      {
+        "id": "agent-metadata-config",
+        "name": "Agent Metadata Configuration",
+        "type": "config",
+        "path": ".opencode/config/agent-metadata.json",
+        "description": "Centralized metadata for OpenAgents Control agents — used for registry management, installation, and documentation",
+        "tags": [
+          "config",
+          "metadata",
+          "agents"
+        ],
+        "dependencies": [],
+        "category": "essential"
       }
     ]
   },
@@ -3133,7 +3153,8 @@
         "context:workflows-review",
         "context:system-context-guide",
         "context:adding-skill-basics",
-        "config:env-example"
+        "config:env-example",
+        "config:agent-metadata-config"
       ]
     },
     "developer": {
@@ -3180,7 +3201,8 @@
         "context:api-design",
         "config:env-example",
         "config:readme",
-        "context:openagents-repo/*"
+        "context:openagents-repo/*",
+        "config:agent-metadata-config"
       ]
     },
     "business": {
@@ -3210,7 +3232,8 @@
         "context:project-intelligence/*",
         "context:adding-skill-basics",
         "config:env-example",
-        "config:readme"
+        "config:readme",
+        "config:agent-metadata-config"
       ]
     },
     "full": {
@@ -3265,7 +3288,8 @@
         "context:api-design",
         "config:env-example",
         "config:readme",
-        "context:openagents-repo/*"
+        "context:openagents-repo/*",
+        "config:agent-metadata-config"
       ]
     },
     "advanced": {
@@ -3338,7 +3362,8 @@
         "context:frontmatter",
         "context:codebase-references",
         "config:env-example",
-        "config:readme"
+        "config:readme",
+        "config:agent-metadata-config"
       ],
       "additionalPaths": [
         ".Building/",
@@ -3348,21 +3373,6 @@
   },
   "metadata": {
     "lastUpdated": "2026-01-31",
-    "schemaVersion": "1.0.0"
-  },
-  "subagents": {
-    "test": {
-      "simple-responder": {
-        "id": "simple-responder",
-        "name": "Simple Responder",
-        "description": "Test agent that responds with AWESOME TESTING",
-        "category": "test",
-        "type": "utility",
-        "version": "1.0.0",
-        "path": ".opencode/agent/subagents/test/simple-responder.md",
-        "mode": "subagent",
-        "status": "stable"
-      }
-    }
+    "schemaVersion": "2.0.0"
   }
 }