aico-cli 0.3.16 → 0.3.20
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/simple-config.mjs +7 -11
- package/dist/cli.mjs +0 -11
- package/package.json +1 -1
- package/templates/agents/base/frontend-designer.md +193 -0
- package/templates/commands/base//344/272/247/345/223/201/350/256/276/350/256/241/346/231/272/350/203/275/344/275/223.md +1 -1
- package/templates/commands/git/cleanBranches.md +102 -0
- package/templates/commands/git/commit.md +93 -0
- package/templates/commands/git/rollback.md +90 -0
- package/templates/commands/git/worktree.md +276 -0
- package/templates/hooks/notify.ps1 +108 -0
- package/templates/hooks/pre-requirement-identifier.ps1 +160 -0
- package/templates/hooks/requirement/hook-utils.ps1 +365 -0
- package/templates/settings.json +53 -2
- package/templates/test-windows-compatibility.ps1 +476 -0
- package/templates/utils/platform-launcher.ps1 +333 -0
- package/templates/windows-bootstrap.ps1 +390 -0
- package/templates/commands/aico/workflow.md +0 -229
- package/templates/hooks/notify.log +0 -81
|
@@ -0,0 +1,333 @@
|
|
|
1
|
+
# AICO CLI 跨平台启动器 - PowerShell 版本
|
|
2
|
+
# 提供与 Bash 版本功能等价的跨平台脚本执行环境
|
|
3
|
+
|
|
4
|
+
param(
|
|
5
|
+
[Parameter(Mandatory=$true)]
|
|
6
|
+
[string]$ScriptType,
|
|
7
|
+
|
|
8
|
+
[Parameter(Mandatory=$false)]
|
|
9
|
+
[string[]]$Arguments = @()
|
|
10
|
+
)
|
|
11
|
+
|
|
12
|
+
# 全局配置
|
|
13
|
+
$AICO_TEMPLATES_DIR = Split-Path -Parent $PSScriptRoot
|
|
14
|
+
$AICO_HOOKS_DIR = Join-Path $AICO_TEMPLATES_DIR "hooks"
|
|
15
|
+
$AICO_AGENTS_DIR = Join-Path $AICO_TEMPLATES_DIR "agents"
|
|
16
|
+
$AICO_UTILS_DIR = Join-Path $AICO_TEMPLATES_DIR "utils"
|
|
17
|
+
|
|
18
|
+
# 日志函数
|
|
19
|
+
function Write-AicoLog {
|
|
20
|
+
param(
|
|
21
|
+
[string]$Level = "INFO",
|
|
22
|
+
[string]$Message,
|
|
23
|
+
[string]$LogFile = "$env:USERPROFILE\.claude\hooks\notify.log"
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
$timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
|
|
27
|
+
$logEntry = "[$Level] $timestamp - $Message"
|
|
28
|
+
|
|
29
|
+
# 控制台输出
|
|
30
|
+
switch ($Level) {
|
|
31
|
+
"ERROR" { Write-Host $logEntry -ForegroundColor Red }
|
|
32
|
+
"WARN" { Write-Host $logEntry -ForegroundColor Yellow }
|
|
33
|
+
"INFO" { Write-Host $logEntry -ForegroundColor Green }
|
|
34
|
+
"DEBUG" { Write-Host $logEntry -ForegroundColor Gray }
|
|
35
|
+
default { Write-Host $logEntry }
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
# 文件日志
|
|
39
|
+
try {
|
|
40
|
+
$logDir = Split-Path -Parent $LogFile
|
|
41
|
+
if (!(Test-Path $logDir)) {
|
|
42
|
+
New-Item -ItemType Directory -Path $logDir -Force | Out-Null
|
|
43
|
+
}
|
|
44
|
+
Add-Content -Path $LogFile -Value $logEntry -Force
|
|
45
|
+
} catch {
|
|
46
|
+
Write-Debug "无法写入日志文件: $_.Exception.Message"
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
# 平台检测函数
|
|
51
|
+
function Get-PlatformInfo {
|
|
52
|
+
$os = [System.Environment]::OSVersion
|
|
53
|
+
$isWindows = $os.Platform -eq "Win32NT"
|
|
54
|
+
$is64Bit = [System.Environment]::Is64BitOperatingSystem
|
|
55
|
+
|
|
56
|
+
if ($isWindows) {
|
|
57
|
+
$winVersion = Get-CimInstance -ClassName Win32_OperatingSystem | Select-Object -ExpandProperty Caption
|
|
58
|
+
return @{
|
|
59
|
+
Platform = "windows"
|
|
60
|
+
Version = $winVersion
|
|
61
|
+
Is64Bit = $is64Bit
|
|
62
|
+
IsWSL = $false
|
|
63
|
+
TempDir = $env:TEMP
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
# WSL 检测
|
|
68
|
+
if (Test-Path "/proc/version") {
|
|
69
|
+
$wslCheck = Get-Content "/proc/version" -ErrorAction SilentlyContinue
|
|
70
|
+
if ($wslCheck -match "Microsoft") {
|
|
71
|
+
return @{
|
|
72
|
+
Platform = "wsl"
|
|
73
|
+
Version = "WSL"
|
|
74
|
+
Is64Bit = $is64Bit
|
|
75
|
+
IsWSL = $true
|
|
76
|
+
TempDir = "/tmp"
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
return @{
|
|
82
|
+
Platform = "unknown"
|
|
83
|
+
Version = $os.VersionString
|
|
84
|
+
Is64Bit = $is64Bit
|
|
85
|
+
IsWSL = $false
|
|
86
|
+
TempDir = "/tmp"
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
# 音频播放函数 - Windows 专用
|
|
91
|
+
function Play-SoundFile {
|
|
92
|
+
param(
|
|
93
|
+
[string]$SoundFile
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
if (!(Test-Path $SoundFile)) {
|
|
97
|
+
Write-AicoLog -Level "WARN" -Message "音频文件不存在: $SoundFile"
|
|
98
|
+
return $false
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
try {
|
|
102
|
+
# Windows Media Player COM 对象
|
|
103
|
+
$player = New-Object -ComObject WMPlayer.OCX.7
|
|
104
|
+
$player.URL = $SoundFile
|
|
105
|
+
$player.controls.play()
|
|
106
|
+
|
|
107
|
+
# 等待播放完成(约1秒)
|
|
108
|
+
Start-Sleep -Milliseconds 1000
|
|
109
|
+
$player.close()
|
|
110
|
+
|
|
111
|
+
Write-AicoLog -Level "INFO" -Message "音频播放成功: $SoundFile"
|
|
112
|
+
return $true
|
|
113
|
+
}
|
|
114
|
+
catch {
|
|
115
|
+
# 备用方案:使用 .NET System.Media
|
|
116
|
+
try {
|
|
117
|
+
$soundPlayer = New-Object System.Media.SoundPlayer($SoundFile)
|
|
118
|
+
$soundPlayer.PlaySync()
|
|
119
|
+
Write-AicoLog -Level "INFO" -Message "音频播放成功(.NET): $SoundFile"
|
|
120
|
+
return $true
|
|
121
|
+
}
|
|
122
|
+
catch {
|
|
123
|
+
Write-AicoLog -Level "ERROR" -Message "音频播放失败: $_.Exception.Message"
|
|
124
|
+
return $false
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
# 通知系统函数
|
|
130
|
+
function Invoke-AicoNotification {
|
|
131
|
+
param(
|
|
132
|
+
[Parameter(Mandatory=$true)]
|
|
133
|
+
[ValidateSet("input", "complete", "error", "warning")]
|
|
134
|
+
[string]$Type,
|
|
135
|
+
|
|
136
|
+
[string]$Message = ""
|
|
137
|
+
)
|
|
138
|
+
|
|
139
|
+
Write-AicoLog -Level "INFO" -Message "通知触发: Type=$Type, Message=$Message"
|
|
140
|
+
|
|
141
|
+
# 音頻文件路徑
|
|
142
|
+
$soundsDir = Join-Path $AICO_HOOKS_DIR "sounds"
|
|
143
|
+
|
|
144
|
+
switch ($Type) {
|
|
145
|
+
"input" {
|
|
146
|
+
$soundFile = Join-Path $soundsDir "input-needed.wav"
|
|
147
|
+
Play-SoundFile -SoundFile $soundFile
|
|
148
|
+
|
|
149
|
+
# Windows 通知气泡
|
|
150
|
+
try {
|
|
151
|
+
Add-Type -AssemblyName System.Windows.Forms
|
|
152
|
+
$notify = New-Object System.Windows.Forms.NotifyIcon
|
|
153
|
+
$notify.Icon = [System.Drawing.SystemIcons]::Information
|
|
154
|
+
$notify.Visible = $true
|
|
155
|
+
$notify.ShowBalloonTip(3000, "Claude Code", "需要您的输入", [System.Windows.Forms.ToolTipIcon]::Info)
|
|
156
|
+
$notify.Dispose()
|
|
157
|
+
}
|
|
158
|
+
catch {
|
|
159
|
+
Write-Debug "系统通知失败: $_.Exception.Message"
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
"complete" {
|
|
164
|
+
$soundFile = Join-Path $soundsDir "complete.wav"
|
|
165
|
+
Play-SoundFile -SoundFile $soundFile
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
"error" {
|
|
169
|
+
# 错误提示音
|
|
170
|
+
[Console]::Beep(500, 300)
|
|
171
|
+
Write-Error $Message
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
"warning" {
|
|
175
|
+
# 警告提示音
|
|
176
|
+
[Console]::Beep(800, 200)
|
|
177
|
+
Write-Warning $Message
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
# 任务管理函数
|
|
183
|
+
function Invoke-TaskManager {
|
|
184
|
+
param(
|
|
185
|
+
[Parameter(Mandatory=$true)]
|
|
186
|
+
[ValidateSet("acquire", "complete", "fail", "list", "parallel", "check-deps")]
|
|
187
|
+
[string]$Command,
|
|
188
|
+
|
|
189
|
+
[string]$TaskListPath = "",
|
|
190
|
+
[string]$TaskId = "",
|
|
191
|
+
[string]$Result = "成功",
|
|
192
|
+
[string]$ErrorMessage = "",
|
|
193
|
+
[int]$MaxParallel = 3
|
|
194
|
+
)
|
|
195
|
+
|
|
196
|
+
switch ($Command) {
|
|
197
|
+
"acquire" {
|
|
198
|
+
if ([string]::IsNullOrEmpty($TaskListPath) -or [string]::IsNullOrEmpty($TaskId)) {
|
|
199
|
+
Write-AicoLog -Level "ERROR" -Message "任务领取需要 TaskListPath 和 TaskId 参数"
|
|
200
|
+
return $false
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
# 实现任务领取逻辑
|
|
204
|
+
$taskContent = Get-Content $TaskListPath -Raw -ErrorAction SilentlyContinue
|
|
205
|
+
if ($taskContent -match $TaskId) {
|
|
206
|
+
Write-AicoLog -Level "INFO" -Message "任务领取成功: $TaskId"
|
|
207
|
+
return $true
|
|
208
|
+
} else {
|
|
209
|
+
Write-AicoLog -Level "WARN" -Message "任务不存在: $TaskId"
|
|
210
|
+
return $false
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
"complete" {
|
|
215
|
+
Write-AicoLog -Level "INFO" -Message "任务完成: $TaskId, 结果: $Result"
|
|
216
|
+
return $true
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
"fail" {
|
|
220
|
+
Write-AicoLog -Level "ERROR" -Message "任务失败: $TaskId, 错误: $ErrorMessage"
|
|
221
|
+
return $false
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
"list" {
|
|
225
|
+
if ([string]::IsNullOrEmpty($TaskListPath)) {
|
|
226
|
+
Write-AicoLog -Level "ERROR" -Message "任务列表需要 TaskListPath 参数"
|
|
227
|
+
return @()
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
$availableTasks = @()
|
|
231
|
+
# 解析任务列表,返回可用任务
|
|
232
|
+
Write-AicoLog -Level "INFO" -Message "获取可用任务列表: $TaskListPath"
|
|
233
|
+
return $availableTasks
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
"parallel" {
|
|
237
|
+
Write-AicoLog -Level "INFO" -Message "开始并行任务执行 (最大并行数: $MaxParallel)"
|
|
238
|
+
# 实现并行执行逻辑
|
|
239
|
+
return $true
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
"check-deps" {
|
|
243
|
+
Write-AicoLog -Level "INFO" -Message "检查任务依赖: $TaskId"
|
|
244
|
+
return $true
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
# Hook 执行函数
|
|
250
|
+
function Invoke-AicoHook {
|
|
251
|
+
param(
|
|
252
|
+
[Parameter(Mandatory=$true)]
|
|
253
|
+
[ValidateSet("pre", "post")]
|
|
254
|
+
[string]$Type,
|
|
255
|
+
|
|
256
|
+
[Parameter(Mandatory=$true)]
|
|
257
|
+
[string]$HookName,
|
|
258
|
+
|
|
259
|
+
[string[]]$Arguments = @()
|
|
260
|
+
)
|
|
261
|
+
|
|
262
|
+
$hookScript = "$Type-$HookName.ps1"
|
|
263
|
+
$hookPath = Join-Path $AICO_HOOKS_DIR $hookScript
|
|
264
|
+
|
|
265
|
+
if (Test-Path $hookPath) {
|
|
266
|
+
Write-AicoLog -Level "INFO" -Message "执行 $Type Hook: $HookName"
|
|
267
|
+
try {
|
|
268
|
+
& $hookPath @Arguments
|
|
269
|
+
Write-AicoLog -Level "INFO" -Message "Hook $HookName $Type 执行成功"
|
|
270
|
+
return $true
|
|
271
|
+
}
|
|
272
|
+
catch {
|
|
273
|
+
Write-AicoLog -Level "ERROR" -Message "Hook $HookName $Type 执行失败: $_.Exception.Message"
|
|
274
|
+
return $false
|
|
275
|
+
}
|
|
276
|
+
} else {
|
|
277
|
+
Write-AicoLog -Level "DEBUG" -Message "Hook 脚本不存在: $hookPath"
|
|
278
|
+
return $true # 不存在的 Hook 视为成功
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
# 主函数
|
|
283
|
+
function Main {
|
|
284
|
+
param(
|
|
285
|
+
[string]$ScriptType,
|
|
286
|
+
[string[]]$Arguments
|
|
287
|
+
)
|
|
288
|
+
|
|
289
|
+
Write-AicoLog -Level "INFO" -Message "AICO Platform Launcher 启动: ScriptType=$ScriptType"
|
|
290
|
+
|
|
291
|
+
# 平台信息
|
|
292
|
+
$platform = Get-PlatformInfo
|
|
293
|
+
Write-AicoLog -Level "DEBUG" -Message "平台信息: $($platform | ConvertTo-Json -Compress)"
|
|
294
|
+
|
|
295
|
+
switch ($ScriptType.ToLower()) {
|
|
296
|
+
"notify" {
|
|
297
|
+
$notificationType = $Arguments[0]
|
|
298
|
+
Invoke-AicoNotification -Type $notificationType
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
"task-manager" {
|
|
302
|
+
$command = $Arguments[0]
|
|
303
|
+
$taskListPath = $Arguments[1]
|
|
304
|
+
$taskId = $Arguments[2]
|
|
305
|
+
|
|
306
|
+
Invoke-TaskManager -Command $command -TaskListPath $taskListPath -TaskId $taskId
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
"hook" {
|
|
310
|
+
$hookType = $Arguments[0]
|
|
311
|
+
$hookName = $Arguments[1]
|
|
312
|
+
$hookArgs = $Arguments[2..($Arguments.Length-1)]
|
|
313
|
+
|
|
314
|
+
Invoke-AicoHook -Type $hookType -HookName $hookName -Arguments $hookArgs
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
"platform-info" {
|
|
318
|
+
$platform | ConvertTo-Json -Depth 3
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
default {
|
|
322
|
+
Write-AicoLog -Level "ERROR" -Message "未知的脚本类型: $ScriptType"
|
|
323
|
+
Write-Host "用法:"
|
|
324
|
+
Write-Host " platform-launcher.ps1 notify [input|complete|error|warning]"
|
|
325
|
+
Write-Host " platform-launcher.ps1 task-manager [command] [参数...]"
|
|
326
|
+
Write-Host " platform-launcher.ps1 hook [pre|post] [hook-name] [参数...]"
|
|
327
|
+
Write-Host " platform-launcher.ps1 platform-info"
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
# 执行主函数
|
|
333
|
+
Main -ScriptType $ScriptType -Arguments $Arguments
|