openclaw-config-guardian 1.0.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.
- package/LICENSE +21 -0
- package/README.md +198 -0
- package/bin/cli.js +2 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +136 -0
- package/dist/cli.js.map +1 -0
- package/dist/core.d.ts +36 -0
- package/dist/core.d.ts.map +1 -0
- package/dist/core.js +228 -0
- package/dist/core.js.map +1 -0
- package/dist/daemon.d.ts +4 -0
- package/dist/daemon.d.ts.map +1 -0
- package/dist/daemon.js +42 -0
- package/dist/daemon.js.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -0
- package/dist/webui.d.ts +2 -0
- package/dist/webui.d.ts.map +1 -0
- package/dist/webui.js +77 -0
- package/dist/webui.js.map +1 -0
- package/openclaw.plugin.json +39 -0
- package/package.json +70 -0
- package/scripts/install.sh +89 -0
- package/scripts/postinstall.js +60 -0
- package/skills/config-guardian/SKILL.md +91 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 OpenClaw Config Guardian Contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
|
|
3
|
+
<img width="120" src="https://img.shields.io/badge/🛡️-Config_Guardian-blue?style=for-the-badge" alt="Config Guardian" />
|
|
4
|
+
|
|
5
|
+
# OpenClaw Config Guardian
|
|
6
|
+
|
|
7
|
+
**Auto backup & one-click rollback for OpenClaw configuration.**
|
|
8
|
+
|
|
9
|
+
[](https://www.npmjs.com/package/@openclaw/config-guardian)
|
|
10
|
+
[](LICENSE)
|
|
11
|
+
[](https://nodejs.org/)
|
|
12
|
+
|
|
13
|
+
</div>
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## ✨ Features
|
|
18
|
+
|
|
19
|
+
| Feature | Description |
|
|
20
|
+
|---------|-------------|
|
|
21
|
+
| 🔄 **Auto Backup** | Automatic daily backups at 2:00 AM (only when OpenClaw is healthy) |
|
|
22
|
+
| 🌐 **Web UI** | Beautiful web interface to manage backups |
|
|
23
|
+
| ⚡ **One-Click Rollback** | Restore to any backup point instantly |
|
|
24
|
+
| 🏥 **Health Check** | Verifies OpenClaw status before backup |
|
|
25
|
+
| 🧹 **Auto Cleanup** | Keeps only the latest N backups automatically |
|
|
26
|
+
| 🖥️ **CLI Support** | Full command-line interface |
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## 🚀 Quick Start
|
|
31
|
+
|
|
32
|
+
### Option 1: npx (No Installation)
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
# Check status
|
|
36
|
+
npx @openclaw/config-guardian status
|
|
37
|
+
|
|
38
|
+
# Create backup
|
|
39
|
+
npx @openclaw/config-guardian backup
|
|
40
|
+
|
|
41
|
+
# Start Web UI
|
|
42
|
+
npx @openclaw/config-guardian webui
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### Option 2: Global Install
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
# Install globally
|
|
49
|
+
npm install -g @openclaw/config-guardian
|
|
50
|
+
|
|
51
|
+
# Use shorthand
|
|
52
|
+
ocg status
|
|
53
|
+
ocg backup
|
|
54
|
+
ocg webui
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### Option 3: One-Line Install Script
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
curl -fsSL https://raw.githubusercontent.com/openclaw/config-guardian/main/scripts/install.sh | bash
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
## 📖 Usage
|
|
66
|
+
|
|
67
|
+
### CLI Commands
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
# View status
|
|
71
|
+
openclaw-config-guardian status
|
|
72
|
+
|
|
73
|
+
# Create backup immediately
|
|
74
|
+
openclaw-config-guardian backup
|
|
75
|
+
|
|
76
|
+
# List all backups
|
|
77
|
+
openclaw-config-guardian list
|
|
78
|
+
|
|
79
|
+
# Restore to specific backup
|
|
80
|
+
openclaw-config-guardian restore backup-2024-01-01T00-00-00-000Z
|
|
81
|
+
|
|
82
|
+
# Delete a backup
|
|
83
|
+
openclaw-config-guardian delete backup-2024-01-01T00-00-00-000Z
|
|
84
|
+
|
|
85
|
+
# Start Web UI
|
|
86
|
+
openclaw-config-guardian webui
|
|
87
|
+
|
|
88
|
+
# Show help
|
|
89
|
+
openclaw-config-guardian help
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### Web UI
|
|
93
|
+
|
|
94
|
+
Start the Web UI and open http://localhost:3456:
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
openclaw-config-guardian webui
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
Features:
|
|
101
|
+
- Toggle auto backup on/off
|
|
102
|
+
- View system status
|
|
103
|
+
- Create backups with one click
|
|
104
|
+
- Restore to any backup point
|
|
105
|
+
- Delete old backups
|
|
106
|
+
|
|
107
|
+
---
|
|
108
|
+
|
|
109
|
+
## ⚙️ Configuration
|
|
110
|
+
|
|
111
|
+
Edit `~/.openclaw/extensions/openclaw-config-guardian/config.json`:
|
|
112
|
+
|
|
113
|
+
```json
|
|
114
|
+
{
|
|
115
|
+
"autoBackup": true,
|
|
116
|
+
"maxBackups": 10,
|
|
117
|
+
"webUIPort": 3456,
|
|
118
|
+
"backupItems": [
|
|
119
|
+
"config.json",
|
|
120
|
+
"gateway.json",
|
|
121
|
+
"agents.json",
|
|
122
|
+
"skills.json",
|
|
123
|
+
"memory",
|
|
124
|
+
"workspace"
|
|
125
|
+
]
|
|
126
|
+
}
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
| Option | Description | Default |
|
|
130
|
+
|--------|-------------|---------|
|
|
131
|
+
| `autoBackup` | Enable automatic daily backups | `true` |
|
|
132
|
+
| `maxBackups` | Maximum backups to keep | `10` |
|
|
133
|
+
| `webUIPort` | Port for Web UI | `3456` |
|
|
134
|
+
| `backupItems` | Files/directories to backup | See above |
|
|
135
|
+
|
|
136
|
+
---
|
|
137
|
+
|
|
138
|
+
## 📦 What's Backed Up
|
|
139
|
+
|
|
140
|
+
By default, the following are backed up:
|
|
141
|
+
|
|
142
|
+
- `config.json` - Main configuration
|
|
143
|
+
- `gateway.json` - Gateway configuration
|
|
144
|
+
- `agents.json` - Agents configuration
|
|
145
|
+
- `skills.json` - Skills configuration
|
|
146
|
+
- `memory/` - Memory files
|
|
147
|
+
- `workspace/` - Workspace files
|
|
148
|
+
|
|
149
|
+
---
|
|
150
|
+
|
|
151
|
+
## 🔒 Safety Features
|
|
152
|
+
|
|
153
|
+
- **Emergency Backup**: Before rollback, current config is backed up
|
|
154
|
+
- **Health Check**: Only backs up when OpenClaw is running normally
|
|
155
|
+
- **Auto Cleanup**: Old backups are automatically deleted
|
|
156
|
+
- **Safe Restore**: Stops Gateway before restore, restarts after
|
|
157
|
+
|
|
158
|
+
---
|
|
159
|
+
|
|
160
|
+
## 🛠️ Development
|
|
161
|
+
|
|
162
|
+
```bash
|
|
163
|
+
# Clone the repo
|
|
164
|
+
git clone https://github.com/openclaw/config-guardian.git
|
|
165
|
+
cd config-guardian
|
|
166
|
+
|
|
167
|
+
# Install dependencies
|
|
168
|
+
npm install
|
|
169
|
+
|
|
170
|
+
# Build
|
|
171
|
+
npm run build
|
|
172
|
+
|
|
173
|
+
# Local install
|
|
174
|
+
npm install -g .
|
|
175
|
+
|
|
176
|
+
# Or use local script
|
|
177
|
+
bash scripts/install.sh --local
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
---
|
|
181
|
+
|
|
182
|
+
## 🤝 Contributing
|
|
183
|
+
|
|
184
|
+
Contributions are welcome! Please feel free to submit a Pull Request.
|
|
185
|
+
|
|
186
|
+
---
|
|
187
|
+
|
|
188
|
+
## 📄 License
|
|
189
|
+
|
|
190
|
+
MIT License - see [LICENSE](LICENSE) file for details.
|
|
191
|
+
|
|
192
|
+
---
|
|
193
|
+
|
|
194
|
+
<div align="center">
|
|
195
|
+
|
|
196
|
+
Made with ❤️ for the OpenClaw community
|
|
197
|
+
|
|
198
|
+
</div>
|
package/bin/cli.js
ADDED
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import { getConfig, createBackup, listBackups, restoreBackup, deleteBackup, checkOpenClawHealth } from './core.js';
|
|
2
|
+
function printUsage() {
|
|
3
|
+
console.log(`
|
|
4
|
+
🛡️ OpenClaw Config Guardian
|
|
5
|
+
=============================
|
|
6
|
+
|
|
7
|
+
Usage: openclaw-config-guardian <command> [options]
|
|
8
|
+
|
|
9
|
+
Commands:
|
|
10
|
+
install Install the plugin
|
|
11
|
+
uninstall Uninstall the plugin
|
|
12
|
+
status Show current status
|
|
13
|
+
backup Create a backup immediately
|
|
14
|
+
restore <backup-id> Restore to a specific backup
|
|
15
|
+
delete <backup-id> Delete a specific backup
|
|
16
|
+
list List all backups
|
|
17
|
+
webui [port] Start Web UI (default port: 3456)
|
|
18
|
+
config Show current configuration
|
|
19
|
+
help Show this help message
|
|
20
|
+
|
|
21
|
+
Examples:
|
|
22
|
+
openclaw-config-guardian backup
|
|
23
|
+
openclaw-config-guardian restore backup-2024-01-01T00-00-00-000Z
|
|
24
|
+
openclaw-config-guardian webui 8080
|
|
25
|
+
`);
|
|
26
|
+
}
|
|
27
|
+
function showStatus() {
|
|
28
|
+
const config = getConfig();
|
|
29
|
+
const backups = listBackups();
|
|
30
|
+
console.log('\n📊 Config Guardian 状态');
|
|
31
|
+
console.log('======================');
|
|
32
|
+
console.log('自动备份:', config.autoBackup ? '✅ 开启' : '❌ 关闭');
|
|
33
|
+
console.log('最大备份数:', config.maxBackups);
|
|
34
|
+
console.log('Web UI 端口:', config.webUIPort);
|
|
35
|
+
console.log('上次备份:', config.lastBackup || '无');
|
|
36
|
+
console.log('备份数量:', backups.length);
|
|
37
|
+
console.log('OpenClaw 状态:', checkOpenClawHealth() ? '🟢 运行中' : '🔴 未运行');
|
|
38
|
+
if (backups.length > 0) {
|
|
39
|
+
console.log('\n最近备份:');
|
|
40
|
+
backups.slice(0, 5).forEach(b => {
|
|
41
|
+
console.log(` • ${b.id} (${new Date(b.timestamp).toLocaleString()})`);
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
console.log();
|
|
45
|
+
}
|
|
46
|
+
function showConfig() {
|
|
47
|
+
const config = getConfig();
|
|
48
|
+
console.log('\n⚙️ 当前配置');
|
|
49
|
+
console.log('=============');
|
|
50
|
+
console.log(JSON.stringify(config, null, 2));
|
|
51
|
+
console.log();
|
|
52
|
+
}
|
|
53
|
+
function showList() {
|
|
54
|
+
const backups = listBackups();
|
|
55
|
+
if (backups.length === 0) {
|
|
56
|
+
console.log('\n📭 暂无备份\n');
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
console.log('\n📦 备份列表');
|
|
60
|
+
console.log('===========');
|
|
61
|
+
backups.forEach((b, i) => {
|
|
62
|
+
console.log(`${i + 1}. ${b.id}`);
|
|
63
|
+
console.log(` 时间: ${new Date(b.timestamp).toLocaleString()}`);
|
|
64
|
+
console.log(` 项目: ${b.items.join(', ')}`);
|
|
65
|
+
console.log();
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
async function main() {
|
|
69
|
+
const args = process.argv.slice(2);
|
|
70
|
+
const command = args[0];
|
|
71
|
+
switch (command) {
|
|
72
|
+
case 'install':
|
|
73
|
+
console.log('✅ 插件已安装!');
|
|
74
|
+
console.log('🌐 启动 Web UI: openclaw-config-guardian webui');
|
|
75
|
+
console.log('📊 查看状态: openclaw-config-guardian status');
|
|
76
|
+
break;
|
|
77
|
+
case 'uninstall':
|
|
78
|
+
console.log('🗑️ 插件已卸载');
|
|
79
|
+
break;
|
|
80
|
+
case 'status':
|
|
81
|
+
showStatus();
|
|
82
|
+
break;
|
|
83
|
+
case 'config':
|
|
84
|
+
showConfig();
|
|
85
|
+
break;
|
|
86
|
+
case 'backup':
|
|
87
|
+
console.log('💾 执行手动备份...');
|
|
88
|
+
const result = createBackup();
|
|
89
|
+
if (!result.success) {
|
|
90
|
+
process.exit(1);
|
|
91
|
+
}
|
|
92
|
+
break;
|
|
93
|
+
case 'restore':
|
|
94
|
+
const backupId = args[1];
|
|
95
|
+
if (!backupId) {
|
|
96
|
+
console.error('❌ 请指定备份 ID');
|
|
97
|
+
console.log('用法: openclaw-config-guardian restore <backup-id>');
|
|
98
|
+
showList();
|
|
99
|
+
process.exit(1);
|
|
100
|
+
}
|
|
101
|
+
restoreBackup(backupId);
|
|
102
|
+
break;
|
|
103
|
+
case 'delete':
|
|
104
|
+
const deleteId = args[1];
|
|
105
|
+
if (!deleteId) {
|
|
106
|
+
console.error('❌ 请指定备份 ID');
|
|
107
|
+
console.log('用法: openclaw-config-guardian delete <backup-id>');
|
|
108
|
+
process.exit(1);
|
|
109
|
+
}
|
|
110
|
+
const deleteResult = deleteBackup(deleteId);
|
|
111
|
+
if (!deleteResult.success) {
|
|
112
|
+
console.error('❌ 删除失败:', deleteResult.error);
|
|
113
|
+
process.exit(1);
|
|
114
|
+
}
|
|
115
|
+
break;
|
|
116
|
+
case 'list':
|
|
117
|
+
showList();
|
|
118
|
+
break;
|
|
119
|
+
case 'webui':
|
|
120
|
+
const port = args[1] ? parseInt(args[1]) : undefined;
|
|
121
|
+
const { startWebUI } = await import('./webui.js');
|
|
122
|
+
startWebUI(port);
|
|
123
|
+
break;
|
|
124
|
+
case 'help':
|
|
125
|
+
case '--help':
|
|
126
|
+
case '-h':
|
|
127
|
+
default:
|
|
128
|
+
printUsage();
|
|
129
|
+
break;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
main().catch(err => {
|
|
133
|
+
console.error('❌ 错误:', err);
|
|
134
|
+
process.exit(1);
|
|
135
|
+
});
|
|
136
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
package/dist/core.d.ts
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
export interface BackupConfig {
|
|
2
|
+
autoBackup: boolean;
|
|
3
|
+
maxBackups: number;
|
|
4
|
+
webUIPort: number;
|
|
5
|
+
backupItems: string[];
|
|
6
|
+
lastBackup?: string;
|
|
7
|
+
}
|
|
8
|
+
export interface BackupMeta {
|
|
9
|
+
timestamp: string;
|
|
10
|
+
version: string;
|
|
11
|
+
items: string[];
|
|
12
|
+
}
|
|
13
|
+
export interface BackupInfo {
|
|
14
|
+
id: string;
|
|
15
|
+
timestamp: string;
|
|
16
|
+
items: string[];
|
|
17
|
+
}
|
|
18
|
+
export declare function getConfig(): BackupConfig;
|
|
19
|
+
export declare function saveConfig(config: BackupConfig): void;
|
|
20
|
+
export declare function checkOpenClawHealth(): boolean;
|
|
21
|
+
export declare function createBackup(): {
|
|
22
|
+
success: boolean;
|
|
23
|
+
backupId?: string;
|
|
24
|
+
error?: string;
|
|
25
|
+
};
|
|
26
|
+
export declare function cleanupOldBackups(maxBackups?: number): void;
|
|
27
|
+
export declare function listBackups(): BackupInfo[];
|
|
28
|
+
export declare function restoreBackup(backupId: string): {
|
|
29
|
+
success: boolean;
|
|
30
|
+
error?: string;
|
|
31
|
+
};
|
|
32
|
+
export declare function deleteBackup(backupId: string): {
|
|
33
|
+
success: boolean;
|
|
34
|
+
error?: string;
|
|
35
|
+
};
|
|
36
|
+
//# sourceMappingURL=core.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"core.d.ts","sourceRoot":"","sources":["../src/core.ts"],"names":[],"mappings":"AAuBA,MAAM,WAAW,YAAY;IAC3B,UAAU,EAAE,OAAO,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,UAAU;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAED,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAED,wBAAgB,SAAS,IAAI,YAAY,CAYxC;AAED,wBAAgB,UAAU,CAAC,MAAM,EAAE,YAAY,GAAG,IAAI,CAGrD;AAED,wBAAgB,mBAAmB,IAAI,OAAO,CAO7C;AAED,wBAAgB,YAAY,IAAI;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAgEtF;AAED,wBAAgB,iBAAiB,CAAC,UAAU,GAAE,MAAW,GAAG,IAAI,CAkB/D;AAED,wBAAgB,WAAW,IAAI,UAAU,EAAE,CAoB1C;AAED,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CA6EpF;AAED,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAenF"}
|
package/dist/core.js
ADDED
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import { execSync } from 'child_process';
|
|
4
|
+
import { fileURLToPath } from 'url';
|
|
5
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
6
|
+
const __dirname = path.dirname(__filename);
|
|
7
|
+
const PLUGIN_DIR = path.join(process.env.HOME || process.env.USERPROFILE || '', '.openclaw', 'extensions', 'openclaw-config-guardian');
|
|
8
|
+
const CONFIG_FILE = path.join(PLUGIN_DIR, 'config.json');
|
|
9
|
+
const BACKUPS_DIR = path.join(PLUGIN_DIR, 'backups');
|
|
10
|
+
const OPENCLAW_DIR = path.join(process.env.HOME || process.env.USERPROFILE || '', '.openclaw');
|
|
11
|
+
// 默认配置
|
|
12
|
+
const DEFAULT_BACKUP_ITEMS = [
|
|
13
|
+
'config.json',
|
|
14
|
+
'gateway.json',
|
|
15
|
+
'agents.json',
|
|
16
|
+
'skills.json',
|
|
17
|
+
'memory',
|
|
18
|
+
'workspace'
|
|
19
|
+
];
|
|
20
|
+
export function getConfig() {
|
|
21
|
+
if (!fs.existsSync(CONFIG_FILE)) {
|
|
22
|
+
const defaultConfig = {
|
|
23
|
+
autoBackup: true,
|
|
24
|
+
maxBackups: 10,
|
|
25
|
+
webUIPort: 3456,
|
|
26
|
+
backupItems: DEFAULT_BACKUP_ITEMS
|
|
27
|
+
};
|
|
28
|
+
saveConfig(defaultConfig);
|
|
29
|
+
return defaultConfig;
|
|
30
|
+
}
|
|
31
|
+
return JSON.parse(fs.readFileSync(CONFIG_FILE, 'utf8'));
|
|
32
|
+
}
|
|
33
|
+
export function saveConfig(config) {
|
|
34
|
+
fs.mkdirSync(PLUGIN_DIR, { recursive: true });
|
|
35
|
+
fs.writeFileSync(CONFIG_FILE, JSON.stringify(config, null, 2));
|
|
36
|
+
}
|
|
37
|
+
export function checkOpenClawHealth() {
|
|
38
|
+
try {
|
|
39
|
+
const result = execSync('openclaw gateway status', { encoding: 'utf8', timeout: 10000 });
|
|
40
|
+
return result.includes('running') || result.includes('active');
|
|
41
|
+
}
|
|
42
|
+
catch {
|
|
43
|
+
return false;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
export function createBackup() {
|
|
47
|
+
const config = getConfig();
|
|
48
|
+
const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
|
|
49
|
+
const backupId = `backup-${timestamp}`;
|
|
50
|
+
const backupDir = path.join(BACKUPS_DIR, backupId);
|
|
51
|
+
console.log(`[${new Date().toLocaleString()}] 开始备份...`);
|
|
52
|
+
// 检查 OpenClaw 健康状态
|
|
53
|
+
if (!checkOpenClawHealth()) {
|
|
54
|
+
console.log('⚠️ OpenClaw 状态异常,跳过本次备份');
|
|
55
|
+
return { success: false, error: 'OpenClaw is not running' };
|
|
56
|
+
}
|
|
57
|
+
try {
|
|
58
|
+
fs.mkdirSync(backupDir, { recursive: true });
|
|
59
|
+
// 备份元数据
|
|
60
|
+
const meta = {
|
|
61
|
+
timestamp: new Date().toISOString(),
|
|
62
|
+
version: '1.0.0',
|
|
63
|
+
items: []
|
|
64
|
+
};
|
|
65
|
+
// 备份各项
|
|
66
|
+
for (const item of config.backupItems) {
|
|
67
|
+
const sourcePath = path.join(OPENCLAW_DIR, item);
|
|
68
|
+
const destPath = path.join(backupDir, item);
|
|
69
|
+
if (fs.existsSync(sourcePath)) {
|
|
70
|
+
const stat = fs.statSync(sourcePath);
|
|
71
|
+
if (stat.isDirectory()) {
|
|
72
|
+
fs.cpSync(sourcePath, destPath, { recursive: true });
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
fs.copyFileSync(sourcePath, destPath);
|
|
76
|
+
}
|
|
77
|
+
meta.items.push(item);
|
|
78
|
+
console.log(` ✓ ${item}`);
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
console.log(` ⚠ ${item} (不存在)`);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
// 保存元数据
|
|
85
|
+
fs.writeFileSync(path.join(backupDir, 'meta.json'), JSON.stringify(meta, null, 2));
|
|
86
|
+
// 更新配置
|
|
87
|
+
config.lastBackup = timestamp;
|
|
88
|
+
saveConfig(config);
|
|
89
|
+
// 清理旧备份
|
|
90
|
+
cleanupOldBackups(config.maxBackups);
|
|
91
|
+
console.log(`✅ 备份完成: ${backupId}`);
|
|
92
|
+
return { success: true, backupId };
|
|
93
|
+
}
|
|
94
|
+
catch (err) {
|
|
95
|
+
const error = err instanceof Error ? err.message : String(err);
|
|
96
|
+
console.error('❌ 备份失败:', error);
|
|
97
|
+
// 清理失败的备份
|
|
98
|
+
if (fs.existsSync(backupDir)) {
|
|
99
|
+
fs.rmSync(backupDir, { recursive: true });
|
|
100
|
+
}
|
|
101
|
+
return { success: false, error };
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
export function cleanupOldBackups(maxBackups = 10) {
|
|
105
|
+
if (!fs.existsSync(BACKUPS_DIR))
|
|
106
|
+
return;
|
|
107
|
+
const backups = fs.readdirSync(BACKUPS_DIR)
|
|
108
|
+
.filter(d => d.startsWith('backup-'))
|
|
109
|
+
.map(d => ({
|
|
110
|
+
name: d,
|
|
111
|
+
path: path.join(BACKUPS_DIR, d),
|
|
112
|
+
time: fs.statSync(path.join(BACKUPS_DIR, d)).mtime.getTime()
|
|
113
|
+
}))
|
|
114
|
+
.sort((a, b) => b.time - a.time);
|
|
115
|
+
// 保留最近 N 个
|
|
116
|
+
const toDelete = backups.slice(maxBackups);
|
|
117
|
+
for (const backup of toDelete) {
|
|
118
|
+
fs.rmSync(backup.path, { recursive: true });
|
|
119
|
+
console.log(`🗑️ 清理旧备份: ${backup.name}`);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
export function listBackups() {
|
|
123
|
+
if (!fs.existsSync(BACKUPS_DIR)) {
|
|
124
|
+
return [];
|
|
125
|
+
}
|
|
126
|
+
return fs.readdirSync(BACKUPS_DIR)
|
|
127
|
+
.filter(d => d.startsWith('backup-'))
|
|
128
|
+
.map(d => {
|
|
129
|
+
const metaPath = path.join(BACKUPS_DIR, d, 'meta.json');
|
|
130
|
+
let meta = {};
|
|
131
|
+
if (fs.existsSync(metaPath)) {
|
|
132
|
+
meta = JSON.parse(fs.readFileSync(metaPath, 'utf8'));
|
|
133
|
+
}
|
|
134
|
+
return {
|
|
135
|
+
id: d,
|
|
136
|
+
timestamp: meta.timestamp || d.replace('backup-', ''),
|
|
137
|
+
items: meta.items || []
|
|
138
|
+
};
|
|
139
|
+
})
|
|
140
|
+
.sort((a, b) => new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime());
|
|
141
|
+
}
|
|
142
|
+
export function restoreBackup(backupId) {
|
|
143
|
+
const backupDir = path.join(BACKUPS_DIR, backupId);
|
|
144
|
+
if (!fs.existsSync(backupDir)) {
|
|
145
|
+
console.error(`❌ 备份不存在: ${backupId}`);
|
|
146
|
+
return { success: false, error: `Backup not found: ${backupId}` };
|
|
147
|
+
}
|
|
148
|
+
console.log(`🔄 准备回滚到: ${backupId}`);
|
|
149
|
+
console.log('⚠️ 这将覆盖当前配置,请确认...');
|
|
150
|
+
try {
|
|
151
|
+
// 先创建当前配置的紧急备份
|
|
152
|
+
const emergencyBackup = path.join(BACKUPS_DIR, `emergency-${Date.now()}`);
|
|
153
|
+
fs.mkdirSync(emergencyBackup, { recursive: true });
|
|
154
|
+
const items = ['config.json', 'gateway.json', 'agents.json', 'skills.json'];
|
|
155
|
+
for (const item of items) {
|
|
156
|
+
const sourcePath = path.join(OPENCLAW_DIR, item);
|
|
157
|
+
if (fs.existsSync(sourcePath)) {
|
|
158
|
+
fs.copyFileSync(sourcePath, path.join(emergencyBackup, item));
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
console.log(`📦 已创建紧急备份: ${path.basename(emergencyBackup)}`);
|
|
162
|
+
// 停止 gateway
|
|
163
|
+
console.log('🛑 停止 OpenClaw Gateway...');
|
|
164
|
+
try {
|
|
165
|
+
execSync('openclaw gateway stop', { timeout: 30000 });
|
|
166
|
+
}
|
|
167
|
+
catch {
|
|
168
|
+
console.log(' ⚠️ gateway 可能未运行');
|
|
169
|
+
}
|
|
170
|
+
// 恢复备份
|
|
171
|
+
console.log('📂 恢复配置文件中...');
|
|
172
|
+
const metaPath = path.join(backupDir, 'meta.json');
|
|
173
|
+
const meta = fs.existsSync(metaPath)
|
|
174
|
+
? JSON.parse(fs.readFileSync(metaPath, 'utf8'))
|
|
175
|
+
: { items: [], timestamp: '', version: '' };
|
|
176
|
+
for (const item of meta.items || []) {
|
|
177
|
+
const sourcePath = path.join(backupDir, item);
|
|
178
|
+
const destPath = path.join(OPENCLAW_DIR, item);
|
|
179
|
+
if (fs.existsSync(sourcePath)) {
|
|
180
|
+
// 删除现有文件/目录
|
|
181
|
+
if (fs.existsSync(destPath)) {
|
|
182
|
+
fs.rmSync(destPath, { recursive: true });
|
|
183
|
+
}
|
|
184
|
+
// 复制备份
|
|
185
|
+
const stat = fs.statSync(sourcePath);
|
|
186
|
+
if (stat.isDirectory()) {
|
|
187
|
+
fs.cpSync(sourcePath, destPath, { recursive: true });
|
|
188
|
+
}
|
|
189
|
+
else {
|
|
190
|
+
fs.copyFileSync(sourcePath, destPath);
|
|
191
|
+
}
|
|
192
|
+
console.log(` ✓ ${item}`);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
// 启动 gateway
|
|
196
|
+
console.log('🚀 启动 OpenClaw Gateway...');
|
|
197
|
+
try {
|
|
198
|
+
execSync('openclaw gateway start', { timeout: 30000 });
|
|
199
|
+
console.log('✅ Gateway 已启动');
|
|
200
|
+
}
|
|
201
|
+
catch {
|
|
202
|
+
console.error('❌ 启动失败,请手动检查');
|
|
203
|
+
}
|
|
204
|
+
console.log('✅ 回滚完成!');
|
|
205
|
+
return { success: true };
|
|
206
|
+
}
|
|
207
|
+
catch (err) {
|
|
208
|
+
const error = err instanceof Error ? err.message : String(err);
|
|
209
|
+
console.error('❌ 回滚失败:', error);
|
|
210
|
+
return { success: false, error };
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
export function deleteBackup(backupId) {
|
|
214
|
+
const backupDir = path.join(BACKUPS_DIR, backupId);
|
|
215
|
+
if (!fs.existsSync(backupDir)) {
|
|
216
|
+
return { success: false, error: `Backup not found: ${backupId}` };
|
|
217
|
+
}
|
|
218
|
+
try {
|
|
219
|
+
fs.rmSync(backupDir, { recursive: true });
|
|
220
|
+
console.log(`🗑️ 已删除备份: ${backupId}`);
|
|
221
|
+
return { success: true };
|
|
222
|
+
}
|
|
223
|
+
catch (err) {
|
|
224
|
+
const error = err instanceof Error ? err.message : String(err);
|
|
225
|
+
return { success: false, error };
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
//# sourceMappingURL=core.js.map
|
package/dist/core.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"core.js","sourceRoot":"","sources":["../src/core.ts"],"names":[],"mappings":"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"}
|
package/dist/daemon.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"daemon.d.ts","sourceRoot":"","sources":["../src/daemon.ts"],"names":[],"mappings":"AAOA,wBAAgB,eAAe,IAAI,IAAI,CAYtC;AAED,wBAAgB,cAAc,IAAI,IAAI,CAMrC;AAED,wBAAgB,IAAI,IAAI,IAAI,CAmB3B"}
|
package/dist/daemon.js
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import cron from 'node-cron';
|
|
4
|
+
import { getConfig, createBackup } from './core.js';
|
|
5
|
+
let backupJob = null;
|
|
6
|
+
export function startAutoBackup() {
|
|
7
|
+
if (backupJob) {
|
|
8
|
+
backupJob.stop();
|
|
9
|
+
}
|
|
10
|
+
// 每24小时执行一次(每天凌晨2点)
|
|
11
|
+
backupJob = cron.schedule('0 2 * * *', () => {
|
|
12
|
+
console.log('[定时任务] 执行自动备份...');
|
|
13
|
+
createBackup();
|
|
14
|
+
});
|
|
15
|
+
console.log('✅ 自动备份已启用(每天凌晨2点)');
|
|
16
|
+
}
|
|
17
|
+
export function stopAutoBackup() {
|
|
18
|
+
if (backupJob) {
|
|
19
|
+
backupJob.stop();
|
|
20
|
+
backupJob = null;
|
|
21
|
+
}
|
|
22
|
+
console.log('⏹️ 自动备份已停止');
|
|
23
|
+
}
|
|
24
|
+
export function init() {
|
|
25
|
+
const config = getConfig();
|
|
26
|
+
if (config.autoBackup) {
|
|
27
|
+
startAutoBackup();
|
|
28
|
+
}
|
|
29
|
+
// 监听配置变化
|
|
30
|
+
const PLUGIN_DIR = path.join(process.env.HOME || process.env.USERPROFILE || '', '.openclaw', 'extensions', 'openclaw-config-guardian');
|
|
31
|
+
const CONFIG_FILE = path.join(PLUGIN_DIR, 'config.json');
|
|
32
|
+
fs.watchFile(CONFIG_FILE, () => {
|
|
33
|
+
const newConfig = getConfig();
|
|
34
|
+
if (newConfig.autoBackup && !backupJob) {
|
|
35
|
+
startAutoBackup();
|
|
36
|
+
}
|
|
37
|
+
else if (!newConfig.autoBackup && backupJob) {
|
|
38
|
+
stopAutoBackup();
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=daemon.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"daemon.js","sourceRoot":"","sources":["../src/daemon.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,SAAS,EAAc,YAAY,EAAE,MAAM,WAAW,CAAC;AAEhE,IAAI,SAAS,GAA8B,IAAI,CAAC;AAEhD,MAAM,UAAU,eAAe;IAC7B,IAAI,SAAS,EAAE,CAAC;QACd,SAAS,CAAC,IAAI,EAAE,CAAC;IACnB,CAAC;IAED,oBAAoB;IACpB,SAAS,GAAG,IAAI,CAAC,QAAQ,CAAC,WAAW,EAAE,GAAG,EAAE;QAC1C,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC;QAChC,YAAY,EAAE,CAAC;IACjB,CAAC,CAAC,CAAC;IAEH,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAC;AACnC,CAAC;AAED,MAAM,UAAU,cAAc;IAC5B,IAAI,SAAS,EAAE,CAAC;QACd,SAAS,CAAC,IAAI,EAAE,CAAC;QACjB,SAAS,GAAG,IAAI,CAAC;IACnB,CAAC;IACD,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;AAC7B,CAAC;AAED,MAAM,UAAU,IAAI;IAClB,MAAM,MAAM,GAAG,SAAS,EAAE,CAAC;IAE3B,IAAI,MAAM,CAAC,UAAU,EAAE,CAAC;QACtB,eAAe,EAAE,CAAC;IACpB,CAAC;IAED,SAAS;IACT,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,OAAO,CAAC,GAAG,CAAC,WAAW,IAAI,EAAE,EAAE,WAAW,EAAE,YAAY,EAAE,0BAA0B,CAAC,CAAC;IACvI,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,aAAa,CAAC,CAAC;IAEzD,EAAE,CAAC,SAAS,CAAC,WAAW,EAAE,GAAG,EAAE;QAC7B,MAAM,SAAS,GAAG,SAAS,EAAE,CAAC;QAC9B,IAAI,SAAS,CAAC,UAAU,IAAI,CAAC,SAAS,EAAE,CAAC;YACvC,eAAe,EAAE,CAAC;QACpB,CAAC;aAAM,IAAI,CAAC,SAAS,CAAC,UAAU,IAAI,SAAS,EAAE,CAAC;YAC9C,cAAc,EAAE,CAAC;QACnB,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAGnC,cAAc,WAAW,CAAC;AAC1B,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;;;;AAG5B,wBAAwB"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAEnC,SAAS;AACT,cAAc,WAAW,CAAC;AAC1B,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAE5B,OAAO;AACP,eAAe,EAAE,IAAI,EAAE,CAAC"}
|
package/dist/webui.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"webui.d.ts","sourceRoot":"","sources":["../src/webui.ts"],"names":[],"mappings":"AA2EA,wBAAgB,UAAU,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAQ9C"}
|
package/dist/webui.js
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import express from 'express';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import { fileURLToPath } from 'url';
|
|
4
|
+
import { getConfig, saveConfig, createBackup, listBackups, restoreBackup, deleteBackup, checkOpenClawHealth } from './core.js';
|
|
5
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
6
|
+
const __dirname = path.dirname(__filename);
|
|
7
|
+
const app = express();
|
|
8
|
+
app.use(express.json());
|
|
9
|
+
// 静态文件服务
|
|
10
|
+
const webuiPath = path.join(__dirname, '..', 'webui');
|
|
11
|
+
app.use(express.static(webuiPath));
|
|
12
|
+
// API 路由
|
|
13
|
+
// 获取配置
|
|
14
|
+
app.get('/api/config', (req, res) => {
|
|
15
|
+
res.json(getConfig());
|
|
16
|
+
});
|
|
17
|
+
// 更新配置
|
|
18
|
+
app.post('/api/config', (req, res) => {
|
|
19
|
+
const config = getConfig();
|
|
20
|
+
if (req.body.autoBackup !== undefined) {
|
|
21
|
+
config.autoBackup = req.body.autoBackup;
|
|
22
|
+
}
|
|
23
|
+
if (req.body.maxBackups !== undefined) {
|
|
24
|
+
config.maxBackups = req.body.maxBackups;
|
|
25
|
+
}
|
|
26
|
+
if (req.body.webUIPort !== undefined) {
|
|
27
|
+
config.webUIPort = req.body.webUIPort;
|
|
28
|
+
}
|
|
29
|
+
if (req.body.backupItems !== undefined) {
|
|
30
|
+
config.backupItems = req.body.backupItems;
|
|
31
|
+
}
|
|
32
|
+
saveConfig(config);
|
|
33
|
+
res.json({ success: true, config });
|
|
34
|
+
});
|
|
35
|
+
// 获取备份列表
|
|
36
|
+
app.get('/api/backups', (req, res) => {
|
|
37
|
+
res.json(listBackups());
|
|
38
|
+
});
|
|
39
|
+
// 立即备份
|
|
40
|
+
app.post('/api/backup', async (req, res) => {
|
|
41
|
+
const result = createBackup();
|
|
42
|
+
res.json(result);
|
|
43
|
+
});
|
|
44
|
+
// 回滚备份
|
|
45
|
+
app.post('/api/restore/:id', (req, res) => {
|
|
46
|
+
const backupId = req.params.id;
|
|
47
|
+
const result = restoreBackup(backupId);
|
|
48
|
+
res.json(result);
|
|
49
|
+
});
|
|
50
|
+
// 删除备份
|
|
51
|
+
app.delete('/api/backups/:id', (req, res) => {
|
|
52
|
+
const backupId = req.params.id;
|
|
53
|
+
const result = deleteBackup(backupId);
|
|
54
|
+
res.json(result);
|
|
55
|
+
});
|
|
56
|
+
// 获取 OpenClaw 状态
|
|
57
|
+
app.get('/api/status', (req, res) => {
|
|
58
|
+
res.json({
|
|
59
|
+
gateway: checkOpenClawHealth() ? 'running' : 'stopped',
|
|
60
|
+
config: getConfig()
|
|
61
|
+
});
|
|
62
|
+
});
|
|
63
|
+
// 启动服务器
|
|
64
|
+
export function startWebUI(port) {
|
|
65
|
+
const config = getConfig();
|
|
66
|
+
const actualPort = port || config.webUIPort || 3456;
|
|
67
|
+
app.listen(actualPort, () => {
|
|
68
|
+
console.log(`🌐 Config Guardian Web UI 已启动`);
|
|
69
|
+
console.log(`📍 访问地址: http://localhost:${actualPort}`);
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
// 如果是直接运行
|
|
73
|
+
if (import.meta.url === `file://${process.argv[1]}`) {
|
|
74
|
+
const port = process.argv[2] ? parseInt(process.argv[2]) : undefined;
|
|
75
|
+
startWebUI(port);
|
|
76
|
+
}
|
|
77
|
+
//# sourceMappingURL=webui.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"webui.js","sourceRoot":"","sources":["../src/webui.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "openclaw-config-guardian",
|
|
3
|
+
"name": "OpenClaw Config Guardian",
|
|
4
|
+
"description": "Auto backup & one-click rollback for OpenClaw configuration. Protect your configs with scheduled backups and easy restore via Web UI or CLI.",
|
|
5
|
+
"channels": [],
|
|
6
|
+
"extensions": [],
|
|
7
|
+
"skills": ["skills/config-guardian"],
|
|
8
|
+
"capabilities": {
|
|
9
|
+
"proactiveMessaging": false,
|
|
10
|
+
"cronJobs": true
|
|
11
|
+
},
|
|
12
|
+
"configSchema": {
|
|
13
|
+
"type": "object",
|
|
14
|
+
"additionalProperties": false,
|
|
15
|
+
"properties": {
|
|
16
|
+
"autoBackup": {
|
|
17
|
+
"type": "boolean",
|
|
18
|
+
"default": true,
|
|
19
|
+
"description": "Enable automatic daily backups at 2:00 AM"
|
|
20
|
+
},
|
|
21
|
+
"maxBackups": {
|
|
22
|
+
"type": "number",
|
|
23
|
+
"default": 10,
|
|
24
|
+
"description": "Maximum number of backups to keep (old ones auto-deleted)"
|
|
25
|
+
},
|
|
26
|
+
"webUIPort": {
|
|
27
|
+
"type": "number",
|
|
28
|
+
"default": 3456,
|
|
29
|
+
"description": "Port for the Web UI"
|
|
30
|
+
},
|
|
31
|
+
"backupItems": {
|
|
32
|
+
"type": "array",
|
|
33
|
+
"items": { "type": "string" },
|
|
34
|
+
"default": ["config.json", "gateway.json", "agents.json", "skills.json", "memory", "workspace"],
|
|
35
|
+
"description": "Files and directories to backup"
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "openclaw-config-guardian",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "OpenClaw Config Guardian - Auto backup & one-click rollback for OpenClaw configuration",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"bin": {
|
|
9
|
+
"openclaw-config-guardian": "bin/cli.js",
|
|
10
|
+
"ocg": "bin/cli.js"
|
|
11
|
+
},
|
|
12
|
+
"files": [
|
|
13
|
+
"dist",
|
|
14
|
+
"bin",
|
|
15
|
+
"scripts",
|
|
16
|
+
"skills",
|
|
17
|
+
"openclaw.plugin.json",
|
|
18
|
+
"README.md",
|
|
19
|
+
"LICENSE"
|
|
20
|
+
],
|
|
21
|
+
"openclaw": {
|
|
22
|
+
"id": "openclaw-config-guardian",
|
|
23
|
+
"extensions": [],
|
|
24
|
+
"skills": [
|
|
25
|
+
"skills/config-guardian"
|
|
26
|
+
]
|
|
27
|
+
},
|
|
28
|
+
"scripts": {
|
|
29
|
+
"build": "tsc",
|
|
30
|
+
"dev": "tsc --watch",
|
|
31
|
+
"prepack": "npm run build",
|
|
32
|
+
"postinstall": "node scripts/postinstall.js",
|
|
33
|
+
"test": "echo \"No tests yet\""
|
|
34
|
+
},
|
|
35
|
+
"keywords": [
|
|
36
|
+
"openclaw",
|
|
37
|
+
"openclaw-plugin",
|
|
38
|
+
"backup",
|
|
39
|
+
"config",
|
|
40
|
+
"guardian",
|
|
41
|
+
"rollback",
|
|
42
|
+
"restore"
|
|
43
|
+
],
|
|
44
|
+
"author": "dingclaw",
|
|
45
|
+
"license": "MIT",
|
|
46
|
+
"repository": {
|
|
47
|
+
"type": "git",
|
|
48
|
+
"url": "git+https://github.com/openclaw/config-guardian.git"
|
|
49
|
+
},
|
|
50
|
+
"bugs": {
|
|
51
|
+
"url": "https://github.com/openclaw/config-guardian/issues"
|
|
52
|
+
},
|
|
53
|
+
"homepage": "https://github.com/openclaw/config-guardian#readme",
|
|
54
|
+
"engines": {
|
|
55
|
+
"node": ">=18.0.0"
|
|
56
|
+
},
|
|
57
|
+
"dependencies": {
|
|
58
|
+
"express": "^4.18.2",
|
|
59
|
+
"node-cron": "^3.0.3"
|
|
60
|
+
},
|
|
61
|
+
"devDependencies": {
|
|
62
|
+
"@types/express": "^4.17.21",
|
|
63
|
+
"@types/node": "^20.0.0",
|
|
64
|
+
"@types/node-cron": "^3.0.11",
|
|
65
|
+
"typescript": "^5.9.3"
|
|
66
|
+
},
|
|
67
|
+
"peerDependencies": {
|
|
68
|
+
"openclaw": ">=1.0.0"
|
|
69
|
+
}
|
|
70
|
+
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
|
|
3
|
+
# OpenClaw Config Guardian 一键安装脚本
|
|
4
|
+
# 支持: npm install, npx, curl | bash
|
|
5
|
+
|
|
6
|
+
set -e
|
|
7
|
+
|
|
8
|
+
echo "🛡️ OpenClaw Config Guardian 安装器"
|
|
9
|
+
echo "======================================"
|
|
10
|
+
|
|
11
|
+
# 颜色定义
|
|
12
|
+
RED='\033[0;31m'
|
|
13
|
+
GREEN='\033[0;32m'
|
|
14
|
+
YELLOW='\033[1;33m'
|
|
15
|
+
NC='\033[0m' # No Color
|
|
16
|
+
|
|
17
|
+
# 检查 Node.js
|
|
18
|
+
if ! command -v node &> /dev/null; then
|
|
19
|
+
echo -e "${RED}❌ 未检测到 Node.js,请先安装 Node.js 18+${NC}"
|
|
20
|
+
echo " 访问: https://nodejs.org/"
|
|
21
|
+
exit 1
|
|
22
|
+
fi
|
|
23
|
+
|
|
24
|
+
NODE_VERSION=$(node --version | cut -d'v' -f2 | cut -d'.' -f1)
|
|
25
|
+
if [ "$NODE_VERSION" -lt 18 ]; then
|
|
26
|
+
echo -e "${RED}❌ Node.js 版本过低,需要 18+,当前: $(node --version)${NC}"
|
|
27
|
+
exit 1
|
|
28
|
+
fi
|
|
29
|
+
|
|
30
|
+
echo -e "${GREEN}✓ Node.js $(node --version)${NC}"
|
|
31
|
+
|
|
32
|
+
# 检查 npm
|
|
33
|
+
if ! command -v npm &> /dev/null; then
|
|
34
|
+
echo -e "${RED}❌ 未检测到 npm${NC}"
|
|
35
|
+
exit 1
|
|
36
|
+
fi
|
|
37
|
+
|
|
38
|
+
echo -e "${GREEN}✓ npm $(npm --version)${NC}"
|
|
39
|
+
|
|
40
|
+
# 检查 OpenClaw
|
|
41
|
+
if ! command -v openclaw &> /dev/null; then
|
|
42
|
+
echo -e "${YELLOW}⚠️ 未检测到 OpenClaw CLI${NC}"
|
|
43
|
+
echo " 插件仍可安装,但部分功能需要 OpenClaw"
|
|
44
|
+
else
|
|
45
|
+
echo -e "${GREEN}✓ OpenClaw 已安装${NC}"
|
|
46
|
+
fi
|
|
47
|
+
|
|
48
|
+
echo ""
|
|
49
|
+
echo "📦 正在安装 @openclaw/config-guardian..."
|
|
50
|
+
echo ""
|
|
51
|
+
|
|
52
|
+
# 安装方式选择
|
|
53
|
+
if [ "$1" == "--local" ] || [ "$1" == "-l" ]; then
|
|
54
|
+
# 本地开发安装
|
|
55
|
+
echo "🔧 本地开发模式"
|
|
56
|
+
npm install -g .
|
|
57
|
+
else
|
|
58
|
+
# 从 npm 安装
|
|
59
|
+
npm install -g @openclaw/config-guardian@latest
|
|
60
|
+
fi
|
|
61
|
+
|
|
62
|
+
echo ""
|
|
63
|
+
echo -e "${GREEN}✅ 安装完成!${NC}"
|
|
64
|
+
echo ""
|
|
65
|
+
echo "使用方法:"
|
|
66
|
+
echo ""
|
|
67
|
+
echo " 命令行:"
|
|
68
|
+
echo " ocg status - 查看状态"
|
|
69
|
+
echo " ocg backup - 立即备份"
|
|
70
|
+
echo " ocg restore <id> - 回滚到指定备份"
|
|
71
|
+
echo " ocg list - 列出所有备份"
|
|
72
|
+
echo " ocg webui - 启动 Web UI"
|
|
73
|
+
echo " ocg help - 显示帮助"
|
|
74
|
+
echo ""
|
|
75
|
+
echo " npx 方式 (无需全局安装):"
|
|
76
|
+
echo " npx @openclaw/config-guardian status"
|
|
77
|
+
echo " npx @openclaw/config-guardian webui"
|
|
78
|
+
echo ""
|
|
79
|
+
echo "🌐 Web UI 默认地址: http://localhost:3456"
|
|
80
|
+
echo ""
|
|
81
|
+
echo "配置文件: ~/.openclaw/extensions/openclaw-config-guardian/config.json"
|
|
82
|
+
echo ""
|
|
83
|
+
|
|
84
|
+
# 提示启动 Web UI
|
|
85
|
+
read -p "是否立即启动 Web UI? (y/N): " -n 1 -r
|
|
86
|
+
echo
|
|
87
|
+
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
|
88
|
+
ocg webui
|
|
89
|
+
fi
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import fs from 'fs';
|
|
4
|
+
import path from 'path';
|
|
5
|
+
import { execSync } from 'child_process';
|
|
6
|
+
import { fileURLToPath } from 'url';
|
|
7
|
+
|
|
8
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
9
|
+
const __dirname = path.dirname(__filename);
|
|
10
|
+
|
|
11
|
+
const PLUGIN_DIR = path.join(process.env.HOME || process.env.USERPROFILE || '', '.openclaw', 'extensions', 'openclaw-config-guardian');
|
|
12
|
+
|
|
13
|
+
console.log('🛡️ OpenClaw Config Guardian 安装后配置...');
|
|
14
|
+
|
|
15
|
+
try {
|
|
16
|
+
// 创建插件目录
|
|
17
|
+
fs.mkdirSync(PLUGIN_DIR, { recursive: true });
|
|
18
|
+
|
|
19
|
+
// 创建备份目录
|
|
20
|
+
fs.mkdirSync(path.join(PLUGIN_DIR, 'backups'), { recursive: true });
|
|
21
|
+
|
|
22
|
+
// 创建默认配置
|
|
23
|
+
const configPath = path.join(PLUGIN_DIR, 'config.json');
|
|
24
|
+
if (!fs.existsSync(configPath)) {
|
|
25
|
+
const defaultConfig = {
|
|
26
|
+
autoBackup: true,
|
|
27
|
+
maxBackups: 10,
|
|
28
|
+
webUIPort: 3456,
|
|
29
|
+
backupItems: [
|
|
30
|
+
'config.json',
|
|
31
|
+
'gateway.json',
|
|
32
|
+
'agents.json',
|
|
33
|
+
'skills.json',
|
|
34
|
+
'memory',
|
|
35
|
+
'workspace'
|
|
36
|
+
]
|
|
37
|
+
};
|
|
38
|
+
fs.writeFileSync(configPath, JSON.stringify(defaultConfig, null, 2));
|
|
39
|
+
console.log('✅ 默认配置已创建');
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
console.log('');
|
|
43
|
+
console.log('🎉 安装完成!');
|
|
44
|
+
console.log('');
|
|
45
|
+
console.log('快速开始:');
|
|
46
|
+
console.log(' npx openclaw-config-guardian status - 查看状态');
|
|
47
|
+
console.log(' npx openclaw-config-guardian backup - 立即备份');
|
|
48
|
+
console.log(' npx openclaw-config-guardian webui - 启动 Web UI');
|
|
49
|
+
console.log('');
|
|
50
|
+
console.log('或使用简写:');
|
|
51
|
+
console.log(' ocg status');
|
|
52
|
+
console.log(' ocg backup');
|
|
53
|
+
console.log(' ocg webui');
|
|
54
|
+
console.log('');
|
|
55
|
+
console.log('🌐 Web UI 地址: http://localhost:3456');
|
|
56
|
+
console.log('');
|
|
57
|
+
} catch (err) {
|
|
58
|
+
console.error('❌ 配置失败:', err.message);
|
|
59
|
+
process.exit(1);
|
|
60
|
+
}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: config-guardian
|
|
3
|
+
description: OpenClaw 配置守护者 - 自动备份与一键回滚。支持定时备份、Web UI 管理、命令行操作。
|
|
4
|
+
metadata: {"openclaw":{"emoji":"🛡️","requires":{"config":["config-guardian"]}}}
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Config Guardian 技能
|
|
8
|
+
|
|
9
|
+
## 功能
|
|
10
|
+
|
|
11
|
+
- 🔄 **自动备份**: 每天凌晨 2 点自动备份配置
|
|
12
|
+
- 🌐 **Web UI**: 图形界面管理备份
|
|
13
|
+
- ⚡ **一键回滚**: 快速恢复到任意备份点
|
|
14
|
+
- 🏥 **健康检测**: 备份前自动检查 OpenClaw 状态
|
|
15
|
+
- 🧹 **自动清理**: 保留最近 N 个备份,自动删除旧备份
|
|
16
|
+
|
|
17
|
+
## 使用方式
|
|
18
|
+
|
|
19
|
+
### 1. Web UI(推荐)
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
openclaw config-guardian webui
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
访问 http://localhost:3456
|
|
26
|
+
|
|
27
|
+
### 2. 命令行
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
# 查看状态
|
|
31
|
+
openclaw config-guardian status
|
|
32
|
+
|
|
33
|
+
# 立即备份
|
|
34
|
+
openclaw config-guardian backup
|
|
35
|
+
|
|
36
|
+
# 回滚到指定备份
|
|
37
|
+
openclaw config-guardian restore <backup-id>
|
|
38
|
+
|
|
39
|
+
# 列出所有备份
|
|
40
|
+
openclaw config-guardian list
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### 3. 配置
|
|
44
|
+
|
|
45
|
+
编辑 `~/.openclaw/config.json`:
|
|
46
|
+
|
|
47
|
+
```json
|
|
48
|
+
{
|
|
49
|
+
"config-guardian": {
|
|
50
|
+
"autoBackup": true,
|
|
51
|
+
"maxBackups": 10,
|
|
52
|
+
"webUIPort": 3456,
|
|
53
|
+
"backupItems": [
|
|
54
|
+
"config.json",
|
|
55
|
+
"gateway.json",
|
|
56
|
+
"agents.json",
|
|
57
|
+
"skills.json",
|
|
58
|
+
"memory",
|
|
59
|
+
"workspace"
|
|
60
|
+
]
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## 备份内容
|
|
66
|
+
|
|
67
|
+
默认备份以下文件和目录:
|
|
68
|
+
- `config.json` - 主配置
|
|
69
|
+
- `gateway.json` - 网关配置
|
|
70
|
+
- `agents.json` - 代理配置
|
|
71
|
+
- `skills.json` - 技能配置
|
|
72
|
+
- `memory/` - 记忆文件
|
|
73
|
+
- `workspace/` - 工作空间
|
|
74
|
+
|
|
75
|
+
## API 接口
|
|
76
|
+
|
|
77
|
+
Web UI 提供以下 REST API:
|
|
78
|
+
|
|
79
|
+
| 接口 | 方法 | 说明 |
|
|
80
|
+
|------|------|------|
|
|
81
|
+
| `/api/config` | GET/POST | 获取/更新配置 |
|
|
82
|
+
| `/api/backups` | GET | 获取备份列表 |
|
|
83
|
+
| `/api/backup` | POST | 立即执行备份 |
|
|
84
|
+
| `/api/restore/:id` | POST | 回滚到指定备份 |
|
|
85
|
+
| `/api/status` | GET | 获取 OpenClaw 状态 |
|
|
86
|
+
|
|
87
|
+
## 安全说明
|
|
88
|
+
|
|
89
|
+
- 回滚前会自动创建紧急备份
|
|
90
|
+
- 仅在 OpenClaw 运行正常时执行备份
|
|
91
|
+
- 备份文件存储在本地,不会上传云端
|