Skill Detection CLI
通过已安装的 SkillDetectionClient.exe 做技能包检测。
exe 是 --windowed 窗口程序:Agent Shell 里 没有 stdout 摘要,不要读终端里的 ok: / type: / message:。
- 成败:只看 exe 的真实进程退出码(见第 3 步;禁止用
&直接调用后读 Shell Exit code) - 错误码:一旦不是 0,立刻先告知用户检测未通过(含退出码含义),再去读日志
- type / message:只从
%LOCALAPPDATA%\SkillDetectionClient\SkillDetectionClient.log读本次末尾一段
Agent 的 Shell 就是 PowerShell。执行必须用 PowerShell 调用 exe 的绝对路径。 禁止 cmd.exe /c,禁止走 SkillDetectionClient.cmd。
硬性规则
先检查安装目录。如果检查没有安装程序,直接告诉用户没有安装。如果安装了,使用绝对路径执行命令行。
禁止:用仓库里的 python app.py、dist\ 便携目录、相对路径、或未确认存在的路径凑合执行。未安装时禁止继续搜索全盘。
1. 检查安装目录
找到 SkillDetectionClient.exe 文件存在 即视为已安装:
- %ProgramFiles%\SkillDetectionClient\SkillDetectionClient.exe($env:ProgramFiles,常见为 C:\Program Files)
- D:\Program Files\SkillDetectionClient\SkillDetectionClient.exe(客户改装到 D 盘时用;只测这一条路径,禁止遍历 D 盘)
- 卸载项注册表 InstallLocation(慢,仅 1、2 都没有时才读)
键:HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall{8F3B9C42-6D2E-4A1B-9E77-3C1A2B4D5E6F}_is1
(若无再试 HKLM\SOFTWARE\WOW6432Node... 同名键)
$exe = Join-Path $env:ProgramFiles "SkillDetectionClient\SkillDetectionClient.exe"
if (-not (Test-Path -LiteralPath $exe)) {
$key = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{8F3B9C42-6D2E-4A1B-9E77-3C1A2B4D5E6F}_is1"
$inst = (Get-ItemProperty -Path $key -ErrorAction SilentlyContinue).InstallLocation
if ($inst) { $exe = Join-Path $inst.TrimEnd("\") "SkillDetectionClient.exe" }
}
Test-Path -LiteralPath $exe
未找到 exe: 立即停止,原样告诉用户:
未安装 Skill Detection 客户端。请先运行安装包完成安装后再试。
不要补充替代运行方式。
2. 准备参数
向用户确认(或从当前对话取已给出的绝对路径):
| 参数 | 必填 | 说明 |
|---|---|---|
--zip |
是 | 技能包 zip,必须是已存在的文件 |
--input |
是 | 至少一个输入文件,必须已存在;多个则全部列出 |
--clean |
否 | 仅当用户明确要求清理 workspace 时才加 |
缺 zip 或输入文件时先问,不要开跑。路径一律先解析成绝对路径。
3. 用 PowerShell 捕获真实退出码并执行
SkillDetectionClient.exe 是 windowed 程序。用 PowerShell & 直接调用时,不会回传 exe 的真实退出码:
- Shell 工具常显示 Exit code 0(仅表示「进程已启动并结束」)
$LASTEXITCODE为空- 这与检测是否通过无关,不能据此判定成败
必须用 Start-Process -Wait -PassThru 等待进程结束,再 exit $p.ExitCode 把真实退出码交给 Shell 工具。整条命令只含启动与 exit 两行,中间不要插入 Write-Output 等语句。
单个输入:
$p = Start-Process -FilePath "<exe绝对路径>" -ArgumentList @('--zip','<zip绝对路径>','--input','<文件1>') -Wait -PassThru -NoNewWindow
exit $p.ExitCode
多个输入(--input 后跟的所有文件都写在同一个 @(...) 里):
$p = Start-Process -FilePath "<exe绝对路径>" -ArgumentList @('--zip','<zip绝对路径>','--input','<文件1>','<文件2>') -Wait -PassThru -NoNewWindow
exit $p.ExitCode
示例:
$p = Start-Process -FilePath "D:\Program Files\SkillDetectionClient\SkillDetectionClient.exe" -ArgumentList @('--zip','D:\abs\pack.zip','--input','D:\abs\a.xlsx','D:\abs\b.xlsx') -Wait -PassThru -NoNewWindow
exit $p.ExitCode
- exe 用第 1 步确认存在的绝对路径(必须带
.exe);-ArgumentList里每个路径单独一项,含空格的路径照常写字符串即可。 - 检测子进程超时约 600 秒,Shell 的
block_until_ms至少660000。 - 默认不加
--clean(会清空整个workspace\)。 - 只认
exit $p.ExitCode后 Shell 工具返回的 Exit code(即$p.ExitCode)。禁止用&后直接读 Shell Exit code,禁止用$LASTEXITCODE,不要解析 stdout。
4. 退出码:立刻判定成败
| 退出码 | 含义 |
|---|---|
| 0 | 检测通过 |
| 1 | 路径不存在、检测失败或执行异常 |
| 2 | 缺 --zip/--input 或参数用法错误 |
Exit code 不是 0: 立刻先告知用户检测未通过,并说明退出码含义。不要等读完日志再决定成败,也不要先去翻日志才开口。
然后再执行第 5 步补 type / message。Exit code 为 0 时同样进入第 5 步。
5. 从日志读取 type、message
读:
%LOCALAPPDATA%\SkillDetectionClient\SkillDetectionClient.log
只看本次检测末尾一段(最新一次 zip: 起到文件末尾)。不要读安装目录下的 log,不要改去调 .cmd。
从该段取出:
type: py/type: macro/type: unknown- 结果描述作为 message(如
检测通过:output 有产出、检测失败,output目录为空或不存在,或缺少必要脚本:/无法识别技能类型等行)
type 必须改成中文再告诉用户(不要原样报 py / macro):
| 日志 type | 对用户说 |
|---|---|
py |
py技能包 |
macro |
宏技能包 |
| 其他 | 未知技能包 |
回复用户时包含:是否通过(来自退出码)、类型(中文)、message、退出码。不要只说「已执行」。第 5 步只为取出 type / message 读一次尾部。
失败原因分析(未通过时)
「失败原因」可直接用本段 message(如 检测失败,output目录为空或不存在)。
「失败原因分析」直接放日志文件的链接,不要再去读 log 日志进行分析。
- 把
%LOCALAPPDATA%展开为绝对路径,用 Markdown 链接填入表格(便于用户点击打开):
[SkillDetectionClient.log](<日志绝对路径>) - 日志绝对路径固定为:
%LOCALAPPDATA%\SkillDetectionClient\SkillDetectionClient.log(展开后,例如C:\Users\15963\AppData\Local\SkillDetectionClient\SkillDetectionClient.log) - 禁止再读日志、归纳 ERROR 根因、询问是否深入分析、或把日志摘要写进该格
通过时:「失败原因」「失败原因分析」均填「无」。
不要做
- 未通过安装检查就执行
- 用
& "...\SkillDetectionClient.exe" ...直接调用后把 Shell Exit code 0 当成检测通过(windowed 程序不会回传真实退出码) - 用
cmd.exe /c或SkillDetectionClient.cmd - 打开 GUI(无
--zip会弹窗口) - 从 stdout 解析
ok:/type:/message: - 用
$LASTEXITCODE或日志来判定成败 - 为「失败原因分析」再读日志、归纳 ERROR 根因,或询问是否深入分析
- CLI 上传 FAIW / 登录
- 把本次检测改成改客户端源码
- 直接阅读SKILL.md和压缩包中的脚本,手动运行脚本检测
输出模板
检测完成后,严格按照以下模板格式向用户展示结果,不要输出额外的内容:
技能包检测结果
| 项目 | 内容 |
|---|---|
| 是否通过 | ✅ 通过 / ❌ 未通过 |
| 退出码 | {退出码}({退出码含义}) |
| 技能包类型 | {中文类型}({类型说明}) |
| 失败原因 | {具体失败原因(日志 message),通过时显示"无"} |
| 失败原因分析 | {日志文件的 Markdown 链接;通过时显示"无"} |
使用说明:
- 是否通过:使用 ✅ 表示通过(退出码为0),使用 ❌ 表示未通过(退出码非0)
- 退出码:显示实际退出码及其含义(参照第4步退出码说明)
- 技能包类型:显示中文类型名称,并在括号中提供类型说明
- 失败原因:显示日志 message 中的失败描述,通过时显示"无"
- 失败原因分析:未通过时直接放日志文件的链接,不要再去读 log 日志进行分析;通过时显示"无"
示例输出:
### 技能包检测结果
| 项目 | 内容 |
|------|------|
| 是否通过 | ❌ 未通过 |
| 退出码 | 1(检测失败或执行异常) |
| 技能包类型 | py技能包(Python 脚本技能包) |
| 失败原因 | 检测失败,output 目录为空或不存在 |
| 失败原因分析 | [SkillDetectionClient.log](C:\Users\temp\AppData\Local\SkillDetectionClient\SkillDetectionClient.log) |