aidevops 3.13.95 → 3.14.1

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.
@@ -1,287 +0,0 @@
1
- #!/usr/bin/env bash
2
- # SPDX-License-Identifier: MIT
3
- # SPDX-FileCopyrightText: 2025-2026 Marcus Quinn
4
- # Runtime agent deployment: convert and copy agents to each runtime's native directory.
5
- # Strips aidevops-only frontmatter (mode, subagents); keeps standard fields
6
- # (name, description, tools, model, permissionMode, hooks, mcpServers, etc.).
7
- # Split from agent-deploy.sh (t1940)
8
-
9
- # Shell safety baseline
10
- set -Eeuo pipefail
11
- IFS=$'\n\t'
12
- # shellcheck disable=SC2154 # rc is assigned by $? in the trap string
13
- trap 'rc=$?; echo "[ERROR] ${BASH_SOURCE[0]}:${LINENO} exit $rc" >&2' ERR
14
- shopt -s inherit_errexit 2>/dev/null || true
15
-
16
- # _convert_agent_frontmatter: strips aidevops-only fields from agent markdown.
17
- # Reads from stdin, writes converted content to stdout.
18
- # Tracks whether we're inside an indented block (subagents list) to correctly
19
- # skip its child lines without stripping other indented YAML fields.
20
- _convert_agent_frontmatter() {
21
- local in_frontmatter=false
22
- local frontmatter_started=false
23
- local in_skip_block=false
24
- local line_num=0
25
-
26
- while IFS= read -r line || [[ -n "$line" ]]; do
27
- line_num=$((line_num + 1))
28
- if [[ $line_num -eq 1 && "$line" == "---" ]]; then
29
- in_frontmatter=true
30
- frontmatter_started=true
31
- echo "$line"
32
- continue
33
- fi
34
- if [[ "$frontmatter_started" == "true" && "$in_frontmatter" == "true" && "$line" == "---" ]]; then
35
- in_frontmatter=false
36
- echo "$line"
37
- continue
38
- fi
39
- if [[ "$in_frontmatter" == "true" ]]; then
40
- # Detect top-level keys (no leading whitespace)
41
- case "$line" in
42
- mode:*)
43
- in_skip_block=false
44
- continue
45
- ;;
46
- subagents:*)
47
- in_skip_block=true
48
- continue
49
- ;;
50
- esac
51
- # If inside a skipped block, consume indented continuation lines
52
- if [[ "$in_skip_block" == "true" ]]; then
53
- case "$line" in
54
- [[:space:]]*)
55
- # Indented line under a skipped key — skip it
56
- continue
57
- ;;
58
- *)
59
- # Non-indented line — we've left the skip block
60
- in_skip_block=false
61
- echo "$line"
62
- ;;
63
- esac
64
- else
65
- echo "$line"
66
- fi
67
- else
68
- echo "$line"
69
- fi
70
- done
71
- return 0
72
- }
73
-
74
- # _is_agent_definition: check if a markdown file has agent frontmatter (name: field).
75
- # Returns 0 if the file is an agent definition, 1 otherwise.
76
- _is_agent_definition() {
77
- local file="$1"
78
- # Check first 30 lines for name: in YAML frontmatter (fast path)
79
- head -30 "$file" 2>/dev/null | grep -q '^name:' 2>/dev/null
80
- return $?
81
- }
82
-
83
- # _agent_source_dirs: list directories under agents_source that contain subagents.
84
- # Excludes framework infrastructure directories that are not agent definitions.
85
- _agent_source_dirs() {
86
- local agents_source="$1"
87
- local dir
88
- for dir in "$agents_source"/*/; do
89
- [[ -d "$dir" ]] || continue
90
- local dirname
91
- dirname=$(basename "$dir")
92
- # Skip framework infrastructure directories
93
- case "$dirname" in
94
- scripts | reference | prompts | templates | configs | hooks | \
95
- plugins | bundles | loop-state | advisories | aidevops | \
96
- custom | draft | tests | rules)
97
- continue
98
- ;;
99
- *)
100
- echo "$dir"
101
- ;;
102
- esac
103
- done
104
- return 0
105
- }
106
-
107
- # _collect_agent_files: print "abspath|relpath" lines for all deployable agent files
108
- # under agents_source. Excludes AGENTS.md, SKILL.md stubs, and non-agent markdown.
109
- _collect_agent_files() {
110
- local agents_source="$1"
111
- local f bn
112
-
113
- # Top-level agents
114
- for f in "$agents_source"/*.md; do
115
- [[ -f "$f" ]] || continue
116
- bn=$(basename "$f")
117
- [[ "$bn" == "AGENTS.md" ]] && continue
118
- if _is_agent_definition "$f"; then
119
- printf '%s|%s\n' "$f" "$bn"
120
- fi
121
- done
122
-
123
- # Subagent directories (recursive)
124
- local subdir
125
- while IFS= read -r subdir; do
126
- while IFS= read -r f; do
127
- [[ -f "$f" ]] || continue
128
- bn=$(basename "$f")
129
- # Skip SKILL.md stubs — they're directory indexes, not real agents
130
- [[ "$bn" == "SKILL.md" ]] && continue
131
- if _is_agent_definition "$f"; then
132
- local relpath="${f#"$agents_source"/}"
133
- printf '%s|%s\n' "$f" "$relpath"
134
- fi
135
- done < <(find "$subdir" -name '*.md' -type f 2>/dev/null)
136
- done < <(_agent_source_dirs "$agents_source")
137
- return 0
138
- }
139
-
140
- # _deploy_agents_to_single_runtime: convert and copy all agent files to one runtime.
141
- # Arguments: runtime_id agent_dir agent_list_file
142
- # agent_list_file contains "abspath|relpath" lines produced by _collect_agent_files.
143
- # Prints the count of successfully deployed agents to stdout.
144
- _deploy_agents_to_single_runtime() {
145
- local runtime_id="$1"
146
- local agent_dir="$2"
147
- local agent_list_file="$3"
148
-
149
- # Only deploy if the runtime is actually installed
150
- local binary config_path config_dir
151
- binary=$(rt_binary "$runtime_id")
152
- config_path=$(rt_config_path "$runtime_id")
153
- config_dir="$(dirname "$config_path" 2>/dev/null)"
154
-
155
- if ! type -P "$binary" >/dev/null 2>&1 && [[ ! -d "$config_dir" ]]; then
156
- echo "0"
157
- return 0
158
- fi
159
-
160
- mkdir -p "$agent_dir"
161
- local agent_count=0
162
- local src rel target target_parent
163
-
164
- while IFS='|' read -r src rel; do
165
- [[ -n "$src" && -n "$rel" ]] || continue
166
- target="$agent_dir/$rel"
167
- target_parent=$(dirname "$target")
168
- [[ -d "$target_parent" ]] || mkdir -p "$target_parent"
169
- if _convert_agent_frontmatter <"$src" >"$target"; then
170
- agent_count=$((agent_count + 1))
171
- fi
172
- done <"$agent_list_file"
173
-
174
- echo "$agent_count"
175
- return 0
176
- }
177
-
178
- # deploy_agents_to_runtimes: main entry point called by setup.sh.
179
- # Iterates all installed runtimes with agent directory support, converts and
180
- # deploys aidevops agents to each runtime's native agent directory.
181
- # Only files with name: frontmatter are deployed. SKILL.md stubs are excluded.
182
- deploy_agents_to_runtimes() {
183
- # Source runtime registry if not already loaded
184
- local registry_script="${INSTALL_DIR:-.}/.agents/scripts/runtime-registry.sh"
185
- if [[ -z "${_RUNTIME_REGISTRY_LOADED:-}" ]]; then
186
- if [[ -f "$registry_script" ]]; then
187
- # shellcheck source=/dev/null
188
- source "$registry_script"
189
- else
190
- print_warning "Runtime registry not found — skipping agent deployment to runtimes"
191
- return 0
192
- fi
193
- fi
194
-
195
- local agents_source="${HOME}/.aidevops/agents"
196
- if [[ ! -d "$agents_source" ]]; then
197
- print_warning "No deployed agents found at $agents_source — skipping"
198
- return 0
199
- fi
200
-
201
- # Build the agent file list once (shared across all runtimes) into a temp file.
202
- # Each line: "abspath|relpath"
203
- local agent_list_file
204
- agent_list_file=$(mktemp)
205
- trap 'rm -f "${agent_list_file:-}"' RETURN
206
- _collect_agent_files "$agents_source" >"$agent_list_file"
207
-
208
- local total_agents
209
- total_agents=$(wc -l <"$agent_list_file" | tr -d ' ')
210
- if [[ "$total_agents" -eq 0 ]]; then
211
- print_warning "No agent definitions found in $agents_source"
212
- return 0
213
- fi
214
-
215
- local deployed_count=0
216
- local runtime_count=0
217
-
218
- local runtime_id agent_dir agent_count display_name feature_flag
219
- while IFS= read -r runtime_id; do
220
- agent_dir=$(rt_agent_dir "$runtime_id")
221
- [[ -z "$agent_dir" ]] && continue
222
-
223
- # Feature flag gate — allow users to disable agent installation per
224
- # runtime via AIDEVOPS_FEATURE_AGENTS_<SUFFIX>=no (see runtime-registry).
225
- if declare -F rt_feature_agents >/dev/null 2>&1; then
226
- feature_flag=$(rt_feature_agents "$runtime_id" 2>/dev/null || echo "yes")
227
- if [[ "$feature_flag" != "yes" ]]; then
228
- display_name=$(rt_display_name "$runtime_id")
229
- print_info "Agent installation disabled for $display_name (feature flag)"
230
- continue
231
- fi
232
- fi
233
-
234
- agent_count=$(_deploy_agents_to_single_runtime "$runtime_id" "$agent_dir" "$agent_list_file")
235
- # A count of 0 means runtime not installed (skipped) — don't increment runtime_count
236
- if [[ "$agent_count" -gt 0 ]]; then
237
- display_name=$(rt_display_name "$runtime_id")
238
- print_info "Deployed $agent_count agents to $display_name ($agent_dir)"
239
- deployed_count=$((deployed_count + agent_count))
240
- runtime_count=$((runtime_count + 1))
241
- fi
242
- done < <(rt_list_with_agents)
243
-
244
- if [[ $runtime_count -eq 0 ]]; then
245
- print_info "No runtimes with agent directory support detected — skipping"
246
- else
247
- print_success "Deployed $deployed_count agent(s) across $runtime_count runtime(s)"
248
- fi
249
-
250
- return 0
251
- }
252
-
253
- # _deploy_agents_to_runtimes_bounded: time-bounded wrapper for deploy_agents_to_runtimes.
254
- #
255
- # deploy_agents_to_runtimes is a shell function (not an external script), so it
256
- # cannot be passed directly to the `timeout` binary. Instead we run it in a
257
- # background subshell and poll for completion with a configurable wall-clock
258
- # deadline. When the deadline expires the subshell is killed with SIGTERM then
259
- # SIGKILL and this non-critical step is treated as a warning so setup can
260
- # continue after core deployment has already succeeded.
261
- #
262
- # Configurable via AIDEVOPS_DEPLOY_RUNTIMES_TIMEOUT (default 120s).
263
- _deploy_agents_to_runtimes_bounded() {
264
- local timeout_s="${AIDEVOPS_DEPLOY_RUNTIMES_TIMEOUT:-120}"
265
- local _start_s=$SECONDS
266
- local _pid=""
267
- local _rc=0
268
-
269
- deploy_agents_to_runtimes &
270
- _pid=$!
271
-
272
- while kill -0 "$_pid" 2>/dev/null; do
273
- if (( SECONDS - _start_s >= timeout_s )); then
274
- kill -TERM "$_pid" 2>/dev/null || true
275
- sleep 2
276
- kill -KILL "$_pid" 2>/dev/null || true
277
- wait "$_pid" 2>/dev/null || true
278
- print_warning "Runtime agent deployment exceeded ${timeout_s}s — skipping (non-critical)"
279
- return 0
280
- fi
281
- sleep 1
282
- done
283
-
284
- wait "$_pid" 2>/dev/null
285
- _rc=$?
286
- return "$_rc"
287
- }