openclaw-safeclaw-plugin 0.5.1 → 0.7.1
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 +16 -21
- package/cli.tsx +153 -2
- package/dist/cli.js +159 -2
- package/dist/index.js +1 -1
- package/index.ts +1 -1
- package/openclaw.plugin.json +31 -0
- package/package.json +7 -1
package/README.md
CHANGED
|
@@ -1,38 +1,33 @@
|
|
|
1
1
|
# openclaw-safeclaw-plugin
|
|
2
2
|
|
|
3
|
-
Neurosymbolic governance plugin for OpenClaw AI agents. Validates every tool call, message, and action against
|
|
3
|
+
Neurosymbolic governance plugin for OpenClaw AI agents. Validates every tool call, message, and action against safety constraints before execution.
|
|
4
4
|
|
|
5
5
|
## Install
|
|
6
6
|
|
|
7
7
|
```bash
|
|
8
|
-
|
|
8
|
+
npm install -g openclaw-safeclaw-plugin
|
|
9
9
|
```
|
|
10
10
|
|
|
11
11
|
## Quick Start
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
1. Sign up at [safeclaw.eu](https://safeclaw.eu) and create an API key
|
|
14
|
+
2. Install and connect:
|
|
14
15
|
|
|
15
16
|
```bash
|
|
16
|
-
|
|
17
|
+
npm install -g openclaw-safeclaw-plugin
|
|
18
|
+
safeclaw connect <your-api-key>
|
|
19
|
+
safeclaw restart-openclaw
|
|
17
20
|
```
|
|
18
21
|
|
|
19
|
-
|
|
22
|
+
That's it. Every tool call your AI agent makes is now governed by SafeClaw.
|
|
20
23
|
|
|
21
|
-
##
|
|
24
|
+
## Commands
|
|
22
25
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
# Start the SafeClaw service
|
|
29
|
-
git clone https://github.com/tendlyeu/SafeClaw.git
|
|
30
|
-
cd SafeClaw/safeclaw-service
|
|
31
|
-
python -m venv .venv && source .venv/bin/activate
|
|
32
|
-
pip install -e ".[dev]"
|
|
33
|
-
safeclaw init --user-id yourname
|
|
34
|
-
safeclaw serve
|
|
35
|
-
# Engine ready on http://localhost:8420
|
|
26
|
+
```
|
|
27
|
+
safeclaw connect <api-key> Connect to SafeClaw and register with OpenClaw
|
|
28
|
+
safeclaw setup Register plugin with OpenClaw (no key needed)
|
|
29
|
+
safeclaw tui Open the interactive settings TUI
|
|
30
|
+
safeclaw restart-openclaw Restart the OpenClaw daemon
|
|
36
31
|
```
|
|
37
32
|
|
|
38
33
|
## What It Does
|
|
@@ -60,11 +55,11 @@ Set via environment variables or `~/.safeclaw/config.json`:
|
|
|
60
55
|
| Variable | Default | Description |
|
|
61
56
|
|----------|---------|-------------|
|
|
62
57
|
| `SAFECLAW_URL` | `https://api.safeclaw.eu/api/v1` | SafeClaw service URL |
|
|
63
|
-
| `SAFECLAW_API_KEY` | *(empty)* | API key
|
|
58
|
+
| `SAFECLAW_API_KEY` | *(empty)* | API key (set automatically by `safeclaw connect`) |
|
|
64
59
|
| `SAFECLAW_TIMEOUT_MS` | `500` | Request timeout in ms |
|
|
65
60
|
| `SAFECLAW_ENABLED` | `true` | Set `false` to disable |
|
|
66
61
|
| `SAFECLAW_ENFORCEMENT` | `enforce` | `enforce`, `warn-only`, `audit-only`, or `disabled` |
|
|
67
|
-
| `SAFECLAW_FAIL_MODE` | `
|
|
62
|
+
| `SAFECLAW_FAIL_MODE` | `open` | `open` (allow on failure) or `closed` (block on failure) |
|
|
68
63
|
|
|
69
64
|
## Enforcement Modes
|
|
70
65
|
|
package/cli.tsx
CHANGED
|
@@ -7,6 +7,35 @@ import { join } from 'path';
|
|
|
7
7
|
import { homedir } from 'os';
|
|
8
8
|
import App from './tui/App.js';
|
|
9
9
|
|
|
10
|
+
function registerWithOpenClaw(): boolean {
|
|
11
|
+
// Use OpenClaw's native plugin install mechanism
|
|
12
|
+
try {
|
|
13
|
+
execSync('openclaw plugins install openclaw-safeclaw-plugin', {
|
|
14
|
+
encoding: 'utf-8',
|
|
15
|
+
timeout: 30000,
|
|
16
|
+
stdio: 'pipe',
|
|
17
|
+
});
|
|
18
|
+
return true;
|
|
19
|
+
} catch {
|
|
20
|
+
// Fallback: try linking from the global npm install location
|
|
21
|
+
try {
|
|
22
|
+
const globalRoot = execSync('npm root -g', { encoding: 'utf-8', timeout: 5000 }).trim();
|
|
23
|
+
const pluginPath = join(globalRoot, 'openclaw-safeclaw-plugin');
|
|
24
|
+
if (existsSync(pluginPath)) {
|
|
25
|
+
execSync(`openclaw plugins install --link "${pluginPath}"`, {
|
|
26
|
+
encoding: 'utf-8',
|
|
27
|
+
timeout: 15000,
|
|
28
|
+
stdio: 'pipe',
|
|
29
|
+
});
|
|
30
|
+
return true;
|
|
31
|
+
}
|
|
32
|
+
} catch {
|
|
33
|
+
// Both methods failed
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
|
|
10
39
|
const args = process.argv.slice(2);
|
|
11
40
|
const command = args[0];
|
|
12
41
|
|
|
@@ -22,6 +51,12 @@ if (command === 'connect') {
|
|
|
22
51
|
process.exit(1);
|
|
23
52
|
}
|
|
24
53
|
|
|
54
|
+
if (!apiKey.startsWith('sc_')) {
|
|
55
|
+
console.error('Error: Invalid API key. Keys start with "sc_".');
|
|
56
|
+
console.error('Get your key at https://safeclaw.eu/dashboard');
|
|
57
|
+
process.exit(1);
|
|
58
|
+
}
|
|
59
|
+
|
|
25
60
|
const configDir = join(homedir(), '.safeclaw');
|
|
26
61
|
const configPath = join(configDir, 'config.json');
|
|
27
62
|
|
|
@@ -47,7 +82,22 @@ if (command === 'connect') {
|
|
|
47
82
|
writeFileSync(configPath, JSON.stringify(config, null, 2) + '\n');
|
|
48
83
|
chmodSync(configPath, 0o600);
|
|
49
84
|
|
|
50
|
-
console.log(`Connected!
|
|
85
|
+
console.log(`Connected! API key saved to ${configPath}`);
|
|
86
|
+
|
|
87
|
+
// Register with OpenClaw
|
|
88
|
+
console.log('Registering SafeClaw plugin with OpenClaw...');
|
|
89
|
+
const registered = registerWithOpenClaw();
|
|
90
|
+
if (registered) {
|
|
91
|
+
console.log('SafeClaw plugin registered with OpenClaw.');
|
|
92
|
+
console.log('');
|
|
93
|
+
console.log('Restart OpenClaw to activate:');
|
|
94
|
+
console.log(' safeclaw restart-openclaw');
|
|
95
|
+
} else {
|
|
96
|
+
console.log('');
|
|
97
|
+
console.log('Could not auto-register with OpenClaw.');
|
|
98
|
+
console.log('Register manually:');
|
|
99
|
+
console.log(' openclaw plugins install openclaw-safeclaw-plugin');
|
|
100
|
+
}
|
|
51
101
|
} else if (command === 'tui') {
|
|
52
102
|
render(React.createElement(App));
|
|
53
103
|
} else if (command === 'restart-openclaw') {
|
|
@@ -60,11 +110,112 @@ if (command === 'connect') {
|
|
|
60
110
|
console.error('Failed to restart OpenClaw daemon:', message);
|
|
61
111
|
process.exit(1);
|
|
62
112
|
}
|
|
113
|
+
} else if (command === 'setup') {
|
|
114
|
+
console.log('Registering SafeClaw plugin with OpenClaw...');
|
|
115
|
+
const registered = registerWithOpenClaw();
|
|
116
|
+
if (registered) {
|
|
117
|
+
console.log('SafeClaw plugin registered with OpenClaw.');
|
|
118
|
+
console.log('');
|
|
119
|
+
console.log('Next steps:');
|
|
120
|
+
console.log(' 1. Get an API key at https://safeclaw.eu/dashboard');
|
|
121
|
+
console.log(' 2. Run: safeclaw connect <your-api-key>');
|
|
122
|
+
console.log(' 3. Run: safeclaw restart-openclaw');
|
|
123
|
+
} else {
|
|
124
|
+
console.log('Could not auto-register.');
|
|
125
|
+
console.log('Try: openclaw plugins install openclaw-safeclaw-plugin');
|
|
126
|
+
}
|
|
127
|
+
} else if (command === 'status') {
|
|
128
|
+
const configPath = join(homedir(), '.safeclaw', 'config.json');
|
|
129
|
+
let allOk = true;
|
|
130
|
+
|
|
131
|
+
// 1. Config file
|
|
132
|
+
if (existsSync(configPath)) {
|
|
133
|
+
console.log('[ok] Config file: ' + configPath);
|
|
134
|
+
} else {
|
|
135
|
+
console.log('[!!] Config file not found. Run: safeclaw connect <api-key>');
|
|
136
|
+
allOk = false;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// 2. API key
|
|
140
|
+
let apiKey = '';
|
|
141
|
+
let serviceUrl = 'https://api.safeclaw.eu/api/v1';
|
|
142
|
+
if (existsSync(configPath)) {
|
|
143
|
+
try {
|
|
144
|
+
const cfg = JSON.parse(readFileSync(configPath, 'utf-8'));
|
|
145
|
+
const remote = cfg.remote as Record<string, string> | undefined;
|
|
146
|
+
apiKey = remote?.apiKey ?? '';
|
|
147
|
+
serviceUrl = remote?.serviceUrl ?? serviceUrl;
|
|
148
|
+
} catch { /* ignore */ }
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
if (apiKey && apiKey.startsWith('sc_')) {
|
|
152
|
+
console.log('[ok] API key: configured (sc_...)');
|
|
153
|
+
} else if (apiKey) {
|
|
154
|
+
console.log('[!!] API key: invalid (must start with sc_)');
|
|
155
|
+
allOk = false;
|
|
156
|
+
} else {
|
|
157
|
+
console.log('[!!] API key: not set. Run: safeclaw connect <api-key>');
|
|
158
|
+
allOk = false;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// 3. SafeClaw service reachable
|
|
162
|
+
try {
|
|
163
|
+
const res = await fetch(`${serviceUrl}/health`, {
|
|
164
|
+
signal: AbortSignal.timeout(5000),
|
|
165
|
+
headers: apiKey ? { 'Authorization': `Bearer ${apiKey}` } : {},
|
|
166
|
+
});
|
|
167
|
+
if (res.ok) {
|
|
168
|
+
const data = await res.json() as Record<string, unknown>;
|
|
169
|
+
console.log(`[ok] SafeClaw service: ${data.status ?? 'ok'} (${serviceUrl})`);
|
|
170
|
+
} else {
|
|
171
|
+
console.log(`[!!] SafeClaw service: HTTP ${res.status} (${serviceUrl})`);
|
|
172
|
+
allOk = false;
|
|
173
|
+
}
|
|
174
|
+
} catch {
|
|
175
|
+
console.log(`[!!] SafeClaw service: unreachable (${serviceUrl})`);
|
|
176
|
+
allOk = false;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// 4. OpenClaw installed
|
|
180
|
+
try {
|
|
181
|
+
execSync('which openclaw', { encoding: 'utf-8', stdio: 'pipe' });
|
|
182
|
+
console.log('[ok] OpenClaw: installed');
|
|
183
|
+
} catch {
|
|
184
|
+
console.log('[!!] OpenClaw: not found in PATH');
|
|
185
|
+
allOk = false;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// 5. Plugin registered with OpenClaw
|
|
189
|
+
try {
|
|
190
|
+
const pluginList = execSync('openclaw plugins list', {
|
|
191
|
+
encoding: 'utf-8',
|
|
192
|
+
timeout: 10000,
|
|
193
|
+
stdio: 'pipe',
|
|
194
|
+
});
|
|
195
|
+
if (pluginList.includes('safeclaw')) {
|
|
196
|
+
console.log('[ok] Plugin: registered with OpenClaw');
|
|
197
|
+
} else {
|
|
198
|
+
console.log('[!!] Plugin: not registered with OpenClaw. Run: safeclaw setup');
|
|
199
|
+
allOk = false;
|
|
200
|
+
}
|
|
201
|
+
} catch {
|
|
202
|
+
console.log('[??] Plugin: could not check OpenClaw plugin list');
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
// Summary
|
|
206
|
+
console.log('');
|
|
207
|
+
if (allOk) {
|
|
208
|
+
console.log('All checks passed. SafeClaw is ready.');
|
|
209
|
+
} else {
|
|
210
|
+
console.log('Some checks failed. Fix the issues above.');
|
|
211
|
+
}
|
|
63
212
|
} else {
|
|
64
213
|
console.log('Usage: safeclaw <command>');
|
|
65
214
|
console.log('');
|
|
66
215
|
console.log('Commands:');
|
|
67
|
-
console.log(' connect <api-key>
|
|
216
|
+
console.log(' connect <api-key> Connect to SafeClaw and register with OpenClaw');
|
|
217
|
+
console.log(' setup Register SafeClaw plugin with OpenClaw (no key needed)');
|
|
218
|
+
console.log(' status Check SafeClaw + OpenClaw connection status');
|
|
68
219
|
console.log(' tui Open the interactive SafeClaw settings TUI');
|
|
69
220
|
console.log(' restart-openclaw Restart the OpenClaw daemon');
|
|
70
221
|
process.exit(0);
|
package/dist/cli.js
CHANGED
|
@@ -6,6 +6,36 @@ import { readFileSync, writeFileSync, mkdirSync, chmodSync, existsSync } from 'f
|
|
|
6
6
|
import { join } from 'path';
|
|
7
7
|
import { homedir } from 'os';
|
|
8
8
|
import App from './tui/App.js';
|
|
9
|
+
function registerWithOpenClaw() {
|
|
10
|
+
// Use OpenClaw's native plugin install mechanism
|
|
11
|
+
try {
|
|
12
|
+
execSync('openclaw plugins install openclaw-safeclaw-plugin', {
|
|
13
|
+
encoding: 'utf-8',
|
|
14
|
+
timeout: 30000,
|
|
15
|
+
stdio: 'pipe',
|
|
16
|
+
});
|
|
17
|
+
return true;
|
|
18
|
+
}
|
|
19
|
+
catch {
|
|
20
|
+
// Fallback: try linking from the global npm install location
|
|
21
|
+
try {
|
|
22
|
+
const globalRoot = execSync('npm root -g', { encoding: 'utf-8', timeout: 5000 }).trim();
|
|
23
|
+
const pluginPath = join(globalRoot, 'openclaw-safeclaw-plugin');
|
|
24
|
+
if (existsSync(pluginPath)) {
|
|
25
|
+
execSync(`openclaw plugins install --link "${pluginPath}"`, {
|
|
26
|
+
encoding: 'utf-8',
|
|
27
|
+
timeout: 15000,
|
|
28
|
+
stdio: 'pipe',
|
|
29
|
+
});
|
|
30
|
+
return true;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
// Both methods failed
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return false;
|
|
38
|
+
}
|
|
9
39
|
const args = process.argv.slice(2);
|
|
10
40
|
const command = args[0];
|
|
11
41
|
if (command === 'connect') {
|
|
@@ -18,6 +48,11 @@ if (command === 'connect') {
|
|
|
18
48
|
console.error('Usage: safeclaw connect <api-key> [--service-url <url>]');
|
|
19
49
|
process.exit(1);
|
|
20
50
|
}
|
|
51
|
+
if (!apiKey.startsWith('sc_')) {
|
|
52
|
+
console.error('Error: Invalid API key. Keys start with "sc_".');
|
|
53
|
+
console.error('Get your key at https://safeclaw.eu/dashboard');
|
|
54
|
+
process.exit(1);
|
|
55
|
+
}
|
|
21
56
|
const configDir = join(homedir(), '.safeclaw');
|
|
22
57
|
const configPath = join(configDir, 'config.json');
|
|
23
58
|
// Load existing config or start fresh
|
|
@@ -40,7 +75,22 @@ if (command === 'connect') {
|
|
|
40
75
|
mkdirSync(configDir, { recursive: true });
|
|
41
76
|
writeFileSync(configPath, JSON.stringify(config, null, 2) + '\n');
|
|
42
77
|
chmodSync(configPath, 0o600);
|
|
43
|
-
console.log(`Connected!
|
|
78
|
+
console.log(`Connected! API key saved to ${configPath}`);
|
|
79
|
+
// Register with OpenClaw
|
|
80
|
+
console.log('Registering SafeClaw plugin with OpenClaw...');
|
|
81
|
+
const registered = registerWithOpenClaw();
|
|
82
|
+
if (registered) {
|
|
83
|
+
console.log('SafeClaw plugin registered with OpenClaw.');
|
|
84
|
+
console.log('');
|
|
85
|
+
console.log('Restart OpenClaw to activate:');
|
|
86
|
+
console.log(' safeclaw restart-openclaw');
|
|
87
|
+
}
|
|
88
|
+
else {
|
|
89
|
+
console.log('');
|
|
90
|
+
console.log('Could not auto-register with OpenClaw.');
|
|
91
|
+
console.log('Register manually:');
|
|
92
|
+
console.log(' openclaw plugins install openclaw-safeclaw-plugin');
|
|
93
|
+
}
|
|
44
94
|
}
|
|
45
95
|
else if (command === 'tui') {
|
|
46
96
|
render(React.createElement(App));
|
|
@@ -57,11 +107,118 @@ else if (command === 'restart-openclaw') {
|
|
|
57
107
|
process.exit(1);
|
|
58
108
|
}
|
|
59
109
|
}
|
|
110
|
+
else if (command === 'setup') {
|
|
111
|
+
console.log('Registering SafeClaw plugin with OpenClaw...');
|
|
112
|
+
const registered = registerWithOpenClaw();
|
|
113
|
+
if (registered) {
|
|
114
|
+
console.log('SafeClaw plugin registered with OpenClaw.');
|
|
115
|
+
console.log('');
|
|
116
|
+
console.log('Next steps:');
|
|
117
|
+
console.log(' 1. Get an API key at https://safeclaw.eu/dashboard');
|
|
118
|
+
console.log(' 2. Run: safeclaw connect <your-api-key>');
|
|
119
|
+
console.log(' 3. Run: safeclaw restart-openclaw');
|
|
120
|
+
}
|
|
121
|
+
else {
|
|
122
|
+
console.log('Could not auto-register.');
|
|
123
|
+
console.log('Try: openclaw plugins install openclaw-safeclaw-plugin');
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
else if (command === 'status') {
|
|
127
|
+
const configPath = join(homedir(), '.safeclaw', 'config.json');
|
|
128
|
+
let allOk = true;
|
|
129
|
+
// 1. Config file
|
|
130
|
+
if (existsSync(configPath)) {
|
|
131
|
+
console.log('[ok] Config file: ' + configPath);
|
|
132
|
+
}
|
|
133
|
+
else {
|
|
134
|
+
console.log('[!!] Config file not found. Run: safeclaw connect <api-key>');
|
|
135
|
+
allOk = false;
|
|
136
|
+
}
|
|
137
|
+
// 2. API key
|
|
138
|
+
let apiKey = '';
|
|
139
|
+
let serviceUrl = 'https://api.safeclaw.eu/api/v1';
|
|
140
|
+
if (existsSync(configPath)) {
|
|
141
|
+
try {
|
|
142
|
+
const cfg = JSON.parse(readFileSync(configPath, 'utf-8'));
|
|
143
|
+
const remote = cfg.remote;
|
|
144
|
+
apiKey = remote?.apiKey ?? '';
|
|
145
|
+
serviceUrl = remote?.serviceUrl ?? serviceUrl;
|
|
146
|
+
}
|
|
147
|
+
catch { /* ignore */ }
|
|
148
|
+
}
|
|
149
|
+
if (apiKey && apiKey.startsWith('sc_')) {
|
|
150
|
+
console.log('[ok] API key: configured (sc_...)');
|
|
151
|
+
}
|
|
152
|
+
else if (apiKey) {
|
|
153
|
+
console.log('[!!] API key: invalid (must start with sc_)');
|
|
154
|
+
allOk = false;
|
|
155
|
+
}
|
|
156
|
+
else {
|
|
157
|
+
console.log('[!!] API key: not set. Run: safeclaw connect <api-key>');
|
|
158
|
+
allOk = false;
|
|
159
|
+
}
|
|
160
|
+
// 3. SafeClaw service reachable
|
|
161
|
+
try {
|
|
162
|
+
const res = await fetch(`${serviceUrl}/health`, {
|
|
163
|
+
signal: AbortSignal.timeout(5000),
|
|
164
|
+
headers: apiKey ? { 'Authorization': `Bearer ${apiKey}` } : {},
|
|
165
|
+
});
|
|
166
|
+
if (res.ok) {
|
|
167
|
+
const data = await res.json();
|
|
168
|
+
console.log(`[ok] SafeClaw service: ${data.status ?? 'ok'} (${serviceUrl})`);
|
|
169
|
+
}
|
|
170
|
+
else {
|
|
171
|
+
console.log(`[!!] SafeClaw service: HTTP ${res.status} (${serviceUrl})`);
|
|
172
|
+
allOk = false;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
catch {
|
|
176
|
+
console.log(`[!!] SafeClaw service: unreachable (${serviceUrl})`);
|
|
177
|
+
allOk = false;
|
|
178
|
+
}
|
|
179
|
+
// 4. OpenClaw installed
|
|
180
|
+
try {
|
|
181
|
+
execSync('which openclaw', { encoding: 'utf-8', stdio: 'pipe' });
|
|
182
|
+
console.log('[ok] OpenClaw: installed');
|
|
183
|
+
}
|
|
184
|
+
catch {
|
|
185
|
+
console.log('[!!] OpenClaw: not found in PATH');
|
|
186
|
+
allOk = false;
|
|
187
|
+
}
|
|
188
|
+
// 5. Plugin registered with OpenClaw
|
|
189
|
+
try {
|
|
190
|
+
const pluginList = execSync('openclaw plugins list', {
|
|
191
|
+
encoding: 'utf-8',
|
|
192
|
+
timeout: 10000,
|
|
193
|
+
stdio: 'pipe',
|
|
194
|
+
});
|
|
195
|
+
if (pluginList.includes('safeclaw')) {
|
|
196
|
+
console.log('[ok] Plugin: registered with OpenClaw');
|
|
197
|
+
}
|
|
198
|
+
else {
|
|
199
|
+
console.log('[!!] Plugin: not registered with OpenClaw. Run: safeclaw setup');
|
|
200
|
+
allOk = false;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
catch {
|
|
204
|
+
console.log('[??] Plugin: could not check OpenClaw plugin list');
|
|
205
|
+
}
|
|
206
|
+
// Summary
|
|
207
|
+
console.log('');
|
|
208
|
+
if (allOk) {
|
|
209
|
+
console.log('All checks passed. SafeClaw is ready.');
|
|
210
|
+
}
|
|
211
|
+
else {
|
|
212
|
+
console.log('Some checks failed. Fix the issues above.');
|
|
213
|
+
}
|
|
214
|
+
}
|
|
60
215
|
else {
|
|
61
216
|
console.log('Usage: safeclaw <command>');
|
|
62
217
|
console.log('');
|
|
63
218
|
console.log('Commands:');
|
|
64
|
-
console.log(' connect <api-key>
|
|
219
|
+
console.log(' connect <api-key> Connect to SafeClaw and register with OpenClaw');
|
|
220
|
+
console.log(' setup Register SafeClaw plugin with OpenClaw (no key needed)');
|
|
221
|
+
console.log(' status Check SafeClaw + OpenClaw connection status');
|
|
65
222
|
console.log(' tui Open the interactive SafeClaw settings TUI');
|
|
66
223
|
console.log(' restart-openclaw Restart the OpenClaw daemon');
|
|
67
224
|
process.exit(0);
|
package/dist/index.js
CHANGED
package/index.ts
CHANGED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "safeclaw",
|
|
3
|
+
"name": "SafeClaw Neurosymbolic Governance",
|
|
4
|
+
"description": "Validates AI agent actions against OWL ontologies and SHACL constraints before execution",
|
|
5
|
+
"version": "0.5.1",
|
|
6
|
+
"configSchema": {
|
|
7
|
+
"type": "object",
|
|
8
|
+
"additionalProperties": false,
|
|
9
|
+
"properties": {
|
|
10
|
+
"serviceUrl": {
|
|
11
|
+
"type": "string",
|
|
12
|
+
"description": "SafeClaw service URL",
|
|
13
|
+
"default": "https://api.safeclaw.eu/api/v1"
|
|
14
|
+
},
|
|
15
|
+
"apiKey": {
|
|
16
|
+
"type": "string",
|
|
17
|
+
"description": "SafeClaw API key"
|
|
18
|
+
},
|
|
19
|
+
"enforcement": {
|
|
20
|
+
"type": "string",
|
|
21
|
+
"enum": ["enforce", "warn-only", "audit-only", "disabled"],
|
|
22
|
+
"default": "enforce"
|
|
23
|
+
},
|
|
24
|
+
"failMode": {
|
|
25
|
+
"type": "string",
|
|
26
|
+
"enum": ["open", "closed"],
|
|
27
|
+
"default": "open"
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "openclaw-safeclaw-plugin",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.1",
|
|
4
4
|
"description": "SafeClaw Neurosymbolic Governance plugin for OpenClaw — validates AI agent actions against OWL ontologies and SHACL constraints",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -13,8 +13,14 @@
|
|
|
13
13
|
"typecheck": "tsc --noEmit",
|
|
14
14
|
"prepublishOnly": "npm run build"
|
|
15
15
|
},
|
|
16
|
+
"openclaw": {
|
|
17
|
+
"extensions": [
|
|
18
|
+
"dist/index.js"
|
|
19
|
+
]
|
|
20
|
+
},
|
|
16
21
|
"files": [
|
|
17
22
|
"dist/",
|
|
23
|
+
"openclaw.plugin.json",
|
|
18
24
|
"index.ts",
|
|
19
25
|
"cli.tsx",
|
|
20
26
|
"tui/",
|