aico-cli 0.2.4 → 0.2.7
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/dist/chunks/feature-checker.mjs +2 -3
- package/dist/chunks/simple-config.mjs +206 -64
- package/dist/cli.mjs +5 -5
- package/dist/index.d.mts +16 -2
- package/dist/index.d.ts +16 -2
- package/dist/index.mjs +2 -2
- package/dist/shared/{aico-cli.C9hv-Gol.mjs → aico-cli.CWSSz8Hk.mjs} +1 -1
- package/package.json +1 -1
- package/templates/CLAUDE.md +2 -71
- package/templates/agents/aico/requirement/PLATFORM_COMPATIBILITY.md +219 -0
- package/templates/agents/aico/requirement/crossplatform-utils.sh +307 -0
- package/templates/agents/aico/requirement/requirement-functions-crossplatform.sh +472 -0
- package/templates/agents/aico/requirement/requirement-identifier.md +286 -156
- package/templates/agents/aico/requirement/requirement-launcher.sh +146 -0
- package/templates/agents/aico/requirement/task-executor.md +121 -33
- package/templates/agents/aico/requirement/task-splitter-validator.md +18 -4
- package/templates/commands/aico/requirement.md +19 -4
- package/templates/personality.md +118 -235
- package/templates/utils/task-manager.sh +401 -0
- package/templates/base.md +0 -51
|
@@ -0,0 +1,401 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
|
|
3
|
+
# 跨平台任务管理器 - 支持 Windows (Git Bash/Cygwin/WSL), Linux, macOS
|
|
4
|
+
|
|
5
|
+
set -euo pipefail
|
|
6
|
+
|
|
7
|
+
# 检测平台类型
|
|
8
|
+
detect_platform() {
|
|
9
|
+
case "$(uname -s)" in
|
|
10
|
+
Darwin)
|
|
11
|
+
echo "macos"
|
|
12
|
+
;;
|
|
13
|
+
Linux)
|
|
14
|
+
if grep -q "Microsoft" /proc/version 2>/dev/null; then
|
|
15
|
+
echo "wsl"
|
|
16
|
+
else
|
|
17
|
+
echo "linux"
|
|
18
|
+
fi
|
|
19
|
+
;;
|
|
20
|
+
CYGWIN*|MINGW*|MSYS*)
|
|
21
|
+
echo "windows"
|
|
22
|
+
;;
|
|
23
|
+
*)
|
|
24
|
+
echo "unknown"
|
|
25
|
+
;;
|
|
26
|
+
esac
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
# 获取临时目录(跨平台兼容)
|
|
30
|
+
get_temp_dir() {
|
|
31
|
+
local platform="$(detect_platform)"
|
|
32
|
+
case "$platform" in
|
|
33
|
+
windows|cygwin|mingw|msys)
|
|
34
|
+
# Windows 系统
|
|
35
|
+
if [ -n "${TEMP:-}" ]; then
|
|
36
|
+
echo "$TEMP"
|
|
37
|
+
elif [ -n "${TMP:-}" ]; then
|
|
38
|
+
echo "$TMP"
|
|
39
|
+
else
|
|
40
|
+
echo "/tmp"
|
|
41
|
+
fi
|
|
42
|
+
;;
|
|
43
|
+
*)
|
|
44
|
+
# Unix-like 系统
|
|
45
|
+
echo "/tmp"
|
|
46
|
+
;;
|
|
47
|
+
esac
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
# 安全的文件操作(跨平台兼容)
|
|
51
|
+
safe_file_operation() {
|
|
52
|
+
local operation="$1"
|
|
53
|
+
local file_path="$2"
|
|
54
|
+
local content="${3:-}"
|
|
55
|
+
|
|
56
|
+
case "$operation" in
|
|
57
|
+
read)
|
|
58
|
+
if [ -f "$file_path" ]; then
|
|
59
|
+
cat "$file_path" 2>/dev/null || echo ""
|
|
60
|
+
else
|
|
61
|
+
echo ""
|
|
62
|
+
fi
|
|
63
|
+
;;
|
|
64
|
+
write)
|
|
65
|
+
mkdir -p "$(dirname "$file_path")"
|
|
66
|
+
echo "$content" > "$file_path"
|
|
67
|
+
;;
|
|
68
|
+
append)
|
|
69
|
+
mkdir -p "$(dirname "$file_path")"
|
|
70
|
+
echo "$content" >> "$file_path"
|
|
71
|
+
;;
|
|
72
|
+
lock)
|
|
73
|
+
# 文件锁定机制(跨平台兼容)
|
|
74
|
+
local lock_file="$file_path.lock"
|
|
75
|
+
local timeout=${4:-30}
|
|
76
|
+
local start_time=$(date +%s)
|
|
77
|
+
|
|
78
|
+
while [ -f "$lock_file" ]; do
|
|
79
|
+
local current_time=$(date +%s)
|
|
80
|
+
local elapsed=$((current_time - start_time))
|
|
81
|
+
|
|
82
|
+
if [ $elapsed -ge $timeout ]; then
|
|
83
|
+
echo "锁定超时: $file_path" >&2
|
|
84
|
+
return 1
|
|
85
|
+
fi
|
|
86
|
+
sleep 1
|
|
87
|
+
done
|
|
88
|
+
|
|
89
|
+
touch "$lock_file"
|
|
90
|
+
;;
|
|
91
|
+
unlock)
|
|
92
|
+
rm -f "$file_path.lock" 2>/dev/null || true
|
|
93
|
+
;;
|
|
94
|
+
esac
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
# 原子任务领取
|
|
98
|
+
task_acquire() {
|
|
99
|
+
local task_list_path="$1"
|
|
100
|
+
local task_id="$2"
|
|
101
|
+
local executor_id="${3:-$(hostname)-$(date +%s)}"
|
|
102
|
+
|
|
103
|
+
# 锁定任务清单文件
|
|
104
|
+
safe_file_operation lock "$task_list_path"
|
|
105
|
+
|
|
106
|
+
# 读取任务清单
|
|
107
|
+
local task_list_content="$(safe_file_operation read "$task_list_path")"
|
|
108
|
+
|
|
109
|
+
# 查找任务并检查状态
|
|
110
|
+
if echo "$task_list_content" | grep -q "$task_id"; then
|
|
111
|
+
local task_status=$(echo "$task_list_content" | awk -v id="$task_id" '
|
|
112
|
+
$0 ~ id {
|
|
113
|
+
for(i=1; i<=NF; i++) {
|
|
114
|
+
if ($i ~ /^状态:/) {
|
|
115
|
+
gsub(/状态:/, "", $i)
|
|
116
|
+
print $i
|
|
117
|
+
exit
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}'
|
|
121
|
+
)
|
|
122
|
+
|
|
123
|
+
# 检查任务状态
|
|
124
|
+
if [ "$task_status" = "待执行" ]; then
|
|
125
|
+
# 更新任务状态为执行中
|
|
126
|
+
local updated_content=$(echo "$task_list_content" | awk -v id="$task_id" -v executor="$executor_id" -v timestamp="$(date +'%Y-%m-%d %H:%M:%S')" '
|
|
127
|
+
$0 ~ id {
|
|
128
|
+
gsub(/状态:待执行/, "状态:执行中")
|
|
129
|
+
gsub(/执行者:/, "执行者:" executor " 开始时间:" timestamp)
|
|
130
|
+
}
|
|
131
|
+
{ print }
|
|
132
|
+
')
|
|
133
|
+
|
|
134
|
+
safe_file_operation write "$task_list_path" "$updated_content"
|
|
135
|
+
echo "任务领取成功: $task_id"
|
|
136
|
+
return 0
|
|
137
|
+
else
|
|
138
|
+
echo "任务状态不可领取: $task_status" >&2
|
|
139
|
+
return 1
|
|
140
|
+
fi
|
|
141
|
+
else
|
|
142
|
+
echo "任务不存在: $task_id" >&2
|
|
143
|
+
return 1
|
|
144
|
+
fi
|
|
145
|
+
|
|
146
|
+
# 解锁文件
|
|
147
|
+
safe_file_operation unlock "$task_list_path"
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
# 原子任务完成
|
|
151
|
+
task_complete() {
|
|
152
|
+
local task_list_path="$1"
|
|
153
|
+
local task_id="$2"
|
|
154
|
+
local result="${3:-成功}"
|
|
155
|
+
|
|
156
|
+
safe_file_operation lock "$task_list_path"
|
|
157
|
+
|
|
158
|
+
local task_list_content="$(safe_file_operation read "$task_list_path")"
|
|
159
|
+
|
|
160
|
+
local updated_content=$(echo "$task_list_content" | awk -v id="$task_id" -v result="$result" -v timestamp="$(date +'%Y-%m-%d %H:%M:%S')" '
|
|
161
|
+
$0 ~ id {
|
|
162
|
+
gsub(/状态:执行中/, "状态:已完成")
|
|
163
|
+
gsub(/执行者:[^ ]*/, "& 完成时间:" timestamp " 结果:" result)
|
|
164
|
+
}
|
|
165
|
+
{ print }
|
|
166
|
+
')
|
|
167
|
+
|
|
168
|
+
safe_file_operation write "$task_list_path" "$updated_content"
|
|
169
|
+
|
|
170
|
+
safe_file_operation unlock "$task_list_path"
|
|
171
|
+
echo "任务完成: $task_id - $result"
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
# 原子任务失败
|
|
175
|
+
task_fail() {
|
|
176
|
+
local task_list_path="$1"
|
|
177
|
+
local task_id="$2"
|
|
178
|
+
local error_message="$3"
|
|
179
|
+
|
|
180
|
+
safe_file_operation lock "$task_list_path"
|
|
181
|
+
|
|
182
|
+
local task_list_content="$(safe_file_operation read "$task_list_path")"
|
|
183
|
+
|
|
184
|
+
local updated_content=$(echo "$task_list_content" | awk -v id="$task_id" -v error="$error_message" -v timestamp="$(date +'%Y-%m-%d %H:%M:%S')" '
|
|
185
|
+
$0 ~ id {
|
|
186
|
+
gsub(/状态:执行中/, "状态:失败")
|
|
187
|
+
gsub(/执行者:[^ ]*/, "& 失败时间:" timestamp " 错误:" error)
|
|
188
|
+
}
|
|
189
|
+
{ print }
|
|
190
|
+
')
|
|
191
|
+
|
|
192
|
+
safe_file_operation write "$task_list_path" "$updated_content"
|
|
193
|
+
|
|
194
|
+
safe_file_operation unlock "$task_list_path"
|
|
195
|
+
echo "任务失败: $task_id - $error_message" >&2
|
|
196
|
+
return 1
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
# 获取可执行任务列表
|
|
200
|
+
get_available_tasks() {
|
|
201
|
+
local task_list_path="$1"
|
|
202
|
+
|
|
203
|
+
safe_file_operation lock "$task_list_path"
|
|
204
|
+
|
|
205
|
+
local task_list_content="$(safe_file_operation read "$task_list_path")"
|
|
206
|
+
|
|
207
|
+
# 提取状态为"待执行"的任务
|
|
208
|
+
echo "$task_list_content" | awk '
|
|
209
|
+
/^#### 任务[A-Za-z0-9-]+:/ {
|
|
210
|
+
task_id = $2
|
|
211
|
+
gsub(/:/, "", task_id)
|
|
212
|
+
status = ""
|
|
213
|
+
in_task = 1
|
|
214
|
+
}
|
|
215
|
+
in_task && /^状态:/ {
|
|
216
|
+
status = $0
|
|
217
|
+
gsub(/状态:/, "", status)
|
|
218
|
+
gsub(/^[ \t]+|[ \t]+$/, "", status)
|
|
219
|
+
}
|
|
220
|
+
in_task && /^---$/ {
|
|
221
|
+
if (status == "待执行") {
|
|
222
|
+
print task_id
|
|
223
|
+
}
|
|
224
|
+
in_task = 0
|
|
225
|
+
status = ""
|
|
226
|
+
}
|
|
227
|
+
'
|
|
228
|
+
|
|
229
|
+
safe_file_operation unlock "$task_list_path"
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
# 检查任务依赖是否满足
|
|
233
|
+
check_task_dependencies() {
|
|
234
|
+
local task_list_path="$1"
|
|
235
|
+
local task_id="$2"
|
|
236
|
+
|
|
237
|
+
safe_file_operation lock "$task_list_path"
|
|
238
|
+
|
|
239
|
+
local task_list_content="$(safe_file_operation read "$task_list_path")"
|
|
240
|
+
|
|
241
|
+
# 提取任务的依赖
|
|
242
|
+
local dependencies=$(echo "$task_list_content" | awk -v id="$task_id" '
|
|
243
|
+
$0 ~ id {
|
|
244
|
+
for(i=1; i<=NF; i++) {
|
|
245
|
+
if ($i ~ /^依赖:/) {
|
|
246
|
+
# 打印依赖行并退出
|
|
247
|
+
print $0
|
|
248
|
+
exit
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
')
|
|
253
|
+
|
|
254
|
+
# 提取依赖的任务ID
|
|
255
|
+
local dep_tasks=$(echo "$dependencies" | grep -oE '[A-Z]+-[0-9]+' || true)
|
|
256
|
+
|
|
257
|
+
# 检查每个依赖任务的状态
|
|
258
|
+
local all_deps_completed=true
|
|
259
|
+
for dep_task in $dep_tasks; do
|
|
260
|
+
local dep_status=$(echo "$task_list_content" | awk -v id="$dep_task" '
|
|
261
|
+
$0 ~ id {
|
|
262
|
+
for(i=1; i<=NF; i++) {
|
|
263
|
+
if ($i ~ /^状态:/) {
|
|
264
|
+
gsub(/状态:/, "", $i)
|
|
265
|
+
print $i
|
|
266
|
+
exit
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
')
|
|
271
|
+
|
|
272
|
+
if [ "$dep_status" != "已完成" ]; then
|
|
273
|
+
echo "依赖任务未完成: $dep_task (状态: $dep_status)" >&2
|
|
274
|
+
all_deps_completed=false
|
|
275
|
+
fi
|
|
276
|
+
done
|
|
277
|
+
|
|
278
|
+
safe_file_operation unlock "$task_list_path"
|
|
279
|
+
|
|
280
|
+
$all_deps_completed
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
# 并行任务执行协调器
|
|
284
|
+
parallel_task_executor() {
|
|
285
|
+
local task_list_path="$1"
|
|
286
|
+
local max_parallel="${2:-3}"
|
|
287
|
+
|
|
288
|
+
echo "开始并行任务执行 (最大并行数: $max_parallel)"
|
|
289
|
+
|
|
290
|
+
while true; do
|
|
291
|
+
# 获取可用任务
|
|
292
|
+
local available_tasks=$(get_available_tasks "$task_list_path")
|
|
293
|
+
|
|
294
|
+
if [ -z "$available_tasks" ]; then
|
|
295
|
+
echo "所有任务已完成"
|
|
296
|
+
break
|
|
297
|
+
fi
|
|
298
|
+
|
|
299
|
+
local running_tasks=0
|
|
300
|
+
local completed_tasks=0
|
|
301
|
+
|
|
302
|
+
# 检查当前运行中的任务数
|
|
303
|
+
safe_file_operation lock "$task_list_path"
|
|
304
|
+
local task_list_content="$(safe_file_operation read "$task_list_path")"
|
|
305
|
+
running_tasks=$(echo "$task_list_content" | grep -c "状态:执行中" || true)
|
|
306
|
+
completed_tasks=$(echo "$task_list_content" | grep -c "状态:已完成" || true)
|
|
307
|
+
safe_file_operation unlock "$task_list_path"
|
|
308
|
+
|
|
309
|
+
# 如果还有并行空间,领取新任务
|
|
310
|
+
if [ $running_tasks -lt $max_parallel ]; then
|
|
311
|
+
for task_id in $available_tasks; do
|
|
312
|
+
if [ $running_tasks -ge $max_parallel ]; then
|
|
313
|
+
break
|
|
314
|
+
fi
|
|
315
|
+
|
|
316
|
+
# 检查任务依赖
|
|
317
|
+
if check_task_dependencies "$task_list_path" "$task_id"; then
|
|
318
|
+
# 尝试领取任务
|
|
319
|
+
if task_acquire "$task_list_path" "$task_id" 2>/dev/null; then
|
|
320
|
+
echo "开始执行任务: $task_id"
|
|
321
|
+
# 在实际使用中,这里会调用具体的任务执行逻辑
|
|
322
|
+
((running_tasks++))
|
|
323
|
+
fi
|
|
324
|
+
fi
|
|
325
|
+
done
|
|
326
|
+
fi
|
|
327
|
+
|
|
328
|
+
# 等待一段时间再检查
|
|
329
|
+
sleep 5
|
|
330
|
+
done
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
# 主函数
|
|
334
|
+
main() {
|
|
335
|
+
local command="${1:-help}"
|
|
336
|
+
local task_list_path="${2:-}"
|
|
337
|
+
local task_id="${3:-}"
|
|
338
|
+
|
|
339
|
+
case "$command" in
|
|
340
|
+
acquire)
|
|
341
|
+
if [ -z "$task_list_path" ] || [ -z "$task_id" ]; then
|
|
342
|
+
echo "用法: $0 acquire <任务清单路径> <任务ID>" >&2
|
|
343
|
+
exit 1
|
|
344
|
+
fi
|
|
345
|
+
task_acquire "$task_list_path" "$task_id"
|
|
346
|
+
;;
|
|
347
|
+
complete)
|
|
348
|
+
if [ -z "$task_list_path" ] || [ -z "$task_id" ]; then
|
|
349
|
+
echo "用法: $0 complete <任务清单路径> <任务ID> [结果]" >&2
|
|
350
|
+
exit 1
|
|
351
|
+
fi
|
|
352
|
+
task_complete "$task_list_path" "$task_id" "${4:-成功}"
|
|
353
|
+
;;
|
|
354
|
+
fail)
|
|
355
|
+
if [ -z "$task_list_path" ] || [ -z "$task_id" ]; then
|
|
356
|
+
echo "用法: $0 fail <任务清单路径> <任务ID> <错误信息>" >&2
|
|
357
|
+
exit 1
|
|
358
|
+
fi
|
|
359
|
+
task_fail "$task_list_path" "$task_id" "$4"
|
|
360
|
+
;;
|
|
361
|
+
list)
|
|
362
|
+
if [ -z "$task_list_path" ]; then
|
|
363
|
+
echo "用法: $0 list <任务清单路径>" >&2
|
|
364
|
+
exit 1
|
|
365
|
+
fi
|
|
366
|
+
get_available_tasks "$task_list_path"
|
|
367
|
+
;;
|
|
368
|
+
parallel)
|
|
369
|
+
if [ -z "$task_list_path" ]; then
|
|
370
|
+
echo "用法: $0 parallel <任务清单路径> [最大并行数]" >&2
|
|
371
|
+
exit 1
|
|
372
|
+
fi
|
|
373
|
+
parallel_task_executor "$task_list_path" "${4:-3}"
|
|
374
|
+
;;
|
|
375
|
+
check-deps)
|
|
376
|
+
if [ -z "$task_list_path" ] || [ -z "$task_id" ]; then
|
|
377
|
+
echo "用法: $0 check-deps <任务清单路径> <任务ID>" >&2
|
|
378
|
+
exit 1
|
|
379
|
+
fi
|
|
380
|
+
check_task_dependencies "$task_list_path" "$task_id"
|
|
381
|
+
;;
|
|
382
|
+
*|help)
|
|
383
|
+
echo "跨平台任务管理器"
|
|
384
|
+
echo "用法: $0 <命令> [参数]"
|
|
385
|
+
echo ""
|
|
386
|
+
echo "命令:"
|
|
387
|
+
echo " acquire <清单路径> <任务ID> - 领取任务"
|
|
388
|
+
echo " complete <清单路径> <任务ID> [结果] - 标记任务完成"
|
|
389
|
+
echo " fail <清单路径> <任务ID> <错误> - 标记任务失败"
|
|
390
|
+
echo " list <清单路径> - 列出可用任务"
|
|
391
|
+
echo " parallel <清单路径> [并行数] - 并行执行任务"
|
|
392
|
+
echo " check-deps <清单路径> <任务ID> - 检查任务依赖"
|
|
393
|
+
echo " help - 显示帮助信息"
|
|
394
|
+
;;
|
|
395
|
+
esac
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
# 如果是直接执行而不是被 source,则运行主函数
|
|
399
|
+
if [ "${BASH_SOURCE[0]}" = "$0" ]; then
|
|
400
|
+
main "$@"
|
|
401
|
+
fi
|
package/templates/base.md
DELETED
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
description: Ensure what you implement Always Works™ with comprehensive testing
|
|
2
|
-
---
|
|
3
|
-
|
|
4
|
-
# How to ensure Always Works™ implementation
|
|
5
|
-
|
|
6
|
-
Please ensure your implementation Always Works™ for: $ARGUMENTS.
|
|
7
|
-
|
|
8
|
-
Follow this systematic approach:
|
|
9
|
-
|
|
10
|
-
## Core Philosophy
|
|
11
|
-
|
|
12
|
-
- "Should work" ≠ "does work" - Pattern matching isn't enough
|
|
13
|
-
- I'm not paid to write code, I'm paid to solve problems
|
|
14
|
-
- Untested code is just a guess, not a solution
|
|
15
|
-
|
|
16
|
-
# The 30-Second Reality Check - Must answer YES to ALL:
|
|
17
|
-
|
|
18
|
-
- Did I run/build the code?
|
|
19
|
-
- Did I trigger the exact feature I changed?
|
|
20
|
-
- Did I see the expected result with my own observation (including GUI)?
|
|
21
|
-
- Did I check for error messages?
|
|
22
|
-
|
|
23
|
-
# Phrases to Avoid:
|
|
24
|
-
|
|
25
|
-
- "This should work now"
|
|
26
|
-
- "I've fixed the issue" (especially 2nd+ time)
|
|
27
|
-
- "Try it now" (without trying it myself)
|
|
28
|
-
- "The logic is correct so..."
|
|
29
|
-
|
|
30
|
-
# Specific Test Requirements:
|
|
31
|
-
|
|
32
|
-
- UI Changes: Actually click the button/link/form
|
|
33
|
-
- API Changes: Make the actual API call
|
|
34
|
-
- Data Changes: Query the database
|
|
35
|
-
- Logic Changes: Run the specific scenario
|
|
36
|
-
- Config Changes: Restart and verify it loads
|
|
37
|
-
|
|
38
|
-
# The Embarrassment Test:
|
|
39
|
-
|
|
40
|
-
"If the user records trying this and it fails, will I feel embarrassed to see his face?"
|
|
41
|
-
|
|
42
|
-
# Time Reality:
|
|
43
|
-
|
|
44
|
-
- Time saved skipping tests: 30 seconds
|
|
45
|
-
- Time wasted when it doesn't work: 30 minutes
|
|
46
|
-
- User trust lost: Immeasurable
|
|
47
|
-
|
|
48
|
-
A user describing a bug for the third time isn't thinking "this AI is trying hard" - they're thinking "why am I wasting time with this incompetent tool?"
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|