@paulduvall/claude-dev-toolkit 0.0.1-alpha.2 → 0.0.1-alpha.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +88 -37
- package/bin/claude-commands +307 -65
- package/commands/active/xarchitecture.md +393 -0
- package/commands/active/xconfig.md +127 -0
- package/commands/active/xcontinue.md +92 -0
- package/commands/active/xdebug.md +130 -0
- package/commands/active/xdocs.md +178 -0
- package/commands/active/xexplore.md +94 -0
- package/commands/active/xgit.md +149 -0
- package/commands/active/xpipeline.md +152 -0
- package/commands/active/xquality.md +96 -0
- package/commands/active/xrefactor.md +198 -0
- package/commands/active/xrelease.md +142 -0
- package/commands/active/xsecurity.md +92 -0
- package/commands/active/xspec.md +174 -0
- package/commands/active/xtdd.md +151 -0
- package/commands/active/xtest.md +89 -0
- package/commands/active/xverify.md +80 -0
- package/commands/experiments/xact.md +742 -0
- package/commands/experiments/xanalytics.md +113 -0
- package/commands/experiments/xanalyze.md +70 -0
- package/commands/experiments/xapi.md +161 -0
- package/commands/experiments/xatomic.md +112 -0
- package/commands/experiments/xaws.md +85 -0
- package/commands/experiments/xcicd.md +337 -0
- package/commands/experiments/xcommit.md +122 -0
- package/commands/experiments/xcompliance.md +182 -0
- package/commands/experiments/xconstraints.md +89 -0
- package/commands/experiments/xcoverage.md +90 -0
- package/commands/experiments/xdb.md +102 -0
- package/commands/experiments/xdesign.md +121 -0
- package/commands/experiments/xdevcontainer.md +238 -0
- package/commands/experiments/xevaluate.md +111 -0
- package/commands/experiments/xfootnote.md +12 -0
- package/commands/experiments/xgenerate.md +117 -0
- package/commands/experiments/xgovernance.md +149 -0
- package/commands/experiments/xgreen.md +66 -0
- package/commands/experiments/xiac.md +118 -0
- package/commands/experiments/xincident.md +137 -0
- package/commands/experiments/xinfra.md +115 -0
- package/commands/experiments/xknowledge.md +115 -0
- package/commands/experiments/xmaturity.md +120 -0
- package/commands/experiments/xmetrics.md +118 -0
- package/commands/experiments/xmonitoring.md +128 -0
- package/commands/experiments/xnew.md +903 -0
- package/commands/experiments/xobservable.md +114 -0
- package/commands/experiments/xoidc.md +165 -0
- package/commands/experiments/xoptimize.md +115 -0
- package/commands/experiments/xperformance.md +112 -0
- package/commands/experiments/xplanning.md +131 -0
- package/commands/experiments/xpolicy.md +115 -0
- package/commands/experiments/xproduct.md +98 -0
- package/commands/experiments/xreadiness.md +75 -0
- package/commands/experiments/xred.md +55 -0
- package/commands/experiments/xrisk.md +128 -0
- package/commands/experiments/xrules.md +124 -0
- package/commands/experiments/xsandbox.md +120 -0
- package/commands/experiments/xscan.md +102 -0
- package/commands/experiments/xsetup.md +123 -0
- package/commands/experiments/xtemplate.md +116 -0
- package/commands/experiments/xtrace.md +212 -0
- package/commands/experiments/xux.md +171 -0
- package/commands/experiments/xvalidate.md +104 -0
- package/commands/experiments/xworkflow.md +113 -0
- package/hooks/.smellrc.example.json +19 -0
- package/hooks/README.md +263 -0
- package/hooks/check-commit-signing.py +127 -0
- package/hooks/check-complexity.py +38 -0
- package/hooks/check-security.py +37 -0
- package/hooks/claude-wrapper.sh +29 -0
- package/hooks/config.py +110 -0
- package/hooks/file-logger.sh +100 -0
- package/hooks/lib/argument-parser.sh +427 -0
- package/hooks/lib/config-constants.sh +230 -0
- package/hooks/lib/context-manager.sh +560 -0
- package/hooks/lib/error-handler.sh +423 -0
- package/hooks/lib/execution-engine.sh +444 -0
- package/hooks/lib/execution-results.sh +113 -0
- package/hooks/lib/execution-simulation.sh +114 -0
- package/hooks/lib/field-validators.sh +104 -0
- package/hooks/lib/file-utils.sh +398 -0
- package/hooks/lib/subagent-discovery.sh +468 -0
- package/hooks/lib/subagent-validator.sh +407 -0
- package/hooks/lib/validation-reporter.sh +134 -0
- package/hooks/on-error-debug.sh +226 -0
- package/hooks/pre-commit-quality.sh +204 -0
- package/hooks/pre-commit-test-runner.sh +132 -0
- package/hooks/pre-write-security.sh +115 -0
- package/hooks/prevent-credential-exposure.sh +279 -0
- package/hooks/security_bandit.py +177 -0
- package/hooks/security_checks.py +97 -0
- package/hooks/security_secrets.py +81 -0
- package/hooks/security_trojan.py +61 -0
- package/hooks/settings.example.json +52 -0
- package/hooks/smell_checks.py +238 -0
- package/hooks/smell_javascript.py +231 -0
- package/hooks/smell_python.py +110 -0
- package/hooks/smell_ruff.py +70 -0
- package/hooks/smell_types.py +72 -0
- package/hooks/subagent-trigger-simple.sh +202 -0
- package/hooks/subagent-trigger.sh +253 -0
- package/hooks/suppression.py +82 -0
- package/hooks/tab-color.sh +70 -0
- package/hooks/verify-before-edit.sh +135 -0
- package/lib/backup-restore-command.js +140 -0
- package/lib/base/base-command.js +252 -0
- package/lib/base/command-result.js +184 -0
- package/lib/config/constants.js +255 -0
- package/lib/config.js +48 -6
- package/lib/configure-command.js +428 -0
- package/lib/dependency-validator.js +64 -5
- package/lib/hook-installer-core.js +2 -2
- package/lib/installation-instruction-generator.js +213 -495
- package/lib/installer.js +134 -56
- package/lib/oidc-command.js +740 -0
- package/lib/services/backup-list-service.js +226 -0
- package/lib/services/backup-service.js +230 -0
- package/lib/services/command-installer-service.js +217 -0
- package/lib/services/logger-service.js +201 -0
- package/lib/services/package-manager-service.js +319 -0
- package/lib/services/platform-instruction-service.js +294 -0
- package/lib/services/recovery-instruction-service.js +348 -0
- package/lib/services/restore-service.js +221 -0
- package/lib/setup-command.js +359 -0
- package/lib/setup-wizard.js +155 -262
- package/lib/uninstall-command.js +100 -0
- package/lib/utils/claude-path-config.js +184 -0
- package/lib/utils/file-system-utils.js +152 -0
- package/lib/utils.js +8 -4
- package/lib/verify-command.js +430 -0
- package/package.json +7 -3
- package/scripts/postinstall.js +172 -157
- package/subagents/debug-specialist.md +7 -0
- package/templates/README.md +115 -0
- package/templates/basic-settings.json +30 -0
- package/templates/comprehensive-settings.json +57 -0
- package/templates/global-claude.md +344 -0
- package/templates/hybrid-hook-config.yaml +132 -0
- package/templates/security-focused-settings.json +62 -0
- package/templates/subagent-hooks.yaml +188 -0
- package/lib/package-manager-service.js +0 -270
- package/subagents/debug-context.md +0 -197
|
@@ -0,0 +1,468 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -uo pipefail
|
|
3
|
+
|
|
4
|
+
# Subagent Discovery Module for Subagent-Hook Integration
|
|
5
|
+
#
|
|
6
|
+
# This module provides functionality to discover, locate, and enumerate
|
|
7
|
+
# available subagents across different directory hierarchies.
|
|
8
|
+
|
|
9
|
+
# Include guard
|
|
10
|
+
[[ -n "${_SUBAGENT_DISCOVERY_LOADED:-}" ]] && return 0
|
|
11
|
+
_SUBAGENT_DISCOVERY_LOADED=1
|
|
12
|
+
|
|
13
|
+
# Source required modules
|
|
14
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
15
|
+
source "$SCRIPT_DIR/config-constants.sh"
|
|
16
|
+
source "$SCRIPT_DIR/file-utils.sh"
|
|
17
|
+
source "$SCRIPT_DIR/error-handler.sh"
|
|
18
|
+
|
|
19
|
+
##################################
|
|
20
|
+
# Discovery Functions
|
|
21
|
+
##################################
|
|
22
|
+
|
|
23
|
+
find_subagent() {
|
|
24
|
+
local subagent_name="$1"
|
|
25
|
+
|
|
26
|
+
if [[ -z "$subagent_name" ]]; then
|
|
27
|
+
log_error "Subagent name is required for discovery"
|
|
28
|
+
return $EXIT_VALIDATION_FAILED
|
|
29
|
+
fi
|
|
30
|
+
|
|
31
|
+
log_debug "Searching for subagent: $subagent_name"
|
|
32
|
+
|
|
33
|
+
# Use the file utilities function for path resolution
|
|
34
|
+
local subagent_path
|
|
35
|
+
if subagent_path=$(resolve_subagent_path "$subagent_name"); then
|
|
36
|
+
log_debug "Found subagent at: $subagent_path"
|
|
37
|
+
echo "$subagent_path"
|
|
38
|
+
return $EXIT_SUCCESS
|
|
39
|
+
else
|
|
40
|
+
log_debug "Subagent not found: $subagent_name"
|
|
41
|
+
return $EXIT_SUBAGENT_NOT_FOUND
|
|
42
|
+
fi
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
discover_available_subagents() {
|
|
46
|
+
local search_dir="${1:-$SUBAGENTS_DIR}"
|
|
47
|
+
local subagents=()
|
|
48
|
+
|
|
49
|
+
log_debug "Discovering subagents in: $search_dir"
|
|
50
|
+
|
|
51
|
+
if [[ ! -d "$search_dir" ]]; then
|
|
52
|
+
log_debug "Subagents directory does not exist: $search_dir"
|
|
53
|
+
return $EXIT_SUCCESS
|
|
54
|
+
fi
|
|
55
|
+
|
|
56
|
+
# Find all .md files in the subagents directory
|
|
57
|
+
while IFS= read -r -d '' file; do
|
|
58
|
+
if is_valid_subagent_file "$file"; then
|
|
59
|
+
local name
|
|
60
|
+
name=$(basename "$file" "$SUBAGENT_FILE_EXTENSION")
|
|
61
|
+
subagents+=("$name")
|
|
62
|
+
log_debug "Discovered valid subagent: $name"
|
|
63
|
+
else
|
|
64
|
+
log_debug "Invalid subagent file skipped: $file"
|
|
65
|
+
fi
|
|
66
|
+
done < <(find "$search_dir" -name "*$SUBAGENT_FILE_EXTENSION" -type f -print0 2>/dev/null)
|
|
67
|
+
|
|
68
|
+
# Sort subagents alphabetically
|
|
69
|
+
mapfile -t subagents < <(printf '%s\n' "${subagents[@]}" | sort)
|
|
70
|
+
|
|
71
|
+
log_debug "Discovery complete: ${#subagents[@]} valid subagents found"
|
|
72
|
+
|
|
73
|
+
# Output results
|
|
74
|
+
printf '%s\n' "${subagents[@]}"
|
|
75
|
+
return $EXIT_SUCCESS
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
get_all_available_subagents() {
|
|
79
|
+
local all_subagents=()
|
|
80
|
+
local user_subagents project_subagents
|
|
81
|
+
|
|
82
|
+
log_debug "Getting all available subagents from all locations"
|
|
83
|
+
|
|
84
|
+
# Get user-level subagents
|
|
85
|
+
if user_subagents=$(discover_available_subagents "$SUBAGENTS_DIR" 2>/dev/null); then
|
|
86
|
+
while IFS= read -r subagent; do
|
|
87
|
+
[[ -n "$subagent" ]] && all_subagents+=("$subagent")
|
|
88
|
+
done <<< "$user_subagents"
|
|
89
|
+
fi
|
|
90
|
+
|
|
91
|
+
# Get project-level subagents (these take priority)
|
|
92
|
+
if [[ -d "$PROJECT_SUBAGENTS_DIR" ]]; then
|
|
93
|
+
if project_subagents=$(discover_available_subagents "$PROJECT_SUBAGENTS_DIR" 2>/dev/null); then
|
|
94
|
+
while IFS= read -r subagent; do
|
|
95
|
+
[[ -n "$subagent" ]] && all_subagents+=("$subagent")
|
|
96
|
+
done <<< "$project_subagents"
|
|
97
|
+
fi
|
|
98
|
+
fi
|
|
99
|
+
|
|
100
|
+
# Remove duplicates (project-level takes precedence)
|
|
101
|
+
local unique_subagents=()
|
|
102
|
+
local -A seen
|
|
103
|
+
|
|
104
|
+
for subagent in "${all_subagents[@]}"; do
|
|
105
|
+
if [[ -z "${seen[$subagent]}" ]]; then
|
|
106
|
+
unique_subagents+=("$subagent")
|
|
107
|
+
seen[$subagent]=1
|
|
108
|
+
fi
|
|
109
|
+
done
|
|
110
|
+
|
|
111
|
+
# Sort results
|
|
112
|
+
mapfile -t unique_subagents < <(printf '%s\n' "${unique_subagents[@]}" | sort)
|
|
113
|
+
|
|
114
|
+
log_debug "Total unique subagents available: ${#unique_subagents[@]}"
|
|
115
|
+
|
|
116
|
+
# Output results
|
|
117
|
+
printf '%s\n' "${unique_subagents[@]}"
|
|
118
|
+
return $EXIT_SUCCESS
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
##################################
|
|
122
|
+
# Subagent Information Functions
|
|
123
|
+
##################################
|
|
124
|
+
|
|
125
|
+
get_subagent_info() {
|
|
126
|
+
local subagent_name="$1"
|
|
127
|
+
local info_type="${2:-all}"
|
|
128
|
+
|
|
129
|
+
if [[ -z "$subagent_name" ]]; then
|
|
130
|
+
log_error "Subagent name is required"
|
|
131
|
+
return $EXIT_VALIDATION_FAILED
|
|
132
|
+
fi
|
|
133
|
+
|
|
134
|
+
local subagent_path
|
|
135
|
+
if ! subagent_path=$(find_subagent "$subagent_name"); then
|
|
136
|
+
log_error "Subagent not found: $subagent_name"
|
|
137
|
+
return $EXIT_SUBAGENT_NOT_FOUND
|
|
138
|
+
fi
|
|
139
|
+
|
|
140
|
+
local content
|
|
141
|
+
if ! content=$(read_file_safely "$subagent_path"); then
|
|
142
|
+
log_error "Failed to read subagent file: $subagent_path"
|
|
143
|
+
return $EXIT_GENERAL_ERROR
|
|
144
|
+
fi
|
|
145
|
+
|
|
146
|
+
# Parse YAML frontmatter
|
|
147
|
+
local in_frontmatter=false
|
|
148
|
+
local name="" description="" version="" tools="" tags=""
|
|
149
|
+
|
|
150
|
+
while IFS= read -r line; do
|
|
151
|
+
if [[ "$line" == "---" ]]; then
|
|
152
|
+
if [[ "$in_frontmatter" == true ]]; then
|
|
153
|
+
break # End of frontmatter
|
|
154
|
+
else
|
|
155
|
+
in_frontmatter=true
|
|
156
|
+
continue
|
|
157
|
+
fi
|
|
158
|
+
fi
|
|
159
|
+
|
|
160
|
+
if [[ "$in_frontmatter" == true ]]; then
|
|
161
|
+
case "$line" in
|
|
162
|
+
name:*)
|
|
163
|
+
name="${line#*: }"
|
|
164
|
+
name="${name#\"}"
|
|
165
|
+
name="${name%\"}"
|
|
166
|
+
;;
|
|
167
|
+
description:*)
|
|
168
|
+
description="${line#*: }"
|
|
169
|
+
description="${description#\"}"
|
|
170
|
+
description="${description%\"}"
|
|
171
|
+
;;
|
|
172
|
+
version:*)
|
|
173
|
+
version="${line#*: }"
|
|
174
|
+
version="${version#\"}"
|
|
175
|
+
version="${version%\"}"
|
|
176
|
+
;;
|
|
177
|
+
tools:*)
|
|
178
|
+
tools="${line#*: }"
|
|
179
|
+
tools="${tools#\"}"
|
|
180
|
+
tools="${tools%\"}"
|
|
181
|
+
;;
|
|
182
|
+
tags:*)
|
|
183
|
+
tags="${line#*: }"
|
|
184
|
+
;;
|
|
185
|
+
esac
|
|
186
|
+
fi
|
|
187
|
+
done <<< "$content"
|
|
188
|
+
|
|
189
|
+
# Output requested information
|
|
190
|
+
case "$info_type" in
|
|
191
|
+
"name")
|
|
192
|
+
echo "$name"
|
|
193
|
+
;;
|
|
194
|
+
"description")
|
|
195
|
+
echo "$description"
|
|
196
|
+
;;
|
|
197
|
+
"version")
|
|
198
|
+
echo "$version"
|
|
199
|
+
;;
|
|
200
|
+
"tools")
|
|
201
|
+
echo "$tools"
|
|
202
|
+
;;
|
|
203
|
+
"tags")
|
|
204
|
+
echo "$tags"
|
|
205
|
+
;;
|
|
206
|
+
"path")
|
|
207
|
+
echo "$subagent_path"
|
|
208
|
+
;;
|
|
209
|
+
"all"|*)
|
|
210
|
+
cat <<EOF
|
|
211
|
+
Name: $name
|
|
212
|
+
Description: $description
|
|
213
|
+
Version: ${version:-unknown}
|
|
214
|
+
Tools: ${tools:-all}
|
|
215
|
+
Tags: ${tags:-none}
|
|
216
|
+
Path: $subagent_path
|
|
217
|
+
EOF
|
|
218
|
+
;;
|
|
219
|
+
esac
|
|
220
|
+
|
|
221
|
+
return $EXIT_SUCCESS
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
list_subagents_with_info() {
|
|
225
|
+
local format="${1:-table}"
|
|
226
|
+
local available_subagents
|
|
227
|
+
|
|
228
|
+
log_debug "Listing all subagents with information (format: $format)"
|
|
229
|
+
|
|
230
|
+
if ! available_subagents=$(get_all_available_subagents); then
|
|
231
|
+
log_error "Failed to get available subagents"
|
|
232
|
+
return $EXIT_GENERAL_ERROR
|
|
233
|
+
fi
|
|
234
|
+
|
|
235
|
+
if [[ -z "$available_subagents" ]]; then
|
|
236
|
+
echo "No subagents found."
|
|
237
|
+
return $EXIT_SUCCESS
|
|
238
|
+
fi
|
|
239
|
+
|
|
240
|
+
case "$format" in
|
|
241
|
+
"json")
|
|
242
|
+
echo "["
|
|
243
|
+
local first=true
|
|
244
|
+
while IFS= read -r subagent; do
|
|
245
|
+
[[ -z "$subagent" ]] && continue
|
|
246
|
+
|
|
247
|
+
if [[ "$first" == true ]]; then
|
|
248
|
+
first=false
|
|
249
|
+
else
|
|
250
|
+
echo ","
|
|
251
|
+
fi
|
|
252
|
+
|
|
253
|
+
local name description version tools path
|
|
254
|
+
name=$(get_subagent_info "$subagent" "name" 2>/dev/null || echo "$subagent")
|
|
255
|
+
description=$(get_subagent_info "$subagent" "description" 2>/dev/null || echo "")
|
|
256
|
+
version=$(get_subagent_info "$subagent" "version" 2>/dev/null || echo "unknown")
|
|
257
|
+
tools=$(get_subagent_info "$subagent" "tools" 2>/dev/null || echo "all")
|
|
258
|
+
path=$(get_subagent_info "$subagent" "path" 2>/dev/null || echo "")
|
|
259
|
+
|
|
260
|
+
cat <<EOF
|
|
261
|
+
{
|
|
262
|
+
"name": "$name",
|
|
263
|
+
"description": "$description",
|
|
264
|
+
"version": "$version",
|
|
265
|
+
"tools": "$tools",
|
|
266
|
+
"path": "$path"
|
|
267
|
+
}
|
|
268
|
+
EOF
|
|
269
|
+
done <<< "$available_subagents"
|
|
270
|
+
echo "]"
|
|
271
|
+
;;
|
|
272
|
+
"table"|*)
|
|
273
|
+
printf "%-20s %-50s %-10s\n" "NAME" "DESCRIPTION" "VERSION"
|
|
274
|
+
printf "%-20s %-50s %-10s\n" "----" "-----------" "-------"
|
|
275
|
+
|
|
276
|
+
while IFS= read -r subagent; do
|
|
277
|
+
[[ -z "$subagent" ]] && continue
|
|
278
|
+
|
|
279
|
+
local name description version
|
|
280
|
+
name=$(get_subagent_info "$subagent" "name" 2>/dev/null || echo "$subagent")
|
|
281
|
+
description=$(get_subagent_info "$subagent" "description" 2>/dev/null || echo "No description")
|
|
282
|
+
version=$(get_subagent_info "$subagent" "version" 2>/dev/null || echo "unknown")
|
|
283
|
+
|
|
284
|
+
# Truncate long descriptions
|
|
285
|
+
if [[ ${#description} -gt 47 ]]; then
|
|
286
|
+
description="${description:0:44}..."
|
|
287
|
+
fi
|
|
288
|
+
|
|
289
|
+
printf "%-20s %-50s %-10s\n" "$name" "$description" "$version"
|
|
290
|
+
done <<< "$available_subagents"
|
|
291
|
+
;;
|
|
292
|
+
esac
|
|
293
|
+
|
|
294
|
+
return $EXIT_SUCCESS
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
##################################
|
|
298
|
+
# Event-Based Discovery Functions
|
|
299
|
+
##################################
|
|
300
|
+
|
|
301
|
+
get_subagents_for_event() {
|
|
302
|
+
local event_type="$1"
|
|
303
|
+
local config_file="${2:-$CONFIG_FILE}"
|
|
304
|
+
local subagents=()
|
|
305
|
+
|
|
306
|
+
if [[ -z "$event_type" ]]; then
|
|
307
|
+
log_error "Event type is required"
|
|
308
|
+
return $EXIT_VALIDATION_FAILED
|
|
309
|
+
fi
|
|
310
|
+
|
|
311
|
+
log_debug "Finding subagents for event: $event_type"
|
|
312
|
+
|
|
313
|
+
# Check if config file exists
|
|
314
|
+
if [[ ! -f "$config_file" ]]; then
|
|
315
|
+
log_debug "Configuration file not found: $config_file"
|
|
316
|
+
return $EXIT_SUCCESS
|
|
317
|
+
fi
|
|
318
|
+
|
|
319
|
+
if ! file_exists_and_readable "$config_file"; then
|
|
320
|
+
log_error "Configuration file not readable: $config_file"
|
|
321
|
+
return $EXIT_GENERAL_ERROR
|
|
322
|
+
fi
|
|
323
|
+
|
|
324
|
+
# Simple YAML parsing for event mappings
|
|
325
|
+
local in_event=false
|
|
326
|
+
local content
|
|
327
|
+
|
|
328
|
+
if ! content=$(read_file_safely "$config_file"); then
|
|
329
|
+
log_error "Failed to read configuration file: $config_file"
|
|
330
|
+
return $EXIT_GENERAL_ERROR
|
|
331
|
+
fi
|
|
332
|
+
|
|
333
|
+
while IFS= read -r line; do
|
|
334
|
+
# Skip comments and empty lines
|
|
335
|
+
[[ "$line" =~ ^[[:space:]]*# ]] && continue
|
|
336
|
+
[[ -z "${line// }" ]] && continue
|
|
337
|
+
|
|
338
|
+
# Check for event section
|
|
339
|
+
if [[ "$line" =~ ^[[:space:]]*${event_type}:[[:space:]]*$ ]]; then
|
|
340
|
+
in_event=true
|
|
341
|
+
log_debug "Found event section: $event_type"
|
|
342
|
+
continue
|
|
343
|
+
elif [[ "$line" =~ ^[[:space:]]*[a-z_][a-z0-9_-]*:[[:space:]]*$ ]]; then
|
|
344
|
+
in_event=false
|
|
345
|
+
continue
|
|
346
|
+
fi
|
|
347
|
+
|
|
348
|
+
# Extract subagent names from list items
|
|
349
|
+
if [[ "$in_event" == true ]] && [[ "$line" =~ ^[[:space:]]*-[[:space:]]*([a-z][a-z0-9-]*)[[:space:]]*$ ]]; then
|
|
350
|
+
local subagent_name="${BASH_REMATCH[1]}"
|
|
351
|
+
|
|
352
|
+
# Verify subagent exists before adding to list
|
|
353
|
+
if find_subagent "$subagent_name" >/dev/null 2>&1; then
|
|
354
|
+
subagents+=("$subagent_name")
|
|
355
|
+
log_debug "Added subagent for event: $subagent_name"
|
|
356
|
+
else
|
|
357
|
+
log_warning "Configured subagent not found: $subagent_name"
|
|
358
|
+
fi
|
|
359
|
+
fi
|
|
360
|
+
done <<< "$content"
|
|
361
|
+
|
|
362
|
+
log_debug "Found ${#subagents[@]} subagents for event: $event_type"
|
|
363
|
+
|
|
364
|
+
# Output results
|
|
365
|
+
printf '%s\n' "${subagents[@]}"
|
|
366
|
+
return $EXIT_SUCCESS
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
get_priority_for_subagent() {
|
|
370
|
+
local subagent_name="$1"
|
|
371
|
+
local config_file="${2:-$CONFIG_FILE}"
|
|
372
|
+
local default_priority="$DEFAULT_PRIORITY"
|
|
373
|
+
|
|
374
|
+
if [[ -z "$subagent_name" ]]; then
|
|
375
|
+
log_error "Subagent name is required"
|
|
376
|
+
return $EXIT_VALIDATION_FAILED
|
|
377
|
+
fi
|
|
378
|
+
|
|
379
|
+
# Check if config file exists and is readable
|
|
380
|
+
if [[ ! -f "$config_file" ]] || ! file_exists_and_readable "$config_file"; then
|
|
381
|
+
echo "$default_priority"
|
|
382
|
+
return $EXIT_SUCCESS
|
|
383
|
+
fi
|
|
384
|
+
|
|
385
|
+
local content
|
|
386
|
+
if ! content=$(read_file_safely "$config_file"); then
|
|
387
|
+
echo "$default_priority"
|
|
388
|
+
return $EXIT_SUCCESS
|
|
389
|
+
fi
|
|
390
|
+
|
|
391
|
+
# Look for priority configuration
|
|
392
|
+
local in_priorities=false
|
|
393
|
+
local in_subagent=false
|
|
394
|
+
|
|
395
|
+
while IFS= read -r line; do
|
|
396
|
+
# Skip comments and empty lines
|
|
397
|
+
[[ "$line" =~ ^[[:space:]]*# ]] && continue
|
|
398
|
+
[[ -z "${line// }" ]] && continue
|
|
399
|
+
|
|
400
|
+
# Check for priorities section
|
|
401
|
+
if [[ "$line" =~ ^[[:space:]]*priorities:[[:space:]]*$ ]]; then
|
|
402
|
+
in_priorities=true
|
|
403
|
+
continue
|
|
404
|
+
elif [[ "$line" =~ ^[[:space:]]*[a-z_][a-z0-9_-]*:[[:space:]]*$ ]] && [[ "$in_priorities" == false ]]; then
|
|
405
|
+
continue
|
|
406
|
+
fi
|
|
407
|
+
|
|
408
|
+
# Check for subagent in priorities section
|
|
409
|
+
if [[ "$in_priorities" == true ]]; then
|
|
410
|
+
if [[ "$line" =~ ^[[:space:]]*${subagent_name}:[[:space:]]*$ ]]; then
|
|
411
|
+
in_subagent=true
|
|
412
|
+
continue
|
|
413
|
+
elif [[ "$line" =~ ^[[:space:]]*[a-z][a-z0-9-]*:[[:space:]]*$ ]]; then
|
|
414
|
+
in_subagent=false
|
|
415
|
+
continue
|
|
416
|
+
fi
|
|
417
|
+
|
|
418
|
+
# Extract priority value
|
|
419
|
+
if [[ "$in_subagent" == true ]] && [[ "$line" =~ ^[[:space:]]*priority:[[:space:]]*([0-9]+)[[:space:]]*$ ]]; then
|
|
420
|
+
echo "${BASH_REMATCH[1]}"
|
|
421
|
+
return $EXIT_SUCCESS
|
|
422
|
+
fi
|
|
423
|
+
fi
|
|
424
|
+
done <<< "$content"
|
|
425
|
+
|
|
426
|
+
# Return default if not found
|
|
427
|
+
echo "$default_priority"
|
|
428
|
+
return $EXIT_SUCCESS
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
##################################
|
|
432
|
+
# Discovery Validation Functions
|
|
433
|
+
##################################
|
|
434
|
+
|
|
435
|
+
validate_discovery_environment() {
|
|
436
|
+
log_debug "Validating discovery environment"
|
|
437
|
+
|
|
438
|
+
# Check if subagents directory exists
|
|
439
|
+
if [[ ! -d "$SUBAGENTS_DIR" ]]; then
|
|
440
|
+
log_warning "User subagents directory does not exist: $SUBAGENTS_DIR"
|
|
441
|
+
if ! ensure_directory_exists "$SUBAGENTS_DIR"; then
|
|
442
|
+
log_error "Failed to create subagents directory: $SUBAGENTS_DIR"
|
|
443
|
+
return $EXIT_GENERAL_ERROR
|
|
444
|
+
fi
|
|
445
|
+
fi
|
|
446
|
+
|
|
447
|
+
# Check directory permissions
|
|
448
|
+
if [[ ! -r "$SUBAGENTS_DIR" ]]; then
|
|
449
|
+
log_error "Subagents directory not readable: $SUBAGENTS_DIR"
|
|
450
|
+
return $EXIT_GENERAL_ERROR
|
|
451
|
+
fi
|
|
452
|
+
|
|
453
|
+
log_debug "Discovery environment validation complete"
|
|
454
|
+
return $EXIT_SUCCESS
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
##################################
|
|
458
|
+
# Initialization
|
|
459
|
+
##################################
|
|
460
|
+
|
|
461
|
+
initialize_subagent_discovery() {
|
|
462
|
+
log_debug "Subagent discovery module initialized"
|
|
463
|
+
|
|
464
|
+
# Validate discovery environment
|
|
465
|
+
validate_discovery_environment || return $?
|
|
466
|
+
|
|
467
|
+
return $EXIT_SUCCESS
|
|
468
|
+
}
|