@pwddd/skills-scanner 1.0.0-beta.2 → 1.0.0-beta.22

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/README.md CHANGED
@@ -1,255 +1,4 @@
1
- # Skills Scanner Plugin
2
-
3
- OpenClaw Skills 安全扫描插件,用于检测 Skills 中的潜在安全威胁。
4
-
5
- ## 功能特性
6
-
7
- - 🔍 **自动扫描**: 监听 Skills 目录,自动扫描新安装的 Skill
8
- - 🛡️ **安装前拦截**: 使用 before_install hook 在安装前强制拦截不安全的 Skills
9
- - 🌐 **ClawHub 扫描**: 直接扫描 ClawHub 上的 Skill,无需手动下载
10
- - 📊 **定时周报**: 每周一自动生成安全扫描报告
11
- - 🛡️ **多种策略**: 支持 strict/balanced/permissive 三种扫描策略
12
- - 🤖 **LLM 分析**: 可选的 LLM 语义分析
13
- - 🔒 **自动隔离**: 检测到不安全的 Skill 自动隔离或删除
14
-
15
- ## 安装
16
-
17
- ```bash
18
- # 从本地安装(开发)
19
- openclaw plugins install ./skills-scanner
20
-
21
- # 从 npm 安装(发布后)
22
- openclaw plugins install @pwddd/skills-scanner
23
- ```
24
-
25
- ## 配置
26
-
27
- 在 `~/.openclaw/openclaw.json` 或工作区配置中添加:
28
-
29
- ```json
30
- {
31
- "plugins": {
32
- "entries": {
33
- "skills-scanner": {
34
- "enabled": true,
35
- "config": {
36
- "apiUrl": "https://110.vemic.com/skills-scanner",
37
- "scanDirs": ["~/.openclaw/skills", "~/.openclaw/workspace/skills"],
38
- "behavioral": false,
39
- "useLLM": false,
40
- "policy": "balanced",
41
- "preInstallScan": "on",
42
- "onUnsafe": "warn",
43
- "enableBeforeInstallHook": true
44
- }
45
- }
46
- }
47
- }
48
- }
49
- ```
50
-
51
- ### 配置说明
52
-
53
- - `apiUrl`: 扫描 API 服务地址
54
- - `scanDirs`: 要监控的 Skills 目录列表
55
- - `behavioral`: 是否启用行为分析(深度扫描,较慢)
56
- - `useLLM`: 是否使用 LLM 进行语义分析
57
- - `policy`: 扫描策略
58
- - `strict`: 严格模式,发现任何可疑行为都标记为不安全
59
- - `balanced`: 平衡模式(推荐)
60
- - `permissive`: 宽松模式,只标记明确的威胁
61
- - `preInstallScan`: 是否启用文件监控(安装后扫描)
62
- - `on`: 启用
63
- - `off`: 禁用
64
- - `onUnsafe`: 发现不安全 Skill 的处理方式
65
- - `warn`: 仅警告,不处理(推荐)
66
- - `quarantine`: 移入隔离目录
67
- - `delete`: 直接删除
68
- - `enableBeforeInstallHook`: 是否启用 before_install hook(安装前拦截)
69
- - `true`: 启用(强烈推荐)
70
- - `false`: 禁用
71
- - `scanTimeoutMs`: 扫描超时时间(毫秒),默认 180000 (3分钟)
72
- - `reportDir`: 自定义报告目录
73
- - `quarantineDir`: 自定义隔离目录
74
-
75
- ### 高级功能
76
-
77
- #### 配置热重载
78
-
79
- 插件支持配置热重载,修改配置后无需重启 Gateway:
80
-
81
- ```bash
82
- # 修改配置文件
83
- vim ~/.openclaw/config.json
84
-
85
- # 重载配置
86
- openclaw config reload
87
- ```
88
-
89
- 配置变更会自动:
90
- - 更新 API URL
91
- - 重启文件监控器(如果扫描目录变更)
92
- - 应用新的扫描策略
93
-
94
- #### 调试模式
95
-
96
- 启用调试模式可以查看详细的运行日志:
97
-
98
- ```bash
99
- # 启用调试模式
100
- export SKILLS_SCANNER_DEBUG=1
101
- openclaw gateway start
102
-
103
- # 或者一次性启用
104
- SKILLS_SCANNER_DEBUG=1 openclaw gateway start
105
- ```
106
-
107
- 调试模式会输出:
108
- - 完整的配置信息
109
- - 详细的扫描过程
110
- - API 请求和响应
111
- - 文件监控事件
112
-
113
- #### 健康检查端点
114
-
115
- 插件提供 HTTP 健康检查端点:
116
-
117
- ```bash
118
- # 通过 HTTP 访问
119
- curl http://localhost:3000/health/skills-scanner
120
-
121
- # 返回示例
122
- {
123
- "status": "healthy",
124
- "plugin": {
125
- "version": "1.0.0",
126
- "id": "skills-scanner",
127
- "name": "Skills Scanner"
128
- },
129
- "api": {
130
- "url": "https://110.vemic.com/skills-scanner",
131
- "status": "available"
132
- },
133
- "watcher": {
134
- "enabled": true,
135
- "running": true,
136
- "directories": 2
137
- },
138
- "metrics": {
139
- "totalScans": 42,
140
- "successRate": "95.24%",
141
- "averageDurationMs": 1234
142
- }
143
- }
144
- ```
145
-
146
- ## 使用方法
147
-
148
- ### 聊天命令
149
-
150
- ```
151
- /skills-scanner scan <路径> [选项] # 扫描 Skill
152
- /skills-scanner scan clawhub <URL> [选项] # 扫描 ClawHub Skill
153
- /skills-scanner health # 健康检查
154
- /skills-scanner config [操作] # 配置管理
155
- /skills-scanner cron [操作] # 定时任务管理
156
- /skills-scanner help # 帮助信息
157
- ```
158
-
159
- #### 扫描选项
160
-
161
- - `--detailed`: 显示详细的安全发现
162
- - `--behavioral`: 启用行为分析
163
- - `--recursive`: 递归扫描子目录
164
- - `--report`: 生成日报格式
165
-
166
- #### 示例
167
-
168
- ```
169
- /skills-scanner scan ~/.openclaw/skills/my-skill
170
- /skills-scanner scan ~/.openclaw/skills --recursive
171
- /skills-scanner scan ~/.openclaw/skills --report
172
- /skills-scanner scan clawhub https://clawhub.ai/username/project
173
- /skills-scanner scan clawhub https://clawhub.ai/Asleep123/caldav-calendar --detailed
174
- /skills-scanner health
175
- ```
176
-
177
- ### CLI 命令
178
-
179
- ```bash
180
- # 扫描单个 Skill
181
- openclaw skills-scanner scan <path> [--detailed] [--behavioral]
182
-
183
- # 扫描 ClawHub Skill
184
- openclaw skills-scanner clawhub <url> [--detailed] [--behavioral]
185
-
186
- # 批量扫描目录
187
- openclaw skills-scanner batch <directory> [--recursive] [--detailed]
188
-
189
- # 生成日报
190
- openclaw skills-scanner report
191
-
192
- # 检查 API 服务健康状态
193
- openclaw skills-scanner health
194
- ```
195
-
196
- ## 工作流程
197
-
198
- 1. **插件启动**: 自动初始化并连接 API 服务
199
- 2. **文件监控**: 监听配置的 Skills 目录
200
- 3. **自动扫描**: 检测到新 Skill 时自动触发扫描
201
- 4. **结果处理**: 根据配置隔离/删除/警告不安全的 Skill
202
- 5. **定时周报**: 每周一 12:05 自动生成安全报告
203
-
204
- ## 故障排除
205
-
206
- ### API 服务连接失败
207
-
208
- 1. 确保 API 服务地址配置正确
209
- 2. 运行健康检查:`/skills-scanner health`
210
- 3. 检查网络连接
211
-
212
- ### 定时任务未注册
213
-
214
- 定时任务会在插件启动时自动注册。如果需要手动注册:
215
-
216
- ```bash
217
- # 手动注册定时任务
218
- /skills-scanner cron setup
219
-
220
- # 或使用 CLI
221
- openclaw cron add \
222
- --name "skills-weekly-report" \
223
- --cron "5 12 * * 1" \
224
- --tz "Asia/Shanghai" \
225
- --session isolated \
226
- --message "请执行 /skills-scanner scan --report 并把结果发送到此渠道" \
227
- --announce
228
- ```
229
-
230
- ## 开发
231
-
232
- ### 目录结构
233
-
234
- ```
235
- extensions/skills-scanner/
236
- ├── package.json # npm 包配置
237
- ├── openclaw.plugin.json # 插件元数据
238
- ├── README.md # 文档
239
- ├── index.ts # 插件入口
240
- ├── src/ # 源代码
241
- │ ├── api-client.ts # HTTP API 客户端
242
- │ ├── config.ts # 配置管理
243
- │ ├── scanner.ts # 扫描逻辑
244
- │ ├── watcher.ts # 文件监控
245
- │ ├── cron.ts # 定时任务
246
- │ ├── commands.ts # 命令处理
247
- │ └── types.ts # 类型定义
248
- └── skills/
249
- └── skills-scanner/
250
- └── SKILL.md # Skill 文档
251
- ```
252
-
253
- ## 许可证
254
-
255
- MIT
1
+ # deprecated
2
+
3
+ # 废弃
4
+ 该插件已被弃用,建议使用其他插件替代
package/index.ts CHANGED
@@ -6,27 +6,20 @@
6
6
 
7
7
  import { definePluginEntry } from "openclaw/plugin-sdk/plugin-entry";
8
8
  import { join } from "node:path";
9
- import os from "node:os";
10
- import { existsSync } from "node:fs";
11
9
  import type { ScannerConfig } from "./src/types.js";
12
10
  import { skillsScannerConfigSchema, generateConfigGuide } from "./src/config.js";
13
11
  import {
14
12
  loadState,
15
13
  saveState,
16
14
  expandPath,
17
- defaultScanDirs,
18
15
  isFirstRun,
19
16
  markConfigReviewed,
20
17
  getStateDir,
21
18
  } from "./src/state.js";
22
19
  import { runScan } from "./src/scanner.js";
23
- import { buildDailyReport } from "./src/report.js";
24
- import { ensureCronJobViaGateway, checkCronJobStatus } from "./src/cron-manager.js";
25
- import { startWatcher } from "./src/watcher.js";
20
+ import { ensureCronJob } from "./src/cron-manager.js";
26
21
  import { createCommandHandlers } from "./src/commands.js";
27
22
  import { SKILLS_SECURITY_GUIDANCE } from "./src/prompt-guidance.js";
28
- import { PROMPT_INJECTION_GUARD } from "./src/prompt-injection-guard.js";
29
- import { HIGH_RISK_OPERATION_GUARD } from "./src/high-risk-operation-guard.js";
30
23
  import { handleBeforeInstall } from "./src/before-install-hook.js";
31
24
  import type { BeforeInstallEvent } from "./src/before-install-hook.js";
32
25
  import { validateConfig } from "./src/config-validator.js";
@@ -57,24 +50,16 @@ export default definePluginEntry({
57
50
  }
58
51
 
59
52
  const apiUrl = cfg.apiUrl ?? "https://110.vemic.com/skills-scanner";
60
- const scanDirs =
61
- (cfg.scanDirs?.map(expandPath) ?? []).filter(existsSync).length > 0
62
- ? cfg.scanDirs!.map(expandPath)
63
- : defaultScanDirs();
64
53
  const behavioral = cfg.behavioral ?? false;
65
54
  const useLLM = cfg.useLLM ?? false;
66
55
  const policy = cfg.policy ?? "balanced";
67
- const preInstallScan = cfg.preInstallScan ?? "on";
68
56
  const onUnsafe = cfg.onUnsafe ?? "warn";
69
57
  const injectSecurityGuidance = cfg.injectSecurityGuidance ?? true;
70
- const enablePromptInjectionGuard = cfg.enablePromptInjectionGuard ?? false;
71
- const enableHighRiskOperationGuard = cfg.enableHighRiskOperationGuard ?? false;
72
58
  const enableBeforeInstallHook = cfg.enableBeforeInstallHook ?? true;
73
59
 
74
60
  api.logger.info("[skills-scanner] ═══════════════════════════════════════");
75
61
  api.logger.info("[skills-scanner] Plugin loading...");
76
62
  api.logger.info(`[skills-scanner] API URL: ${apiUrl}`);
77
- api.logger.info(`[skills-scanner] Scan directories: ${scanDirs.join(", ")}`);
78
63
  api.logger.info(`[skills-scanner] Before-install hook: ${enableBeforeInstallHook ? "✅ ENABLED" : "❌ DISABLED"}`);
79
64
 
80
65
  if (isDebugMode()) {
@@ -84,30 +69,11 @@ export default definePluginEntry({
84
69
 
85
70
  // Inject system prompt guidance (can be disabled via config)
86
71
  if (injectSecurityGuidance) {
87
- // Build combined guidance
88
- const guidanceParts = [SKILLS_SECURITY_GUIDANCE];
89
-
90
- if (enablePromptInjectionGuard) {
91
- guidanceParts.push(PROMPT_INJECTION_GUARD);
92
- }
93
-
94
- if (enableHighRiskOperationGuard) {
95
- guidanceParts.push(HIGH_RISK_OPERATION_GUARD);
96
- }
97
-
98
- const combinedGuidance = guidanceParts.join("\n\n");
99
-
100
72
  api.on("before_prompt_build", async () => ({
101
- prependSystemContext: combinedGuidance,
73
+ prependSystemContext: SKILLS_SECURITY_GUIDANCE,
102
74
  }));
103
75
 
104
76
  api.logger.info("[skills-scanner] ✅ Security guidance injected into system prompt");
105
- if (enablePromptInjectionGuard) {
106
- api.logger.info("[skills-scanner] - Prompt injection guard enabled");
107
- }
108
- if (enableHighRiskOperationGuard) {
109
- api.logger.info("[skills-scanner] - High-risk operation guard enabled");
110
- }
111
77
  } else {
112
78
  api.logger.info("[skills-scanner] ⏭️ Security guidance injection disabled");
113
79
  }
@@ -129,7 +95,9 @@ export default definePluginEntry({
129
95
  api.logger.error("[skills-scanner] ❌ before_install hook error", {
130
96
  error: err.message,
131
97
  stack: err.stack,
132
- skillPath: event.skillPath,
98
+ sourcePath: event.sourcePath,
99
+ targetType: event.targetType,
100
+ targetName: event.targetName,
133
101
  });
134
102
  // Return safe default on error - allow installation but log the failure
135
103
  return { block: false };
@@ -141,80 +109,20 @@ export default definePluginEntry({
141
109
  api.logger.warn("[skills-scanner] ⚠️ before_install hook DISABLED - installations will NOT be intercepted!");
142
110
  }
143
111
 
144
- // Register gateway_start hook for automatic cron job registration
145
- api.on("gateway_start", async () => {
112
+ // 在插件启动时设置系统 crontab 清理任务
113
+ (async () => {
146
114
  try {
147
- api.logger.info("[skills-scanner] 🚀 Gateway started, checking cron job...");
148
- await ensureCronJobViaGateway({
115
+ await ensureCronJob({
149
116
  logger: api.logger,
150
- callGateway: async (method: string, params: any) => {
151
- return await api.callGateway(method, params);
152
- },
153
- });
154
- api.logger.info("[skills-scanner] ✅ Cron job check completed");
155
- } catch (err: any) {
156
- api.logger.error("[skills-scanner] ❌ Cron job registration failed", {
157
- error: err.message,
158
- stack: err.stack,
117
+ config: api.config,
159
118
  });
160
- // Don't throw - avoid blocking gateway startup
161
- }
162
- });
163
-
164
- // Register plugin_uninstall hook for cleanup
165
- api.on("plugin_uninstall", async () => {
166
- api.logger.info("[skills-scanner] 🗑️ Plugin uninstalling, cleaning up...");
167
-
168
- try {
169
- // 1. Stop file watcher
170
- if (stopWatcher) {
171
- api.logger.debug("[skills-scanner] Stopping file watcher...");
172
- stopWatcher();
173
- stopWatcher = null;
174
- api.logger.debug("[skills-scanner] ✅ File watcher stopped");
175
- }
176
-
177
- // 2. Remove cron jobs
178
- try {
179
- const listResult = await api.callGateway("cron.list", {});
180
- const jobs = listResult?.jobs || [];
181
- const ourJobs = jobs.filter((j: any) => j.name === "skills-weekly-report");
182
-
183
- for (const job of ourJobs) {
184
- const jobId = job.jobId || job.id;
185
- await api.callGateway("cron.remove", { jobId });
186
- api.logger.info("[skills-scanner] Removed cron job", { jobId });
187
- }
188
-
189
- if (ourJobs.length > 0) {
190
- api.logger.info(`[skills-scanner] ✅ Removed ${ourJobs.length} cron job(s)`);
191
- }
192
- } catch (err: any) {
193
- api.logger.warn("[skills-scanner] Failed to remove cron jobs", {
194
- error: err.message,
195
- });
196
- }
197
-
198
- // 3. Save final state
199
- try {
200
- const finalState = loadState(api.runtime);
201
- finalState.lastUninstallAt = new Date().toISOString();
202
- saveState(finalState, api.runtime);
203
- api.logger.debug("[skills-scanner] ✅ Final state saved");
204
- } catch (err: any) {
205
- api.logger.warn("[skills-scanner] Failed to save final state", {
206
- error: err.message,
207
- });
208
- }
209
-
210
- api.logger.info("[skills-scanner] ✅ Cleanup completed successfully");
119
+ api.logger.info("[skills-scanner] System crontab cleanup task ensured");
211
120
  } catch (err: any) {
212
- api.logger.error("[skills-scanner] Cleanup failed", {
121
+ api.logger.warn("[skills-scanner] ⚠️ Failed to setup system crontab", {
213
122
  error: err.message,
214
- stack: err.stack,
215
123
  });
216
124
  }
217
- });
125
+ })();
218
126
 
219
127
  // Register config_changed hook for hot reload
220
128
  api.on("config_changed", async (newConfig: any) => {
@@ -233,8 +141,6 @@ export default definePluginEntry({
233
141
 
234
142
  // Check what changed
235
143
  const apiUrlChanged = newCfg.apiUrl !== cfg.apiUrl;
236
- const scanDirsChanged = JSON.stringify(newCfg.scanDirs) !== JSON.stringify(cfg.scanDirs);
237
- const preInstallScanChanged = newCfg.preInstallScan !== cfg.preInstallScan;
238
144
 
239
145
  if (apiUrlChanged) {
240
146
  api.logger.info("[skills-scanner] API URL updated", {
@@ -245,42 +151,6 @@ export default definePluginEntry({
245
151
  Object.assign(cfg, { apiUrl: newCfg.apiUrl });
246
152
  }
247
153
 
248
- if (scanDirsChanged || preInstallScanChanged) {
249
- api.logger.info("[skills-scanner] Scan configuration updated, restarting watcher...");
250
-
251
- // Stop old watcher
252
- if (stopWatcher) {
253
- stopWatcher();
254
- stopWatcher = null;
255
- }
256
-
257
- // Start new watcher with updated config
258
- const newScanDirs =
259
- (newCfg.scanDirs?.map(expandPath) ?? []).filter(existsSync).length > 0
260
- ? newCfg.scanDirs!.map(expandPath)
261
- : defaultScanDirs();
262
-
263
- if (newCfg.preInstallScan === "on" && newScanDirs.length > 0) {
264
- stopWatcher = startWatcher(
265
- newScanDirs,
266
- newCfg.onUnsafe ?? "warn",
267
- newCfg.behavioral ?? false,
268
- newCfg.apiUrl ?? apiUrl,
269
- newCfg.useLLM ?? false,
270
- newCfg.policy ?? "balanced",
271
- persistWatcherAlert,
272
- api.logger,
273
- QUARANTINE_DIR
274
- );
275
- api.logger.info("[skills-scanner] ✅ Watcher restarted with new configuration");
276
- } else {
277
- api.logger.info("[skills-scanner] ⏭️ Watcher disabled by new configuration");
278
- }
279
-
280
- // Update global config
281
- Object.assign(cfg, newCfg);
282
- }
283
-
284
154
  api.logger.info("[skills-scanner] ✅ Configuration reload completed");
285
155
  } catch (err: any) {
286
156
  api.logger.error("[skills-scanner] ❌ Configuration reload failed", {
@@ -297,93 +167,15 @@ export default definePluginEntry({
297
167
  const configGuide = generateConfigGuide(
298
168
  cfg,
299
169
  apiUrl,
300
- scanDirs,
301
170
  behavioral,
302
171
  useLLM,
303
172
  policy,
304
- preInstallScan,
305
173
  onUnsafe
306
174
  );
307
175
  console.log(configGuide);
308
176
  markConfigReviewed(api.runtime);
309
177
  }
310
178
 
311
- // Helper for watcher alerts
312
- function persistWatcherAlert(msg: string): void {
313
- const state = loadState(api.runtime);
314
- const alerts: string[] = (state as any).pendingAlerts ?? [];
315
- alerts.push(`[${new Date().toLocaleString("en-US")}] ${msg}`);
316
- saveState({ ...state, pendingAlerts: alerts } as any, api.runtime);
317
- api.logger.warn(`[skills-scanner] ${msg}`);
318
- }
319
-
320
- // Service: start watcher
321
- let stopWatcher: (() => void) | null = null;
322
-
323
- api.registerService({
324
- id: "skills-scanner-setup",
325
- start: async () => {
326
- api.logger.info("[skills-scanner] 🚀 Service starting...");
327
-
328
- if (preInstallScan === "on" && scanDirs.length > 0) {
329
- api.logger.info(`[skills-scanner] 📁 Starting file monitoring: ${scanDirs.length} directories`);
330
- stopWatcher = startWatcher(
331
- scanDirs,
332
- onUnsafe,
333
- behavioral,
334
- apiUrl,
335
- useLLM,
336
- policy,
337
- persistWatcherAlert,
338
- api.logger,
339
- QUARANTINE_DIR
340
- );
341
- api.logger.info("[skills-scanner] ✅ File monitoring started");
342
- } else {
343
- api.logger.info("[skills-scanner] ⏭️ Pre-install scan disabled");
344
- }
345
- },
346
- stop: async () => {
347
- api.logger.info("[skills-scanner] 🛑 Service stopping...");
348
-
349
- try {
350
- // 1. Stop file watcher
351
- if (stopWatcher) {
352
- api.logger.debug("[skills-scanner] Stopping file watcher...");
353
- stopWatcher();
354
- stopWatcher = null;
355
- api.logger.debug("[skills-scanner] ✅ File watcher stopped");
356
- }
357
-
358
- // 2. Save final state
359
- try {
360
- const finalState = loadState(api.runtime);
361
- finalState.lastShutdownAt = new Date().toISOString();
362
- saveState(finalState, api.runtime);
363
- api.logger.debug("[skills-scanner] ✅ Final state saved");
364
- } catch (err: any) {
365
- api.logger.warn("[skills-scanner] Failed to save final state", {
366
- error: err.message,
367
- });
368
- }
369
-
370
- // 3. Clear pending alerts (optional - keep for next run)
371
- // This is intentionally commented out to preserve alerts
372
- // const state = loadState(api.runtime);
373
- // if ((state as any).pendingAlerts?.length > 0) {
374
- // saveState({ ...state, pendingAlerts: [] } as any, api.runtime);
375
- // }
376
-
377
- api.logger.info("[skills-scanner] ✅ Service stopped cleanly");
378
- } catch (err: any) {
379
- api.logger.error("[skills-scanner] ❌ Error during shutdown", {
380
- error: err.message,
381
- stack: err.stack,
382
- });
383
- }
384
- },
385
- });
386
-
387
179
  // Health check endpoint
388
180
  api.registerHttpRoute({
389
181
  method: "GET",
@@ -417,11 +209,6 @@ export default definePluginEntry({
417
209
  url: apiUrl,
418
210
  status: apiStatus,
419
211
  },
420
- watcher: {
421
- enabled: preInstallScan === "on",
422
- running: stopWatcher !== null,
423
- directories: scanDirs.length,
424
- },
425
212
  state: {
426
213
  lastScanAt: state.lastScanAt || null,
427
214
  lastShutdownAt: state.lastShutdownAt || null,
@@ -461,16 +248,12 @@ export default definePluginEntry({
461
248
  const handlers = createCommandHandlers(
462
249
  cfg,
463
250
  apiUrl,
464
- scanDirs,
465
251
  behavioral,
466
252
  useLLM,
467
253
  policy,
468
- preInstallScan,
469
254
  onUnsafe,
470
255
  api.logger,
471
- async (method: string, params: any) => {
472
- return await api.callGateway(method, params);
473
- }
256
+ api.config
474
257
  );
475
258
 
476
259
  // Chat command: /skills-scanner
@@ -492,13 +275,11 @@ export default definePluginEntry({
492
275
  "• `/skills-scanner scan clawhub <URL> [选项]` - 扫描 ClawHub Skill",
493
276
  "• `/skills-scanner health` - 健康检查",
494
277
  "• `/skills-scanner config [操作]` - 配置管理",
495
- "• `/skills-scanner cron [操作]` - 定时任务管理",
496
278
  "",
497
279
  "扫描选项:",
498
280
  "• `--detailed` - 显示详细发现",
499
281
  "• `--behavioral` - 启用行为分析",
500
282
  "• `--recursive` - 递归扫描子目录",
501
- "• `--report` - 生成日报格式",
502
283
  "",
503
284
  "示例:",
504
285
  "```",
@@ -523,8 +304,6 @@ export default definePluginEntry({
523
304
  return await handlers.handleHealthCommand();
524
305
  } else if (subCommand === "config") {
525
306
  return await handlers.handleConfigCommand(subArgs);
526
- } else if (subCommand === "cron") {
527
- return await handlers.handleCronCommand(subArgs);
528
307
  } else if (subCommand === "help" || subCommand === "--help" || subCommand === "-h") {
529
308
  return { text: handlers.getHelpText() };
530
309
  } else {
@@ -560,23 +339,6 @@ export default definePluginEntry({
560
339
  }
561
340
  });
562
341
 
563
- api.registerGatewayMethod("skillsScanner.report", async ({ respond }: any) => {
564
- if (scanDirs.length === 0) return respond(false, { error: "No scan directories found" });
565
- try {
566
- const report = await buildDailyReport(
567
- scanDirs,
568
- behavioral,
569
- apiUrl,
570
- useLLM,
571
- policy,
572
- api.logger
573
- );
574
- respond(true, { report, state: loadState() });
575
- } catch (err: any) {
576
- respond(false, { error: err.message });
577
- }
578
- });
579
-
580
342
  // CLI commands
581
343
  api.registerCli(
582
344
  ({ program }: any) => {
@@ -615,21 +377,6 @@ export default definePluginEntry({
615
377
  process.exit(res.exitCode);
616
378
  });
617
379
 
618
- cmd
619
- .command("report")
620
- .description("生成日报")
621
- .action(async () => {
622
- const report = await buildDailyReport(
623
- scanDirs,
624
- behavioral,
625
- apiUrl,
626
- useLLM,
627
- policy,
628
- console
629
- );
630
- console.log(report);
631
- });
632
-
633
380
  cmd
634
381
  .command("health")
635
382
  .description("检查 API 服务健康状态")