@ainova-systems/intelligence 0.11.3 → 0.11.4
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/engine/ENGINE_SHA +1 -1
- package/engine/VERSION +1 -1
- package/engine/adapters/agents.sh +75 -48
- package/engine/adapters/claude.sh +88 -58
- package/engine/adapters/codex.sh +39 -47
- package/engine/adapters/copilot.sh +120 -89
- package/engine/adapters/cursor.sh +110 -67
- package/engine/adapters/opencode.sh +77 -61
- package/engine/adapters/pi.sh +118 -80
- package/engine/lib/common.sh +746 -116
- package/engine/lib/contract.sh +2 -2
- package/engine/sync.sh +36 -14
- package/package.json +1 -1
- package/packages/sync/references/adapters.md +9 -1
package/engine/ENGINE_SHA
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
a8e3accf49ce60d8e0b04f04bc68ef6f813f2a2e
|
package/engine/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
0.11.
|
|
1
|
+
0.11.4
|
|
@@ -10,6 +10,9 @@
|
|
|
10
10
|
# Unlike other adapters, the output is a single committed markdown file
|
|
11
11
|
# meant to be read by both humans and LLMs. It must never be hand-edited —
|
|
12
12
|
# every sync regenerates it from scratch.
|
|
13
|
+
#
|
|
14
|
+
# Every per-file loop batches its work into one awk process (see the batched
|
|
15
|
+
# helpers in lib/common.sh): process spawns dominate sync time on Windows.
|
|
13
16
|
|
|
14
17
|
source "$(dirname "${BASH_SOURCE[0]}")/../lib/common.sh"
|
|
15
18
|
|
|
@@ -55,30 +58,37 @@ agents_md_append_agents_table() {
|
|
|
55
58
|
local rows=""
|
|
56
59
|
local count=0
|
|
57
60
|
|
|
61
|
+
local src f
|
|
62
|
+
local -a files=()
|
|
63
|
+
load_yaml_list "$config_file" "agents"
|
|
64
|
+
local list="$IS_YAML_LIST"
|
|
58
65
|
while IFS= read -r src; do
|
|
59
66
|
[ -z "$src" ] && continue
|
|
60
|
-
local dir
|
|
61
|
-
dir="$(resolve_source_dir "$repo_root" "$src")"
|
|
67
|
+
local dir="$repo_root/$src"
|
|
62
68
|
[ -d "$dir" ] || continue
|
|
63
69
|
# Byte-order (LC_ALL=C) sort so generated output is identical across
|
|
64
70
|
# platforms — bash glob order follows LC_COLLATE, which differs between
|
|
65
71
|
# Linux CI (UTF-8, ignores `-`) and Git Bash (C, byte order).
|
|
66
72
|
while IFS= read -r f; do
|
|
67
73
|
[ -f "$f" ] || continue
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
74
|
+
files+=("$f")
|
|
75
|
+
done < <(find "$dir" -maxdepth 1 -type f -name '*.md' -print | LC_ALL=C sort)
|
|
76
|
+
done <<< "$list"
|
|
77
|
+
|
|
78
|
+
if [ "${#files[@]}" -gt 0 ]; then
|
|
79
|
+
local path tier access desc name
|
|
80
|
+
while IFS=$'\x1f' read -r path tier access desc; do
|
|
81
|
+
[ -n "$path" ] || continue
|
|
82
|
+
name="${path##*/}"; name="${name%.md}"
|
|
83
|
+
repo_rel_link_var "$repo_root" "$path"
|
|
84
|
+
if [ -n "$IS_REPO_REL" ]; then
|
|
85
|
+
rows+="| [$name]($IS_REPO_REL) | ${tier:--} | ${access:--} | ${desc:--} |"$'\n'
|
|
76
86
|
else
|
|
77
87
|
rows+="| $name | ${tier:--} | ${access:--} | ${desc:--} |"$'\n'
|
|
78
88
|
fi
|
|
79
89
|
count=$((count + 1))
|
|
80
|
-
done < <(
|
|
81
|
-
|
|
90
|
+
done < <(frontmatter_index "tier,access,description" "${files[@]}")
|
|
91
|
+
fi
|
|
82
92
|
|
|
83
93
|
[ "$count" -eq 0 ] && return 0
|
|
84
94
|
|
|
@@ -102,31 +112,39 @@ agents_md_append_skills_table() {
|
|
|
102
112
|
local rows=""
|
|
103
113
|
local count=0
|
|
104
114
|
|
|
115
|
+
local src skill_dir dirname
|
|
116
|
+
local -a skill_files=()
|
|
117
|
+
load_yaml_list "$config_file" "skills"
|
|
118
|
+
local list="$IS_YAML_LIST"
|
|
105
119
|
while IFS= read -r src; do
|
|
106
120
|
[ -z "$src" ] && continue
|
|
107
|
-
local dir
|
|
108
|
-
dir="$(resolve_source_dir "$repo_root" "$src")"
|
|
121
|
+
local dir="$repo_root/$src"
|
|
109
122
|
[ -d "$dir" ] || continue
|
|
110
123
|
# Byte-order (LC_ALL=C) sort so generated output is identical across
|
|
111
124
|
# platforms — see the note in agents_md_append_agents_table.
|
|
112
125
|
while IFS= read -r skill_dir; do
|
|
113
126
|
[ -d "$skill_dir" ] || continue
|
|
114
|
-
|
|
115
|
-
dirname="$(basename "$skill_dir")"
|
|
127
|
+
dirname="${skill_dir##*/}"
|
|
116
128
|
case "$dirname" in _*) continue ;; esac
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
129
|
+
[ -f "${skill_dir%/}/SKILL.md" ] || continue
|
|
130
|
+
skill_files+=("${skill_dir%/}/SKILL.md")
|
|
131
|
+
done < <(find "$dir" -mindepth 1 -maxdepth 1 -type d -print | LC_ALL=C sort)
|
|
132
|
+
done <<< "$list"
|
|
133
|
+
|
|
134
|
+
if [ "${#skill_files[@]}" -gt 0 ]; then
|
|
135
|
+
local path desc
|
|
136
|
+
while IFS=$'\x1f' read -r path desc; do
|
|
137
|
+
[ -n "$path" ] || continue
|
|
138
|
+
dirname="${path%/SKILL.md}"; dirname="${dirname##*/}"
|
|
139
|
+
repo_rel_link_var "$repo_root" "$path"
|
|
140
|
+
if [ -n "$IS_REPO_REL" ]; then
|
|
141
|
+
rows+="| [$dirname]($IS_REPO_REL) | ${desc:--} |"$'\n'
|
|
124
142
|
else
|
|
125
143
|
rows+="| $dirname | ${desc:--} |"$'\n'
|
|
126
144
|
fi
|
|
127
145
|
count=$((count + 1))
|
|
128
|
-
done < <(
|
|
129
|
-
|
|
146
|
+
done < <(frontmatter_index "description" "${skill_files[@]}")
|
|
147
|
+
fi
|
|
130
148
|
|
|
131
149
|
[ "$count" -eq 0 ] && return 0
|
|
132
150
|
|
|
@@ -151,33 +169,43 @@ agents_md_append_rules_list() {
|
|
|
151
169
|
local count=0
|
|
152
170
|
local global_rule_files=()
|
|
153
171
|
|
|
172
|
+
local src f
|
|
173
|
+
local -a files=()
|
|
174
|
+
load_yaml_list "$config_file" "rules"
|
|
175
|
+
local list="$IS_YAML_LIST"
|
|
154
176
|
while IFS= read -r src; do
|
|
155
177
|
[ -z "$src" ] && continue
|
|
156
|
-
local dir
|
|
157
|
-
dir="$(resolve_source_dir "$repo_root" "$src")"
|
|
178
|
+
local dir="$repo_root/$src"
|
|
158
179
|
[ -d "$dir" ] || continue
|
|
159
180
|
# Byte-order (LC_ALL=C) sort so generated output — and the inline order
|
|
160
181
|
# of always-on rules below — is identical across platforms. See the
|
|
161
182
|
# note in agents_md_append_agents_table.
|
|
162
183
|
while IFS= read -r f; do
|
|
163
184
|
[ -f "$f" ] || continue
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
185
|
+
files+=("$f")
|
|
186
|
+
done < <(find "$dir" -maxdepth 1 -type f -name '*.md' -print | LC_ALL=C sort)
|
|
187
|
+
done <<< "$list"
|
|
188
|
+
|
|
189
|
+
if [ "${#files[@]}" -gt 0 ]; then
|
|
190
|
+
local path hp name scope
|
|
191
|
+
while IFS=$'\x1f' read -r path hp; do
|
|
192
|
+
[ -n "$path" ] || continue
|
|
193
|
+
name="${path##*/}"; name="${name%.md}"
|
|
167
194
|
scope="global"
|
|
168
|
-
if [ "$
|
|
195
|
+
if [ "$hp" != "0" ]; then
|
|
169
196
|
scope="scoped"
|
|
170
197
|
else
|
|
171
|
-
global_rule_files+=("$
|
|
198
|
+
global_rule_files+=("$path")
|
|
172
199
|
fi
|
|
173
|
-
|
|
174
|
-
|
|
200
|
+
repo_rel_link_var "$repo_root" "$path"
|
|
201
|
+
if [ -n "$IS_REPO_REL" ]; then
|
|
202
|
+
lines+="- [$name]($IS_REPO_REL) ($scope)"$'\n'
|
|
175
203
|
else
|
|
176
204
|
lines+="- $name ($scope)"$'\n'
|
|
177
205
|
fi
|
|
178
206
|
count=$((count + 1))
|
|
179
|
-
done < <(
|
|
180
|
-
|
|
207
|
+
done < <(frontmatter_index "paths#" "${files[@]}")
|
|
208
|
+
fi
|
|
181
209
|
|
|
182
210
|
[ "$count" -eq 0 ] && return 0
|
|
183
211
|
|
|
@@ -206,18 +234,17 @@ agents_md_append_rules_list() {
|
|
|
206
234
|
echo "<!-- Inlined from always-on rules in $content_rel/rules/ -->"
|
|
207
235
|
echo ""
|
|
208
236
|
} >> "$output"
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
done
|
|
237
|
+
# One awk inlines every global rule body, with a blank line after
|
|
238
|
+
# each — the same output the per-file passes produced.
|
|
239
|
+
awk '
|
|
240
|
+
FNR == 1 { if (NR != 1) print ""; in_fm = 0; past_fm = 0 }
|
|
241
|
+
{ sub(/\r$/, "") }
|
|
242
|
+
/^---$/ {
|
|
243
|
+
if (!past_fm) { in_fm = !in_fm; if (!in_fm) { past_fm = 1 }; next }
|
|
244
|
+
}
|
|
245
|
+
past_fm || !in_fm { print }
|
|
246
|
+
END { print "" }
|
|
247
|
+
' "${global_rule_files[@]}" >> "$output"
|
|
221
248
|
echo " rules: ${#global_rule_files[@]} global rule(s) inlined"
|
|
222
249
|
fi
|
|
223
250
|
}
|
|
@@ -5,6 +5,9 @@
|
|
|
5
5
|
# Rules: copy as-is (paths: frontmatter preserved)
|
|
6
6
|
# Skills: copy skill directories in full (SKILL.md + bundled resources)
|
|
7
7
|
# Agents: tier -> model, access -> tools/disallowedTools
|
|
8
|
+
#
|
|
9
|
+
# Every per-file loop batches its work into one awk process (see the batched
|
|
10
|
+
# helpers in lib/common.sh): process spawns dominate sync time on Windows.
|
|
8
11
|
|
|
9
12
|
source "$(dirname "${BASH_SOURCE[0]}")/../lib/common.sh"
|
|
10
13
|
|
|
@@ -29,18 +32,24 @@ sync_claude_rules() {
|
|
|
29
32
|
local config_file="$2"
|
|
30
33
|
local output_dir="$3"
|
|
31
34
|
|
|
35
|
+
local src f
|
|
36
|
+
local -a files=()
|
|
37
|
+
load_yaml_list "$config_file" "rules"
|
|
38
|
+
local list="$IS_YAML_LIST"
|
|
32
39
|
while IFS= read -r src; do
|
|
33
40
|
[ -z "$src" ] && continue
|
|
34
|
-
local dir
|
|
35
|
-
dir="$(resolve_source_dir "$repo_root" "$src")"
|
|
41
|
+
local dir="$repo_root/$src"
|
|
36
42
|
[ -d "$dir" ] || continue
|
|
37
43
|
for f in "$dir"/*.md; do
|
|
38
44
|
[ -f "$f" ] || continue
|
|
39
|
-
|
|
40
|
-
finalize_output_file "$output_dir/rules/$(basename "$f")"
|
|
41
|
-
echo " rule: $(basename "$f")"
|
|
45
|
+
files+=("$f")
|
|
42
46
|
done
|
|
43
|
-
done
|
|
47
|
+
done <<< "$list"
|
|
48
|
+
[ "${#files[@]}" -gt 0 ] || return 0
|
|
49
|
+
finalize_copy_files "$output_dir/rules" "${files[@]}"
|
|
50
|
+
for f in "${files[@]}"; do
|
|
51
|
+
echo " rule: ${f##*/}"
|
|
52
|
+
done
|
|
44
53
|
}
|
|
45
54
|
|
|
46
55
|
# Sync skills to Claude format (copy skill directories in full)
|
|
@@ -49,75 +58,98 @@ sync_claude_skills() {
|
|
|
49
58
|
local config_file="$2"
|
|
50
59
|
local output_dir="$3"
|
|
51
60
|
|
|
61
|
+
local src d skill_name
|
|
62
|
+
local -a skill_dirs=()
|
|
63
|
+
load_yaml_list "$config_file" "skills"
|
|
64
|
+
local list="$IS_YAML_LIST"
|
|
52
65
|
while IFS= read -r src; do
|
|
53
66
|
[ -z "$src" ] && continue
|
|
54
|
-
local dir
|
|
55
|
-
dir="$(resolve_source_dir "$repo_root" "$src")"
|
|
67
|
+
local dir="$repo_root/$src"
|
|
56
68
|
[ -d "$dir" ] || continue
|
|
57
69
|
for d in "$dir"/*/; do
|
|
58
70
|
[ -d "$d" ] || continue
|
|
59
|
-
local skill_name
|
|
60
|
-
skill_name="$(basename "$d")"
|
|
61
71
|
[ -f "$d/SKILL.md" ] || continue
|
|
62
|
-
|
|
63
|
-
echo " skill: $skill_name"
|
|
72
|
+
skill_dirs+=("$d")
|
|
64
73
|
done
|
|
65
|
-
done
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
local output_dir="$3"
|
|
73
|
-
local name
|
|
74
|
-
name="$(basename "$src")"
|
|
75
|
-
|
|
76
|
-
local tier access
|
|
77
|
-
tier=$(get_frontmatter_value "tier" "$src")
|
|
78
|
-
access=$(get_frontmatter_value "access" "$src")
|
|
79
|
-
|
|
80
|
-
local model tools extra
|
|
81
|
-
model=$(get_model "$config_file" "claude" "$tier")
|
|
82
|
-
tools=$(map_access_to_claude_tools "$access")
|
|
83
|
-
extra=$(map_access_to_claude_disallowed "$access")
|
|
84
|
-
|
|
85
|
-
# Transform: remove tier/access, inject tools/model/disallowedTools before closing ---
|
|
86
|
-
awk -v model="$model" -v tools="$tools" -v extra="$extra" '
|
|
87
|
-
BEGIN { count=0 }
|
|
88
|
-
/^tier:/ { next }
|
|
89
|
-
/^access:/ { next }
|
|
90
|
-
{
|
|
91
|
-
sub(/\r$/, "")
|
|
92
|
-
}
|
|
93
|
-
/^---$/ { count++ }
|
|
94
|
-
count==2 && /^---$/ {
|
|
95
|
-
if (tools != "") print "tools: " tools
|
|
96
|
-
if (extra != "") print "disallowedTools: " extra
|
|
97
|
-
print "model: " model
|
|
98
|
-
}
|
|
99
|
-
{ print }
|
|
100
|
-
' "$src" > "$output_dir/agents/$name"
|
|
101
|
-
finalize_output_file "$output_dir/agents/$name"
|
|
102
|
-
echo " agent: $name (tier=$tier -> model=$model, access=$access)"
|
|
74
|
+
done <<< "$list"
|
|
75
|
+
[ "${#skill_dirs[@]}" -gt 0 ] || return 0
|
|
76
|
+
copy_skill_bundle_dirs "$output_dir/skills" "${skill_dirs[@]}"
|
|
77
|
+
for d in "${skill_dirs[@]}"; do
|
|
78
|
+
skill_name="${d%/}"
|
|
79
|
+
echo " skill: ${skill_name##*/}"
|
|
80
|
+
done
|
|
103
81
|
}
|
|
104
82
|
|
|
105
|
-
# Sync all agents to Claude format
|
|
83
|
+
# Sync all agents to Claude format: one frontmatter pass resolves
|
|
84
|
+
# tier/access for every file, one transform pass writes every output.
|
|
106
85
|
sync_claude_agents() {
|
|
107
86
|
local repo_root="$1"
|
|
108
87
|
local config_file="$2"
|
|
109
88
|
local output_dir="$3"
|
|
110
89
|
|
|
90
|
+
local src f
|
|
91
|
+
local -a files=()
|
|
92
|
+
load_yaml_list "$config_file" "agents"
|
|
93
|
+
local list="$IS_YAML_LIST"
|
|
111
94
|
while IFS= read -r src; do
|
|
112
95
|
[ -z "$src" ] && continue
|
|
113
|
-
local dir
|
|
114
|
-
dir="$(resolve_source_dir "$repo_root" "$src")"
|
|
96
|
+
local dir="$repo_root/$src"
|
|
115
97
|
[ -d "$dir" ] || continue
|
|
116
98
|
for f in "$dir"/*.md; do
|
|
117
99
|
[ -f "$f" ] || continue
|
|
118
|
-
|
|
100
|
+
files+=("$f")
|
|
119
101
|
done
|
|
120
|
-
done
|
|
102
|
+
done <<< "$list"
|
|
103
|
+
[ "${#files[@]}" -gt 0 ] || return 0
|
|
104
|
+
|
|
105
|
+
load_model_tiers "$config_file" "claude"
|
|
106
|
+
|
|
107
|
+
local path tier access spec="" report=""
|
|
108
|
+
while IFS=$'\x1f' read -r path tier access; do
|
|
109
|
+
[ -n "$path" ] || continue
|
|
110
|
+
resolve_model_var "$tier"
|
|
111
|
+
map_access_to_claude_tools_var "$access"
|
|
112
|
+
map_access_to_claude_disallowed_var "$access"
|
|
113
|
+
spec+="$path"$'\x1f'"$IS_MODEL"$'\x1f'"$IS_CLAUDE_TOOLS"$'\x1f'"$IS_CLAUDE_DISALLOWED"$'\n'
|
|
114
|
+
report+=" agent: ${path##*/} (tier=$tier -> model=$IS_MODEL, access=$access)"$'\n'
|
|
115
|
+
done < <(frontmatter_index "tier,access" "${files[@]}")
|
|
116
|
+
|
|
117
|
+
# The transform used to run per file with the values injected via -v;
|
|
118
|
+
# the batched form carries them per file through the environment (awk -v
|
|
119
|
+
# would reprocess backslash escapes).
|
|
120
|
+
is_fin_awk_vars
|
|
121
|
+
IS_MAP_SPEC="$spec" awk "${IS_FIN_V[@]}" -v dst="$output_dir/agents" "$IS_AWK_LIB"'
|
|
122
|
+
BEGIN {
|
|
123
|
+
US = sprintf("%c", 31)
|
|
124
|
+
n = split(ENVIRON["IS_MAP_SPEC"], recs, "\n")
|
|
125
|
+
for (i = 1; i <= n; i++) {
|
|
126
|
+
if (recs[i] == "") continue
|
|
127
|
+
split(recs[i], f, US)
|
|
128
|
+
MODEL[f[1]] = f[2]; TOOLS[f[1]] = f[3]; EXTRA[f[1]] = f[4]
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
FNR == 1 {
|
|
132
|
+
if (out != "") close(out)
|
|
133
|
+
out = dst "/" base_name(FILENAME)
|
|
134
|
+
count = 0
|
|
135
|
+
}
|
|
136
|
+
/^tier:/ { next }
|
|
137
|
+
/^access:/ { next }
|
|
138
|
+
{ sub(/\r$/, "") }
|
|
139
|
+
/^---$/ { count++ }
|
|
140
|
+
count == 2 && /^---$/ {
|
|
141
|
+
if (TOOLS[FILENAME] != "") print fin_line("tools: " TOOLS[FILENAME]) > out
|
|
142
|
+
if (EXTRA[FILENAME] != "") print fin_line("disallowedTools: " EXTRA[FILENAME]) > out
|
|
143
|
+
print fin_line("model: " MODEL[FILENAME]) > out
|
|
144
|
+
}
|
|
145
|
+
{ print fin_line($0) > out }
|
|
146
|
+
' "${files[@]}"
|
|
147
|
+
# awk never reads a record from an empty source; the old per-file shell
|
|
148
|
+
# redirect still created an empty output for it.
|
|
149
|
+
for f in "${files[@]}"; do
|
|
150
|
+
[ -s "$f" ] || : > "$output_dir/agents/${f##*/}"
|
|
151
|
+
done
|
|
152
|
+
printf '%s' "$report"
|
|
121
153
|
}
|
|
122
154
|
|
|
123
155
|
# Main entry point for Claude adapter
|
|
@@ -133,9 +165,7 @@ sync_to_claude() {
|
|
|
133
165
|
# commands/, statusline.sh, etc.).
|
|
134
166
|
rm -rf "$output_dir/rules" "$output_dir/agents"
|
|
135
167
|
if [ -d "$output_dir/skills" ]; then
|
|
136
|
-
find "$output_dir/skills" -mindepth 1 -maxdepth 1 -type d
|
|
137
|
-
rm -rf "$d"
|
|
138
|
-
done
|
|
168
|
+
find "$output_dir/skills" -mindepth 1 -maxdepth 1 -type d -exec rm -rf {} +
|
|
139
169
|
fi
|
|
140
170
|
mkdir -p "$output_dir/rules" "$output_dir/skills" "$output_dir/agents"
|
|
141
171
|
|
package/engine/adapters/codex.sh
CHANGED
|
@@ -10,6 +10,9 @@
|
|
|
10
10
|
# reads from $REPO_ROOT/.agents/skills exclusively per official docs)
|
|
11
11
|
# Agents: -> .codex/agents/{name}.toml (name, description, model,
|
|
12
12
|
# model_reasoning_effort, sandbox_mode, developer_instructions)
|
|
13
|
+
#
|
|
14
|
+
# Every per-file loop batches its work into one awk process (see the batched
|
|
15
|
+
# helpers in lib/common.sh): process spawns dominate sync time on Windows.
|
|
13
16
|
|
|
14
17
|
source "$(dirname "${BASH_SOURCE[0]}")/../lib/common.sh"
|
|
15
18
|
|
|
@@ -38,24 +41,29 @@ sync_codex_agents() {
|
|
|
38
41
|
local config_file="$2"
|
|
39
42
|
local output_dir="$3"
|
|
40
43
|
|
|
41
|
-
local
|
|
44
|
+
local src f
|
|
45
|
+
local -a files=()
|
|
46
|
+
load_yaml_list "$config_file" "agents"
|
|
47
|
+
local list="$IS_YAML_LIST"
|
|
42
48
|
while IFS= read -r src; do
|
|
43
49
|
[ -z "$src" ] && continue
|
|
44
|
-
local dir
|
|
45
|
-
dir="$(resolve_source_dir "$repo_root" "$src")"
|
|
50
|
+
local dir="$repo_root/$src"
|
|
46
51
|
[ -d "$dir" ] || continue
|
|
47
52
|
for f in "$dir"/*.md; do
|
|
48
53
|
[ -f "$f" ] || continue
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
local tier access description
|
|
53
|
-
tier=$(get_frontmatter_value "tier" "$f")
|
|
54
|
-
access=$(get_frontmatter_value "access" "$f")
|
|
55
|
-
description=$(get_frontmatter_value "description" "$f")
|
|
54
|
+
files+=("$f")
|
|
55
|
+
done
|
|
56
|
+
done <<< "$list"
|
|
56
57
|
|
|
57
|
-
|
|
58
|
-
|
|
58
|
+
local count=0
|
|
59
|
+
if [ "${#files[@]}" -gt 0 ]; then
|
|
60
|
+
load_model_tiers "$config_file" "codex"
|
|
61
|
+
|
|
62
|
+
local path tier access description name effort sandbox spec="" report="" LS=$'\x1e'
|
|
63
|
+
while IFS=$'\x1f' read -r path tier access description; do
|
|
64
|
+
[ -n "$path" ] || continue
|
|
65
|
+
name="${path##*/}"; name="${name%.md}"
|
|
66
|
+
resolve_model_var "$tier"
|
|
59
67
|
case "$tier" in
|
|
60
68
|
heavy) effort="high" ;;
|
|
61
69
|
standard) effort="medium" ;;
|
|
@@ -66,43 +74,27 @@ sync_codex_agents() {
|
|
|
66
74
|
readonly) sandbox="read-only" ;;
|
|
67
75
|
*) sandbox="workspace-write" ;;
|
|
68
76
|
esac
|
|
69
|
-
|
|
70
|
-
local body
|
|
71
|
-
body=$(awk '
|
|
72
|
-
BEGIN { in_fm=0; past_fm=0 }
|
|
73
|
-
{ sub(/\r$/, "") }
|
|
74
|
-
/^---$/ {
|
|
75
|
-
if (!past_fm) { in_fm = !in_fm; if (!in_fm) { past_fm=1 }; next }
|
|
76
|
-
}
|
|
77
|
-
past_fm { print }
|
|
78
|
-
' "$f")
|
|
79
|
-
|
|
80
|
-
# Escape backslashes used in Markdown paths, then neutralize any
|
|
81
|
-
# closing TOML triple-quote sequence in the agent body.
|
|
82
|
-
local body_safe
|
|
83
|
-
body_safe="${body//\\/\\\\}"
|
|
84
|
-
body_safe="${body_safe//\"\"\"/\"\"\\\"}"
|
|
85
|
-
|
|
86
77
|
local name_escaped description_escaped
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
finalize_output_file "$output_dir/$name.toml"
|
|
78
|
+
toml_escape_var "$name"; name_escaped="$IS_TOML_ESCAPED"
|
|
79
|
+
toml_escape_var "$description"; description_escaped="$IS_TOML_ESCAPED"
|
|
80
|
+
|
|
81
|
+
local header
|
|
82
|
+
header="${LS}name = \"$name_escaped\""
|
|
83
|
+
header+="${LS}description = \"$description_escaped\""
|
|
84
|
+
header+="${LS}model = \"$IS_MODEL\""
|
|
85
|
+
header+="${LS}model_reasoning_effort = \"$effort\""
|
|
86
|
+
header+="${LS}sandbox_mode = \"$sandbox\""
|
|
87
|
+
header+="${LS}"
|
|
88
|
+
header+="${LS}developer_instructions = \"\"\""
|
|
89
|
+
|
|
90
|
+
spec+="$path"$'\x1f'"$output_dir/$name.toml"$'\x1f'"fence"$'\x1f'"1"$'\x1f'"toml"$'\x1f'"$header"$'\x1f'"${LS}\"\"\""$'\n'
|
|
91
|
+
report+=" agent: $name.toml"$'\n'
|
|
102
92
|
count=$((count + 1))
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
93
|
+
done < <(frontmatter_index "tier,access,description" "${files[@]}")
|
|
94
|
+
|
|
95
|
+
emit_wrapped_bodies "$spec"
|
|
96
|
+
printf '%s' "$report"
|
|
97
|
+
fi
|
|
106
98
|
|
|
107
99
|
echo " -> Agents: $count"
|
|
108
100
|
}
|