@hddz/plugin-harness 0.1.19 → 0.2.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 @hddz/plugin-harness might be problematic. Click here for more details.
- package/README.md +97 -114
- package/dist/file-watcher.d.ts +37 -0
- package/dist/file-watcher.js +151 -0
- package/dist/index.d.ts +63 -0
- package/dist/index.js +166 -106
- package/dist/src/file-watcher.d.ts +37 -0
- package/dist/src/file-watcher.js +151 -0
- package/dist/src/index.d.ts +70 -0
- package/dist/src/index.js +192 -0
- package/package.json +4 -10
- package/openclaw.plugin.json +0 -39
package/README.md
CHANGED
|
@@ -1,45 +1,46 @@
|
|
|
1
1
|
# @hddz/plugin-harness
|
|
2
2
|
|
|
3
|
-
>
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
> **许可**: MIT
|
|
3
|
+
> OpenClaw Harness Engineering 插件 - 为 AI Agent 构建约束、反馈与控制系统
|
|
4
|
+
|
|
5
|
+
**最新版本**: v0.2.0 (2026-03-24)
|
|
7
6
|
|
|
8
7
|
---
|
|
9
8
|
|
|
10
|
-
## 🎯
|
|
9
|
+
## 🎯 功能
|
|
11
10
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
| **Trace 追踪** | 完整的工具调用链路追踪 | ✅ |
|
|
11
|
+
- ✅ **配置验证**:修改 `openclaw.json` 前自动验证
|
|
12
|
+
- ✅ **Skill 审核**:安装 Skill 前自动安全扫描
|
|
13
|
+
- ✅ **循环检测**:防止 AI 反复修改同一文件
|
|
14
|
+
- ✅ **文件保护**:保护关键文件(SOUL.md 等)不被误删
|
|
15
|
+
- ✅ **操作审计**:记录所有关键操作
|
|
16
|
+
- ✅ **Trace 追踪**:完整的工具调用链路
|
|
17
|
+
- ✅ **文件监听器** (v0.2.0 新增):实时监听配置文件变化,用户手动编辑也能触发验证
|
|
20
18
|
|
|
21
19
|
---
|
|
22
20
|
|
|
23
21
|
## 🚀 快速开始
|
|
24
22
|
|
|
25
|
-
###
|
|
23
|
+
### 安装
|
|
26
24
|
|
|
27
25
|
```bash
|
|
28
|
-
#
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
# 重启 Gateway
|
|
32
|
-
openclaw gateway restart
|
|
26
|
+
# 从 npm 安装(推荐)
|
|
27
|
+
npm install @hddz/plugin-harness@0.2.0
|
|
33
28
|
|
|
34
|
-
#
|
|
35
|
-
openclaw
|
|
29
|
+
# 本地开发版
|
|
30
|
+
cd /Users/hzl/.openclaw/extensions/harness
|
|
31
|
+
npm link
|
|
36
32
|
```
|
|
37
33
|
|
|
38
|
-
|
|
34
|
+
### 配置
|
|
35
|
+
|
|
36
|
+
编辑 `~/.openclaw/openclaw.json`:
|
|
39
37
|
|
|
40
38
|
```json
|
|
41
39
|
{
|
|
42
40
|
"plugins": {
|
|
41
|
+
"installs": [
|
|
42
|
+
"@hddz/plugin-harness@0.2.0"
|
|
43
|
+
],
|
|
43
44
|
"entries": {
|
|
44
45
|
"harness": {
|
|
45
46
|
"enabled": true,
|
|
@@ -55,7 +56,7 @@ openclaw plugins list
|
|
|
55
56
|
"MEMORY.md",
|
|
56
57
|
"openclaw.json"
|
|
57
58
|
],
|
|
58
|
-
"logsDir": "
|
|
59
|
+
"logsDir": "logs/harness"
|
|
59
60
|
}
|
|
60
61
|
}
|
|
61
62
|
}
|
|
@@ -63,13 +64,9 @@ openclaw plugins list
|
|
|
63
64
|
}
|
|
64
65
|
```
|
|
65
66
|
|
|
66
|
-
|
|
67
|
+
然后重启 gateway:
|
|
67
68
|
|
|
68
69
|
```bash
|
|
69
|
-
# 链接本地插件目录
|
|
70
|
-
openclaw plugins install -l /Users/hzl/.openclaw/workspace/harness-plugin
|
|
71
|
-
|
|
72
|
-
# 重启 Gateway
|
|
73
70
|
openclaw gateway restart
|
|
74
71
|
```
|
|
75
72
|
|
|
@@ -79,17 +76,35 @@ openclaw gateway restart
|
|
|
79
76
|
|
|
80
77
|
| 选项 | 类型 | 默认值 | 说明 |
|
|
81
78
|
|------|------|--------|------|
|
|
82
|
-
| `autoValidateConfig` | boolean |
|
|
83
|
-
| `autoAuditSkill` | boolean |
|
|
84
|
-
| `loopDetectionEnabled` | boolean |
|
|
85
|
-
| `protectedFiles` | string[] |
|
|
86
|
-
| `logsDir` | string |
|
|
79
|
+
| `autoValidateConfig` | boolean | true | 配置修改前自动验证 |
|
|
80
|
+
| `autoAuditSkill` | boolean | true | Skill 安装前自动审核 |
|
|
81
|
+
| `loopDetectionEnabled` | boolean | true | 启用循环检测 |
|
|
82
|
+
| `protectedFiles` | string[] | 见上文 | 受保护的文件列表 |
|
|
83
|
+
| `logsDir` | string | logs/harness | 日志目录 |
|
|
87
84
|
|
|
88
85
|
---
|
|
89
86
|
|
|
90
|
-
##
|
|
87
|
+
## 🔍 使用示例
|
|
88
|
+
|
|
89
|
+
### 配置验证(自动)
|
|
90
|
+
|
|
91
|
+
```typescript
|
|
92
|
+
// 修改 openclaw.json 时自动触发
|
|
93
|
+
const result = await plugin.onConfigChange(newConfig);
|
|
94
|
+
// 如果验证失败,会抛出异常阻止修改
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
### Skill 审核(自动)
|
|
98
|
+
|
|
99
|
+
```typescript
|
|
100
|
+
// 安装 Skill 时自动触发
|
|
101
|
+
const auditResult = await plugin.onSkillInstall('/path/to/skill');
|
|
102
|
+
if (!auditResult.passed) {
|
|
103
|
+
throw new Error(`Skill 审核未通过:${auditResult.riskLevel}`);
|
|
104
|
+
}
|
|
105
|
+
```
|
|
91
106
|
|
|
92
|
-
|
|
107
|
+
### 手动查询
|
|
93
108
|
|
|
94
109
|
```bash
|
|
95
110
|
# 查看最近的配置变更
|
|
@@ -97,112 +112,80 @@ harness get-config-changes -l 10
|
|
|
97
112
|
|
|
98
113
|
# 查看操作日志
|
|
99
114
|
harness get-operations -l 20
|
|
115
|
+
|
|
116
|
+
# 查看循环检测统计
|
|
117
|
+
harness loop-stats
|
|
100
118
|
```
|
|
101
119
|
|
|
102
120
|
---
|
|
103
121
|
|
|
104
|
-
##
|
|
122
|
+
## 🛡️ 安全机制
|
|
105
123
|
|
|
106
|
-
###
|
|
124
|
+
### 保护文件
|
|
107
125
|
|
|
108
|
-
|
|
109
|
-
|------|----------|------|
|
|
110
|
-
| `onConfigChange` | 修改 `openclaw.json` 前 | 验证配置有效性 |
|
|
111
|
-
| `onSkillInstall` | 安装 Skill 前 | 扫描安全风险 |
|
|
112
|
-
| `onFileEdit` | 编辑文件时 | 循环检测 + 保护文件监控 |
|
|
113
|
-
| `onFileDelete` | 删除文件前 | 拦截保护文件删除 |
|
|
114
|
-
| `onExecCommand` | 执行命令前 | 记录审计日志 |
|
|
126
|
+
以下文件默认受保护,修改/删除前会告警:
|
|
115
127
|
|
|
116
|
-
|
|
128
|
+
- `SOUL.md` - 身份定义
|
|
129
|
+
- `USER.md` - 用户信息
|
|
130
|
+
- `AGENTS.md` - Agent 指南
|
|
131
|
+
- `TOOLS.md` - 工具配置
|
|
132
|
+
- `MEMORY.md` - 长期记忆
|
|
133
|
+
- `openclaw.json` - 核心配置
|
|
117
134
|
|
|
118
|
-
|
|
119
|
-
harness-plugin/
|
|
120
|
-
├── src/
|
|
121
|
-
│ └── index.ts # 插件核心逻辑
|
|
122
|
-
├── dist/ # 编译输出
|
|
123
|
-
├── docs/ # 文档
|
|
124
|
-
├── openclaw.plugin.json # OpenClaw 插件元数据
|
|
125
|
-
├── package.json # NPM 配置
|
|
126
|
-
├── tsconfig.json # TypeScript 配置
|
|
127
|
-
└── README.md # 本文件
|
|
128
|
-
```
|
|
135
|
+
### 风险等级
|
|
129
136
|
|
|
130
|
-
|
|
137
|
+
| 等级 | 标识 | 处理 |
|
|
138
|
+
|------|------|------|
|
|
139
|
+
| LOW | 🟢 | 允许 |
|
|
140
|
+
| MEDIUM | 🟡 | 警告,但允许 |
|
|
141
|
+
| HIGH | 🟠 | 阻止,需人工确认 |
|
|
142
|
+
| CRITICAL | 🔴 | 阻止,禁止操作 |
|
|
131
143
|
|
|
132
|
-
|
|
144
|
+
---
|
|
133
145
|
|
|
134
|
-
|
|
146
|
+
## 📚 文档
|
|
135
147
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
3. 确认 `openclaw.json` 配置了 `plugins.entries.harness`
|
|
140
|
-
4. 检查 manifest:`cat ~/.openclaw/extensions/harness/openclaw.plugin.json`
|
|
148
|
+
- [使用指南](./docs/使用指南.md)
|
|
149
|
+
- [开发文档](./docs/开发文档.md)
|
|
150
|
+
- [API 参考](./docs/API.md)
|
|
141
151
|
|
|
142
|
-
|
|
152
|
+
---
|
|
143
153
|
|
|
144
|
-
|
|
145
|
-
```json
|
|
146
|
-
{
|
|
147
|
-
"plugins": {
|
|
148
|
-
"entries": {
|
|
149
|
-
"harness": {
|
|
150
|
-
"enabled": true,
|
|
151
|
-
"config": {
|
|
152
|
-
"autoValidateConfig": true
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
```
|
|
154
|
+
## 🔧 开发
|
|
159
155
|
|
|
160
|
-
|
|
156
|
+
```bash
|
|
157
|
+
# 安装依赖
|
|
158
|
+
npm install
|
|
161
159
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
{
|
|
165
|
-
"plugins": {
|
|
166
|
-
"entries": {
|
|
167
|
-
"harness": {
|
|
168
|
-
"config": {
|
|
169
|
-
"autoValidateConfig": false,
|
|
170
|
-
"loopDetectionEnabled": false
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
```
|
|
160
|
+
# 构建
|
|
161
|
+
npm run build
|
|
177
162
|
|
|
178
|
-
|
|
163
|
+
# 测试
|
|
164
|
+
npm test
|
|
179
165
|
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
openclaw plugins uninstall harness
|
|
183
|
-
openclaw gateway restart
|
|
166
|
+
# 链接到 OpenClaw
|
|
167
|
+
npm link
|
|
184
168
|
```
|
|
185
169
|
|
|
186
170
|
---
|
|
187
171
|
|
|
188
|
-
##
|
|
172
|
+
## 📝 变更日志
|
|
173
|
+
|
|
174
|
+
### v0.1.0 (2026-03-19)
|
|
189
175
|
|
|
190
|
-
-
|
|
191
|
-
-
|
|
176
|
+
- ✅ 初始版本
|
|
177
|
+
- ✅ 配置验证
|
|
178
|
+
- ✅ Skill 审核
|
|
179
|
+
- ✅ 循环检测
|
|
180
|
+
- ✅ 操作日志
|
|
181
|
+
- ✅ Trace 追踪
|
|
192
182
|
|
|
193
183
|
---
|
|
194
184
|
|
|
195
|
-
##
|
|
185
|
+
## 📄 许可证
|
|
196
186
|
|
|
197
|
-
|
|
198
|
-
|------|------|------|
|
|
199
|
-
| 0.1.10 | 2026-03-24 | 添加 `openclaw.plugin.json` manifest,支持 `openclaw plugins install` |
|
|
200
|
-
| 0.1.9 | 2026-03-24 | 提供 `install.sh` 一键安装脚本 |
|
|
201
|
-
| 0.1.8 | 2026-03-24 | 修复 Skill 审核路径问题 |
|
|
202
|
-
| 0.1.7 | 2026-03-23 | 初始发布到 npm |
|
|
187
|
+
MIT
|
|
203
188
|
|
|
204
189
|
---
|
|
205
190
|
|
|
206
|
-
|
|
207
|
-
**仓库**: https://github.com/hddz/plugin-harness
|
|
208
|
-
**npm**: https://www.npmjs.com/package/@hddz/plugin-harness
|
|
191
|
+
_@openclaw/plugin-harness | 蓝山 | 2026-03-19_
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { HarnessPlugin } from './index.js';
|
|
2
|
+
export interface FileWatcherConfig {
|
|
3
|
+
watchFiles: string[];
|
|
4
|
+
debounceMs: number;
|
|
5
|
+
onFileChange: (filePath: string, newContent: any) => Promise<void>;
|
|
6
|
+
}
|
|
7
|
+
export declare class FileWatcher {
|
|
8
|
+
private watchPaths;
|
|
9
|
+
private debounceTimers;
|
|
10
|
+
private config;
|
|
11
|
+
private plugin;
|
|
12
|
+
constructor(plugin: HarnessPlugin, config: FileWatcherConfig);
|
|
13
|
+
/**
|
|
14
|
+
* 开始监听文件
|
|
15
|
+
*/
|
|
16
|
+
start(): void;
|
|
17
|
+
/**
|
|
18
|
+
* 监听单个文件
|
|
19
|
+
*/
|
|
20
|
+
private watchFile;
|
|
21
|
+
/**
|
|
22
|
+
* 停止监听单个文件
|
|
23
|
+
*/
|
|
24
|
+
private unwatchFile;
|
|
25
|
+
/**
|
|
26
|
+
* 文件变化处理(带防抖)
|
|
27
|
+
*/
|
|
28
|
+
private onFileChange;
|
|
29
|
+
/**
|
|
30
|
+
* 处理文件变化
|
|
31
|
+
*/
|
|
32
|
+
private handleFileChange;
|
|
33
|
+
/**
|
|
34
|
+
* 停止所有监听
|
|
35
|
+
*/
|
|
36
|
+
stop(): void;
|
|
37
|
+
}
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// src/file-watcher.ts - 配置文件监听器
|
|
3
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
4
|
+
if (k2 === undefined) k2 = k;
|
|
5
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
6
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
7
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
8
|
+
}
|
|
9
|
+
Object.defineProperty(o, k2, desc);
|
|
10
|
+
}) : (function(o, m, k, k2) {
|
|
11
|
+
if (k2 === undefined) k2 = k;
|
|
12
|
+
o[k2] = m[k];
|
|
13
|
+
}));
|
|
14
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
15
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
16
|
+
}) : function(o, v) {
|
|
17
|
+
o["default"] = v;
|
|
18
|
+
});
|
|
19
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
20
|
+
var ownKeys = function(o) {
|
|
21
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
22
|
+
var ar = [];
|
|
23
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
24
|
+
return ar;
|
|
25
|
+
};
|
|
26
|
+
return ownKeys(o);
|
|
27
|
+
};
|
|
28
|
+
return function (mod) {
|
|
29
|
+
if (mod && mod.__esModule) return mod;
|
|
30
|
+
var result = {};
|
|
31
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
32
|
+
__setModuleDefault(result, mod);
|
|
33
|
+
return result;
|
|
34
|
+
};
|
|
35
|
+
})();
|
|
36
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
37
|
+
exports.FileWatcher = void 0;
|
|
38
|
+
const fs = __importStar(require("fs"));
|
|
39
|
+
class FileWatcher {
|
|
40
|
+
watchPaths = new Map();
|
|
41
|
+
debounceTimers = new Map();
|
|
42
|
+
config;
|
|
43
|
+
plugin;
|
|
44
|
+
constructor(plugin, config) {
|
|
45
|
+
this.plugin = plugin;
|
|
46
|
+
this.config = config;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* 开始监听文件
|
|
50
|
+
*/
|
|
51
|
+
start() {
|
|
52
|
+
console.log('👁️ [FileWatcher] 开始监听配置文件...');
|
|
53
|
+
for (const file of this.config.watchFiles) {
|
|
54
|
+
this.watchFile(file);
|
|
55
|
+
}
|
|
56
|
+
console.log(`👁️ [FileWatcher] 正在监听 ${this.config.watchFiles.length} 个文件`);
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* 监听单个文件
|
|
60
|
+
*/
|
|
61
|
+
watchFile(filePath) {
|
|
62
|
+
// 如果已经在监听,先停止
|
|
63
|
+
if (this.watchPaths.has(filePath)) {
|
|
64
|
+
this.unwatchFile(filePath);
|
|
65
|
+
}
|
|
66
|
+
try {
|
|
67
|
+
const watcher = fs.watch(filePath, { persistent: false }, (eventType, filename) => {
|
|
68
|
+
if (eventType === 'change' || eventType === 'rename') {
|
|
69
|
+
console.log(`📝 [FileWatcher] 检测到文件变化:${filePath} (${eventType})`);
|
|
70
|
+
this.onFileChange(filePath);
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
watcher.on('error', (error) => {
|
|
74
|
+
console.error(`❌ [FileWatcher] 监听错误 ${filePath}:`, error.message);
|
|
75
|
+
});
|
|
76
|
+
this.watchPaths.set(filePath, watcher);
|
|
77
|
+
console.log(`✅ [FileWatcher] 开始监听:${filePath}`);
|
|
78
|
+
}
|
|
79
|
+
catch (error) {
|
|
80
|
+
console.warn(`⚠️ [FileWatcher] 无法监听文件 ${filePath}: ${error.message}`);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* 停止监听单个文件
|
|
85
|
+
*/
|
|
86
|
+
unwatchFile(filePath) {
|
|
87
|
+
const watcher = this.watchPaths.get(filePath);
|
|
88
|
+
if (watcher) {
|
|
89
|
+
watcher.close();
|
|
90
|
+
this.watchPaths.delete(filePath);
|
|
91
|
+
console.log(`🛑 [FileWatcher] 停止监听:${filePath}`);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* 文件变化处理(带防抖)
|
|
96
|
+
*/
|
|
97
|
+
async onFileChange(filePath) {
|
|
98
|
+
// 清除之前的定时器
|
|
99
|
+
const existingTimer = this.debounceTimers.get(filePath);
|
|
100
|
+
if (existingTimer) {
|
|
101
|
+
clearTimeout(existingTimer);
|
|
102
|
+
}
|
|
103
|
+
// 设置新的防抖定时器
|
|
104
|
+
const timer = setTimeout(async () => {
|
|
105
|
+
try {
|
|
106
|
+
await this.handleFileChange(filePath);
|
|
107
|
+
}
|
|
108
|
+
catch (error) {
|
|
109
|
+
console.error(`❌ [FileWatcher] 处理文件变化失败 ${filePath}:`, error.message);
|
|
110
|
+
}
|
|
111
|
+
this.debounceTimers.delete(filePath);
|
|
112
|
+
}, this.config.debounceMs);
|
|
113
|
+
this.debounceTimers.set(filePath, timer);
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* 处理文件变化
|
|
117
|
+
*/
|
|
118
|
+
async handleFileChange(filePath) {
|
|
119
|
+
console.log(`🔍 [FileWatcher] 处理文件变化:${filePath}`);
|
|
120
|
+
// 读取新配置
|
|
121
|
+
let newConfig;
|
|
122
|
+
try {
|
|
123
|
+
const content = fs.readFileSync(filePath, 'utf8');
|
|
124
|
+
newConfig = JSON.parse(content);
|
|
125
|
+
}
|
|
126
|
+
catch (error) {
|
|
127
|
+
console.error(`❌ [FileWatcher] 读取配置失败:${error.message}`);
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
// 调用插件的配置变更处理
|
|
131
|
+
await this.config.onFileChange(filePath, newConfig);
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* 停止所有监听
|
|
135
|
+
*/
|
|
136
|
+
stop() {
|
|
137
|
+
console.log('🛑 [FileWatcher] 停止所有文件监听...');
|
|
138
|
+
for (const [filePath, watcher] of this.watchPaths.entries()) {
|
|
139
|
+
watcher.close();
|
|
140
|
+
}
|
|
141
|
+
this.watchPaths.clear();
|
|
142
|
+
// 清除所有定时器
|
|
143
|
+
for (const [filePath, timer] of this.debounceTimers.entries()) {
|
|
144
|
+
clearTimeout(timer);
|
|
145
|
+
}
|
|
146
|
+
this.debounceTimers.clear();
|
|
147
|
+
console.log('🛑 [FileWatcher] 已停止所有监听');
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
exports.FileWatcher = FileWatcher;
|
|
151
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmlsZS13YXRjaGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL2ZpbGUtd2F0Y2hlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUEsZ0NBQWdDOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFFaEMsdUNBQXlCO0FBVXpCLE1BQWEsV0FBVztJQUNkLFVBQVUsR0FBOEIsSUFBSSxHQUFHLEVBQUUsQ0FBQztJQUNsRCxjQUFjLEdBQWdDLElBQUksR0FBRyxFQUFFLENBQUM7SUFDeEQsTUFBTSxDQUFvQjtJQUMxQixNQUFNLENBQWdCO0lBRTlCLFlBQVksTUFBcUIsRUFBRSxNQUF5QjtRQUMxRCxJQUFJLENBQUMsTUFBTSxHQUFHLE1BQU0sQ0FBQztRQUNyQixJQUFJLENBQUMsTUFBTSxHQUFHLE1BQU0sQ0FBQztJQUN2QixDQUFDO0lBRUQ7O09BRUc7SUFDSCxLQUFLO1FBQ0gsT0FBTyxDQUFDLEdBQUcsQ0FBQywrQkFBK0IsQ0FBQyxDQUFDO1FBRTdDLEtBQUssTUFBTSxJQUFJLElBQUksSUFBSSxDQUFDLE1BQU0sQ0FBQyxVQUFVLEVBQUUsQ0FBQztZQUMxQyxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQ3ZCLENBQUM7UUFFRCxPQUFPLENBQUMsR0FBRyxDQUFDLDBCQUEwQixJQUFJLENBQUMsTUFBTSxDQUFDLFVBQVUsQ0FBQyxNQUFNLE1BQU0sQ0FBQyxDQUFDO0lBQzdFLENBQUM7SUFFRDs7T0FFRztJQUNLLFNBQVMsQ0FBQyxRQUFnQjtRQUNoQyxjQUFjO1FBQ2QsSUFBSSxJQUFJLENBQUMsVUFBVSxDQUFDLEdBQUcsQ0FBQyxRQUFRLENBQUMsRUFBRSxDQUFDO1lBQ2xDLElBQUksQ0FBQyxXQUFXLENBQUMsUUFBUSxDQUFDLENBQUM7UUFDN0IsQ0FBQztRQUVELElBQUksQ0FBQztZQUNILE1BQU0sT0FBTyxHQUFHLEVBQUUsQ0FBQyxLQUFLLENBQUMsUUFBUSxFQUFFLEVB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T0FBTyxLQUFVLEVBQUUsQ0FBQztZQUNwQixPQUFPLENBQUMsS0FBSyxDQUFDLDBCQUEwQixLQUFLLENBQUMsT0FBTyxFQUFFLENBQUMsQ0FBQztZQUN6RCxPQUFPO1FBQ1QsQ0FBQztRQUVELGNBQWM7UUFDZCxNQUFNLElBQUksQ0FBQyxNQUFNLENBQUMsWUFBWSxDQUFDLFFBQVEsRUFBRSxTQUFTLENBQUMsQ0FBQztJQUN0RCxDQUFDO0lBRUQ7O09BRUc7SUFDSCxJQUFJO1FBQ0YsT0FBTyxDQUFDLEdBQUcsQ0FBQyw4QkFBOEIsQ0FBQyxDQUFDO1FBRTVDLEtBQUssTUFBTSxDQUFDLFFBQVEsRUFBRSxPQUFPLENBQUMsSUFBSSxJQUFJLENBQUMsVUFBVSxDQUFDLE9BQU8sRUFBRSxFQUFFLENBQUM7WUFDNUQsT0FBTyxDQUFDLEtBQUssRUFBRSxDQUFDO1FBQ2xCLENBQUM7UUFFRCxJQUFJLENBQUMsVUFBVSxDQUFDLEtBQUssRUFBRSxDQUFDO1FBRXhCLFVBQVU7UUFDVixLQUFLLE1BQU0sQ0FBQyxRQUFRLEVBQUUsS0FBSyxDQUFDLElBQUksSUFBSSxDQUFDLGNBQWMsQ0FBQyxPQUFPLEVBQUUsRUFBRSxDQUFDO1lBQzlELFlBQVksQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUN0QixDQUFDO1FBRUQsSUFBSSxDQUFDLGNBQWMsQ0FBQyxLQUFLLEVBQUUsQ0FBQztRQUM1QixPQUFPLENBQUMsR0FBRyxDQUFDLDBCQUEwQixDQUFDLENBQUM7SUFDMUMsQ0FBQztDQUNGO0FBL0hELGtDQStIQyIsInNvdXJjZXNDb250ZW50IjpbIi8vIHNyYy9maWxlLXdhdGNoZXIudHMgLSDphY3nva7mlofku7bnm5HlkKzlmahcblxuaW1wb3J0ICogYXMgZnMgZnJvbSAnZnMnO1xuaW1wb3J0ICogYXMgcGF0aCBmcm9tICdwYXRoJztcbmltcG9ydCB0eXBlIHsgSGFybmVzc1BsdWdpbiB9IGZyb20gJy4vaW5kZXguanMnO1xuXG5leHBvcnQgaW50ZXJmYWNlIEZpbGVXYXRjaGVyQ29uZmlnIHtcbiAgd2F0Y2hGaWxlczogc3RyaW5nW107XG4gIGRlYm91bmNlTXM6IG51bWJlcjtcbiAgb25GaWxlQ2hhbmdlOiAoZmlsZVBhdGg6IHN0cmluZywgbmV3Q29udGVudDogYW55KSA9PiBQcm9taXNlPHZvaWQ+O1xufVxuXG5leHBvcnQgY2xhc3MgRmlsZVdhdGNoZXIge1xuICBwcml2YXRlIHdhdGNoUGF0aHM6IE1hcDxzdHJpbmcsIGZzLkZTV2F0Y2hlcj4gPSBuZXcgTWFwKCk7XG4gIHByaXZhdGUgZGVib3VuY2VUaW1lcnM6IE1hcDxzdHJpbmcsIE5vZGVKUy5UaW1lb3V0PiA9IG5ldyBNYXAoKTtcbiAgcHJpdmF0ZSBjb25maWc6IEZpbGVXYXRjaGVyQ29uZmlnO1xuICBwcml2YXRlIHBsdWdpbjogSGFybmVzc1BsdWdpbjtcblxuICBjb25zdHJ1Y3RvcihwbHVnaW46IEhhcm5lc3NQbHVnaW4sIGNvbmZpZzogRmlsZVdhdGNoZXJDb25maWcpIHtcbiAgICB0aGlzLnBsdWdpbiA9IHBsdWdpbjtcbiAgICB0aGlzLmNvbmZpZyA9IGNvbmZpZztcbiAgfVxuXG4gIC8qKlxuICAgKiDlvIDlp4vnm5HlkKzmlofku7ZcbiAgICovXG4gIHN0YXJ0KCk6IHZvaWQge1xuICAgIGNvbnNvbGUubG9nKCfwn5GB77iPIFtGaWxlV2F0Y2hlcl0g5byA5aeL55uR5ZCs6YWN572u5paH5Lu2Li4uJyk7XG4gICAgXG4gICAgZm9yIChjb25zdCBmaWxlIG9mIHRoaXMuY29uZmlnLndhdGNoRmlsZXMpIHtcbiAgICAgIHRoaXMud2F0Y2hGaWxlKGZpbGUpO1xuICAgIH1cbiAgICBcbiAgICBjb25zb2xlLmxvZyhg8J+Rge+4jyBbRmlsZVdhdGNoZXJdIOato+WcqOebkeWQrCAke3RoaXMuY29uZmlnLndhdGNoRmlsZXMubGVuZ3RofSDkuKrmlofku7ZgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiDnm5HlkKzljZXkuKrmlofku7ZcbiAgICovXG4gIHByaXZhdGUgd2F0Y2hGaWxlKGZpbGVQYXRoOiBzdHJpbmcpOiB2b2lkIHtcbiAgICAvLyDlpoLmnpzlt7Lnu4/lnKjnm5HlkKzvvIzlhYjlgZzmraJcbiAgICBpZiAodGhpcy53YXRjaFBhdGhzLmhhcyhmaWxlUGF0aCkpIHtcbiAgICAgIHRoaXMudW53YXRjaEZpbGUoZmlsZVBhdGgpO1xuICAgIH1cblxuICAgIHRyeSB7XG4gICAgICBjb25zdCB3YXRjaGVyID0gZnMud2F0Y2goZmlsZVBhdGgsIHsgcGVyc2lzdGVudDogZmFsc2UgfSwgKGV2ZW50VHlwZSwgZmlsZW5hbWUpID0+IHtcbiAgICAgICAgaWYgKGV2ZW50VHlwZSA9PT0gJ2NoYW5nZScgfHwgZXZlbnRUeXBlID09PSAncmVuYW1lJykge1xuICAgICAgICAgIGNvbnNvbGUubG9nKGDwn5OdIFtGaWxlV2F0Y2hlcl0g5qOA5rWL5Yiw5paH5Lu25Y+Y5YyW77yaJHtmaWxlUGF0aH0gKCR7ZXZlbnRUeXBlfSlgKTtcbiAgICAgICAgICB0aGlzLm9uRmlsZUNoYW5nZShmaWxlUGF0aCk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuXG4gICAgICB3YXRjaGVyLm9uKCdlcnJvcicsIChlcnJvcikgPT4ge1xuICAgICAgICBjb25zb2xlLmVycm9yKGDinYwgW0ZpbGVXYXRjaGVyXSDnm5HlkKzplJnor68gJHtmaWxlUGF0aH06YCwgZXJyb3IubWVzc2FnZSk7XG4gICAgICB9KTtcblxuICAgICAgdGhpcy53YXRjaFBhdGhzLnNldChmaWxlUGF0aCwgd2F0Y2hlcik7XG4gICAgICBjb25zb2xlLmxvZyhg4pyFIFtGaWxlV2F0Y2hlcl0g5byA5aeL55uR5ZCs77yaJHtmaWxlUGF0aH1gKTtcbiAgICB9IGNhdGNoIChlcnJvcjogYW55KSB7XG4gICAgICBjb25zb2xlLndhcm4oYOKaoO+4jyBbRmlsZVdhdGNoZXJdIOaXoOazleebkeWQrOaWh+S7tiAke2ZpbGVQYXRofTogJHtlcnJvci5tZXNzYWdlfWApO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiDlgZzmraLnm5HlkKzljZXkuKrmlofku7ZcbiAgICovXG4gIHByaXZhdGUgdW53YXRjaEZpbGUoZmlsZVBhdGg6IHN0cmluZyk6IHZvaWQge1xuICAgIGNvbnN0IHdhdGNoZXIgPSB0aGlzLndhdGNoUGF0aHMuZ2V0KGZpbGVQYXRoKTtcbiAgICBpZiAod2F0Y2hlcikge1xuICAgICAgd2F0Y2hlci5jbG9zZSgpO1xuICAgICAgdGhpcy53YXRjaFBhdGhzLmRlbGV0ZShmaWxlUGF0aCk7XG4gICAgICBjb25zb2xlLmxvZyhg8J+bkSBbRmlsZVdhdGNoZXJdIOWBnOatouebkeWQrO+8miR7ZmlsZVBhdGh9YCk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIOaWh+S7tuWPmOWMluWkhOeQhu+8iOW4pumYsuaKlu+8iVxuICAgKi9cbiAgcHJpdmF0ZSBhc3luYyBvbkZpbGVDaGFuZ2UoZmlsZVBhdGg6IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICAgIC8vIOa4hemZpOS5i+WJjeeahOWumuaXtuWZqFxuICAgIGNvbnN0IGV4aXN0aW5nVGltZXIgPSB0aGlzLmRlYm91bmNlVGltZXJzLmdldChmaWxlUGF0aCk7XG4gICAgaWYgKGV4aXN0aW5nVGltZXIpIHtcbiAgICAgIGNsZWFyVGltZW91dChleGlzdGluZ1RpbWVyKTtcbiAgICB9XG5cbiAgICAvLyDorr7nva7mlrDnmoTpmLLmipblrprml7blmahcbiAgICBjb25zdCB0aW1lciA9IHNldFRpbWVvdXQoYXN5bmMgKCkgPT4ge1xuICAgICAgdHJ5IHtcbiAgICAgICAgYXdhaXQgdGhpcy5oYW5kbGVGaWxlQ2hhbmdlKGZpbGVQYXRoKTtcbiAgICAgIH0gY2F0Y2ggKGVycm9yOiBhbnkpIHtcbiAgICAgICAgY29uc29sZS5lcnJvcihg4p2MIFtGaWxlV2F0Y2hlcl0g5aSE55CG5paH5Lu25Y+Y5YyW5aSx6LSlICR7ZmlsZVBhdGh9OmAsIGVycm9yLm1lc3NhZ2UpO1xuICAgICAgfVxuICAgICAgdGhpcy5kZWJvdW5jZVRpbWVycy5kZWxldGUoZmlsZVBhdGgpO1xuICAgIH0sIHRoaXMuY29uZmlnLmRlYm91bmNlTXMpO1xuXG4gICAgdGhpcy5kZWJvdW5jZVRpbWVycy5zZXQoZmlsZVBhdGgsIHRpbWVyKTtcbiAgfVxuXG4gIC8qKlxuICAgKiDlpITnkIbmlofku7blj5jljJZcbiAgICovXG4gIHByaXZhdGUgYXN5bmMgaGFuZGxlRmlsZUNoYW5nZShmaWxlUGF0aDogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc29sZS5sb2coYPCflI0gW0ZpbGVXYXRjaGVyXSDlpITnkIbmlofku7blj5jljJbvvJoke2ZpbGVQYXRofWApO1xuXG4gICAgLy8g6K+75Y+W5paw6YWN572uXG4gICAgbGV0IG5ld0NvbmZpZzogYW55O1xuICAgIHRyeSB7XG4gICAgICBjb25zdCBjb250ZW50ID0gZnMucmVhZEZpbGVTeW5jKGZpbGVQYXRoLCAndXRmOCcpO1xuICAgICAgbmV3Q29uZmlnID0gSlNPTi5wYXJzZShjb250ZW50KTtcbiAgICB9IGNhdGNoIChlcnJvcjogYW55KSB7XG4gICAgICBjb25zb2xlLmVycm9yKGDinYwgW0ZpbGVXYXRjaGVyXSDor7vlj5bphY3nva7lpLHotKXvvJoke2Vycm9yLm1lc3NhZ2V9YCk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgLy8g6LCD55So5o+S5Lu255qE6YWN572u5Y+Y5pu05aSE55CGXG4gICAgYXdhaXQgdGhpcy5jb25maWcub25GaWxlQ2hhbmdlKGZpbGVQYXRoLCBuZXdDb25maWcpO1xuICB9XG5cbiAgLyoqXG4gICAqIOWBnOatouaJgOacieebkeWQrFxuICAgKi9cbiAgc3RvcCgpOiB2b2lkIHtcbiAgICBjb25zb2xlLmxvZygn8J+bkSBbRmlsZVdhdGNoZXJdIOWBnOatouaJgOacieaWh+S7tuebkeWQrC4uLicpO1xuICAgIFxuICAgIGZvciAoY29uc3QgW2ZpbGVQYXRoLCB3YXRjaGVyXSBvZiB0aGlzLndhdGNoUGF0aHMuZW50cmllcygpKSB7XG4gICAgICB3YXRjaGVyLmNsb3NlKCk7XG4gICAgfVxuICAgIFxuICAgIHRoaXMud2F0Y2hQYXRocy5jbGVhcigpO1xuICAgIFxuICAgIC8vIOa4hemZpOaJgOacieWumuaXtuWZqFxuICAgIGZvciAoY29uc3QgW2ZpbGVQYXRoLCB0aW1lcl0gb2YgdGhpcy5kZWJvdW5jZVRpbWVycy5lbnRyaWVzKCkpIHtcbiAgICAgIGNsZWFyVGltZW91dCh0aW1lcik7XG4gICAgfVxuICAgIFxuICAgIHRoaXMuZGVib3VuY2VUaW1lcnMuY2xlYXIoKTtcbiAgICBjb25zb2xlLmxvZygn8J+bkSBbRmlsZVdhdGNoZXJdIOW3suWBnOatouaJgOacieebkeWQrCcpO1xuICB9XG59XG4iXX0=
|
package/dist/index.d.ts
CHANGED
|
@@ -5,3 +5,66 @@ export interface HarnessPluginConfig {
|
|
|
5
5
|
protectedFiles: string[];
|
|
6
6
|
logsDir: string;
|
|
7
7
|
}
|
|
8
|
+
export declare class HarnessPlugin {
|
|
9
|
+
name: string;
|
|
10
|
+
version: string;
|
|
11
|
+
private config;
|
|
12
|
+
private workspacePath;
|
|
13
|
+
private configValidator;
|
|
14
|
+
private skillAuditor;
|
|
15
|
+
private loopDetector;
|
|
16
|
+
private configLogger;
|
|
17
|
+
private operationLogger;
|
|
18
|
+
private traceLogger;
|
|
19
|
+
constructor(workspacePath: string, config?: Partial<HarnessPluginConfig>);
|
|
20
|
+
/**
|
|
21
|
+
* Hook: 配置修改前验证
|
|
22
|
+
*/
|
|
23
|
+
onConfigChange(newConfig: any, sessionId?: string): Promise<{
|
|
24
|
+
valid: boolean;
|
|
25
|
+
errors?: string[];
|
|
26
|
+
}>;
|
|
27
|
+
/**
|
|
28
|
+
* 公开方法:记录配置变更
|
|
29
|
+
*/
|
|
30
|
+
logConfigChange(entry: {
|
|
31
|
+
sessionId: string;
|
|
32
|
+
modifier: string;
|
|
33
|
+
file: string;
|
|
34
|
+
reason: string;
|
|
35
|
+
verified: boolean;
|
|
36
|
+
gatewayRestarted: boolean;
|
|
37
|
+
changes: any[];
|
|
38
|
+
}): void;
|
|
39
|
+
/**
|
|
40
|
+
* Hook: Skill 安装前审核
|
|
41
|
+
*/
|
|
42
|
+
onSkillInstall(skillPath: string, source?: string, sessionId?: string): Promise<{
|
|
43
|
+
passed: boolean;
|
|
44
|
+
warnings?: any[];
|
|
45
|
+
}>;
|
|
46
|
+
/**
|
|
47
|
+
* Hook: 文件编辑时循环检测
|
|
48
|
+
*/
|
|
49
|
+
onFileEdit(filePath: string, sessionId?: string): {
|
|
50
|
+
allowed: boolean;
|
|
51
|
+
warning?: string;
|
|
52
|
+
};
|
|
53
|
+
/**
|
|
54
|
+
* Hook: 文件删除前检查
|
|
55
|
+
*/
|
|
56
|
+
onFileDelete(filePath: string, sessionId?: string): {
|
|
57
|
+
allowed: boolean;
|
|
58
|
+
reason?: string;
|
|
59
|
+
};
|
|
60
|
+
/**
|
|
61
|
+
* Hook: 系统命令执行前
|
|
62
|
+
*/
|
|
63
|
+
onExecCommand(command: string, sessionId?: string): void;
|
|
64
|
+
/**
|
|
65
|
+
* 获取插件状态
|
|
66
|
+
*/
|
|
67
|
+
getStatus(): any;
|
|
68
|
+
}
|
|
69
|
+
export declare function createPlugin(workspacePath: string, config: any): HarnessPlugin;
|
|
70
|
+
export default HarnessPlugin;
|