@pwddd/skills-scanner 1.0.5 → 1.1.0
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.
Potentially problematic release.
This version of @pwddd/skills-scanner might be problematic. Click here for more details.
- package/index.ts +71 -32
- package/package.json +1 -1
package/index.ts
CHANGED
|
@@ -73,7 +73,15 @@ function hasUv(): boolean {
|
|
|
73
73
|
}
|
|
74
74
|
|
|
75
75
|
function isVenvReady(): boolean {
|
|
76
|
-
|
|
76
|
+
if (!existsSync(VENV_PYTHON)) return false;
|
|
77
|
+
|
|
78
|
+
// 检查 cisco-ai-skill-scanner 是否真的安装
|
|
79
|
+
try {
|
|
80
|
+
execSync(`"${VENV_PYTHON}" -c "import skill_scanner"`, { stdio: 'ignore' });
|
|
81
|
+
return true;
|
|
82
|
+
} catch {
|
|
83
|
+
return false;
|
|
84
|
+
}
|
|
77
85
|
}
|
|
78
86
|
|
|
79
87
|
function expandPath(p: string): string {
|
|
@@ -106,24 +114,39 @@ function saveState(s: ScanState) {
|
|
|
106
114
|
|
|
107
115
|
async function ensureDeps(logger: any): Promise<boolean> {
|
|
108
116
|
if (isVenvReady()) {
|
|
109
|
-
logger.info("[skills-scanner] Python
|
|
117
|
+
logger.info("[skills-scanner] Python 依赖已就绪(cisco-ai-skill-scanner 已安装)");
|
|
110
118
|
return true;
|
|
111
119
|
}
|
|
120
|
+
|
|
112
121
|
if (!hasUv()) {
|
|
113
122
|
logger.warn("[skills-scanner] uv 未安装:brew install uv 或 curl -LsSf https://astral.sh/uv/install.sh | sh");
|
|
114
123
|
return false;
|
|
115
124
|
}
|
|
116
|
-
|
|
125
|
+
|
|
126
|
+
logger.info("[skills-scanner] 正在安装 cisco-ai-skill-scanner...");
|
|
127
|
+
|
|
117
128
|
try {
|
|
118
|
-
// 创建 venv
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
129
|
+
// 创建 venv(如果不存在)
|
|
130
|
+
if (!existsSync(VENV_PYTHON)) {
|
|
131
|
+
logger.info("[skills-scanner] 创建 Python 虚拟环境...");
|
|
132
|
+
await execAsync(`uv venv "${join(SKILL_DIR, ".venv")}" --python 3.10`);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// 安装包
|
|
136
|
+
logger.info("[skills-scanner] 安装 cisco-ai-skill-scanner 包...");
|
|
137
|
+
await execAsync(`uv pip install --python "${VENV_PYTHON}" cisco-ai-skill-scanner`);
|
|
138
|
+
|
|
139
|
+
// 验证安装
|
|
140
|
+
if (isVenvReady()) {
|
|
141
|
+
logger.info("[skills-scanner] ✅ 依赖安装完成并验证成功");
|
|
142
|
+
return true;
|
|
143
|
+
} else {
|
|
144
|
+
logger.error("[skills-scanner] ❌ 安装完成但验证失败,包可能未正确安装");
|
|
145
|
+
return false;
|
|
146
|
+
}
|
|
124
147
|
} catch (err: any) {
|
|
125
148
|
logger.error(`[skills-scanner] ⚠️ 依赖安装失败: ${err.message}`);
|
|
126
|
-
logger.error(`[skills-scanner] 请手动运行: uv pip install cisco-ai-skill-scanner`);
|
|
149
|
+
logger.error(`[skills-scanner] 请手动运行: uv pip install --python "${VENV_PYTHON}" cisco-ai-skill-scanner`);
|
|
127
150
|
return false;
|
|
128
151
|
}
|
|
129
152
|
}
|
|
@@ -304,11 +327,25 @@ export default function register(api: any) {
|
|
|
304
327
|
const preInstallScan = cfg.preInstallScan ?? "on";
|
|
305
328
|
const onUnsafe = cfg.onUnsafe ?? "quarantine";
|
|
306
329
|
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
330
|
+
api.logger.info("[skills-scanner] ═══════════════════════════════════════");
|
|
331
|
+
api.logger.info("[skills-scanner] Plugin 正在加载...");
|
|
332
|
+
api.logger.info(`[skills-scanner] 扫描目录: ${scanDirs.join(", ")}`);
|
|
333
|
+
api.logger.info(`[skills-scanner] Python venv 路径: ${VENV_PYTHON}`);
|
|
334
|
+
api.logger.info(`[skills-scanner] Python 依赖状态: ${isVenvReady() ? "✅ 已就绪" : "❌ 未安装"}`);
|
|
335
|
+
|
|
336
|
+
// 立即尝试安装依赖(不等待 service start)
|
|
337
|
+
if (!isVenvReady()) {
|
|
338
|
+
api.logger.info("[skills-scanner] 开始安装 Python 依赖...");
|
|
339
|
+
ensureDeps(api.logger).then(success => {
|
|
340
|
+
if (success) {
|
|
341
|
+
api.logger.info("[skills-scanner] ✅ 依赖安装成功(在 plugin 加载时)");
|
|
342
|
+
}
|
|
343
|
+
}).catch(err => {
|
|
344
|
+
api.logger.error(`[skills-scanner] 依赖安装失败: ${err.message}`);
|
|
345
|
+
});
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
// 向聊天发消息的辅助(用于 watcher 通知)
|
|
312
349
|
function persistWatcherAlert(msg: string) {
|
|
313
350
|
const state = loadState();
|
|
314
351
|
const alerts: string[] = (state as any).pendingAlerts ?? [];
|
|
@@ -323,40 +360,42 @@ export default function register(api: any) {
|
|
|
323
360
|
api.registerService({
|
|
324
361
|
id: "skills-scanner-setup",
|
|
325
362
|
start: async () => {
|
|
326
|
-
api.logger.info("[skills-scanner]
|
|
363
|
+
api.logger.info("[skills-scanner] ─────────────────────────────────────");
|
|
364
|
+
api.logger.info("[skills-scanner] 🚀 后台服务启动中...");
|
|
365
|
+
|
|
366
|
+
// 再次检查并安装依赖(防止 plugin 加载时安装失败)
|
|
327
367
|
const depsReady = await ensureDeps(api.logger);
|
|
328
368
|
|
|
329
369
|
if (!depsReady) {
|
|
330
370
|
api.logger.error("[skills-scanner] ❌ 依赖安装失败,服务无法启动");
|
|
371
|
+
api.logger.error("[skills-scanner] 请手动运行: uv pip install --python \"" + VENV_PYTHON + "\" cisco-ai-skill-scanner");
|
|
331
372
|
return;
|
|
332
373
|
}
|
|
333
374
|
|
|
334
375
|
if (preInstallScan === "on" && scanDirs.length > 0) {
|
|
376
|
+
api.logger.info(`[skills-scanner] 📁 启动文件监控: ${scanDirs.length} 个目录`);
|
|
335
377
|
stopWatcher = startWatcher(scanDirs, onUnsafe, behavioral, persistWatcherAlert, api.logger);
|
|
378
|
+
api.logger.info("[skills-scanner] ✅ 文件监控已启动");
|
|
379
|
+
} else {
|
|
380
|
+
api.logger.info("[skills-scanner] ⏭️ 安装前扫描已禁用");
|
|
336
381
|
}
|
|
382
|
+
|
|
383
|
+
api.logger.info("[skills-scanner] ─────────────────────────────────────");
|
|
384
|
+
},
|
|
385
|
+
stop: () => {
|
|
386
|
+
api.logger.info("[skills-scanner] 🛑 后台服务停止中...");
|
|
387
|
+
stopWatcher?.();
|
|
388
|
+
stopWatcher = null;
|
|
337
389
|
},
|
|
338
|
-
stop: () => { stopWatcher?.(); stopWatcher = null; },
|
|
339
390
|
});
|
|
340
391
|
|
|
341
|
-
// ── 2.
|
|
342
|
-
// 在 Gateway 启动时输出配置提示
|
|
343
|
-
api.logger.info("[skills-scanner] Plugin 已加载");
|
|
344
|
-
api.logger.info(`[skills-scanner] 安装前扫描:${preInstallScan === "on" ? `✅ 监听 ${scanDirs.length} 个目录` : "❌ 已禁用"}`);
|
|
345
|
-
|
|
346
|
-
// 立即检查并安装依赖(不等待 service start)
|
|
347
|
-
if (!isVenvReady()) {
|
|
348
|
-
api.logger.info("[skills-scanner] 检测到 Python 依赖未安装,开始安装...");
|
|
349
|
-
ensureDeps(api.logger).catch(err => {
|
|
350
|
-
api.logger.error(`[skills-scanner] 依赖安装异常: ${err.message}`);
|
|
351
|
-
});
|
|
352
|
-
}
|
|
353
|
-
|
|
354
|
-
// 检查是否需要注册 Cron Job
|
|
392
|
+
// ── 2. 启动日志和 Cron 提示 ───────────────────────────────────────────────
|
|
355
393
|
const state = loadState() as any;
|
|
356
394
|
if (!state.cronJobId) {
|
|
357
395
|
api.logger.warn("[skills-scanner] ⚠️ 未检测到日报 Cron Job,请手动注册一次:");
|
|
358
396
|
api.logger.info('[skills-scanner] openclaw cron add --name "skills-daily-report" --cron "0 8 * * *" --tz "Asia/Shanghai" --session isolated --message "请执行 /scan-report 并把结果发送到此渠道" --announce');
|
|
359
397
|
}
|
|
398
|
+
api.logger.info("[skills-scanner] ═══════════════════════════════════════");
|
|
360
399
|
|
|
361
400
|
// ── 3. /scan-skill ────────────────────────────────────────────────────────
|
|
362
401
|
api.registerCommand({
|
|
@@ -508,5 +547,5 @@ export default function register(api: any) {
|
|
|
508
547
|
});
|
|
509
548
|
}, { commands: ["skills-scan"] });
|
|
510
549
|
|
|
511
|
-
api.logger.info("[skills-scanner] Plugin
|
|
550
|
+
api.logger.info("[skills-scanner] ✅ Plugin 注册完成");
|
|
512
551
|
}
|