@clawtrial/courtroom 1.0.3-d → 1.0.3-g
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 +25 -27
- package/SKILL.md +18 -13
- package/package.json +1 -1
- package/scripts/clawtrial.js +27 -120
- package/src/index.js +14 -12
- package/src/skill.js +1 -14
package/README.md
CHANGED
|
@@ -9,23 +9,20 @@ AI Courtroom - Autonomous behavioral oversight for OpenClaw agents.
|
|
|
9
9
|
npm install -g @clawtrial/courtroom
|
|
10
10
|
```
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
**If `clawtrial` command not found:**
|
|
13
13
|
```bash
|
|
14
|
-
# Option 1: Add npm global bin to PATH
|
|
15
14
|
export PATH="$HOME/.npm-global/bin:$PATH"
|
|
16
|
-
|
|
17
|
-
# Option 2: Create symlink (requires sudo)
|
|
18
|
-
sudo ln -sf "$HOME/.npm-global/lib/node_modules/@clawtrial/courtroom/scripts/clawtrial.js" /usr/bin/clawtrial
|
|
15
|
+
# Or: sudo ln -sf "$HOME/.npm-global/lib/node_modules/@clawtrial/courtroom/scripts/clawtrial.js" /usr/bin/clawtrial
|
|
19
16
|
```
|
|
20
17
|
|
|
21
|
-
### 2. Setup
|
|
18
|
+
### 2. Setup (One-time)
|
|
22
19
|
```bash
|
|
23
20
|
clawtrial setup
|
|
24
21
|
```
|
|
25
22
|
|
|
26
|
-
### 3.
|
|
23
|
+
### 3. Restart ClawDBot
|
|
27
24
|
```bash
|
|
28
|
-
|
|
25
|
+
killall clawdbot && clawdbot
|
|
29
26
|
```
|
|
30
27
|
|
|
31
28
|
### 4. Verify
|
|
@@ -37,27 +34,28 @@ clawtrial status
|
|
|
37
34
|
|
|
38
35
|
## 📋 How It Works
|
|
39
36
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
37
|
+
The courtroom runs **automatically** as a ClawDBot skill:
|
|
38
|
+
|
|
39
|
+
1. **Install** - Package is installed globally
|
|
40
|
+
2. **Setup** - You grant consent via `clawtrial setup`
|
|
41
|
+
3. **Auto-load** - ClawDBot automatically loads the skill on restart
|
|
42
|
+
4. **Monitor** - Skill receives all messages and monitors for offenses
|
|
43
|
+
5. **File cases** - When offenses are detected, cases are filed automatically
|
|
44
44
|
|
|
45
|
-
**
|
|
45
|
+
**No manual start needed** - it runs within ClawDBot's process!
|
|
46
46
|
|
|
47
47
|
---
|
|
48
48
|
|
|
49
49
|
## 🎮 CLI Commands
|
|
50
50
|
|
|
51
51
|
```bash
|
|
52
|
-
clawtrial setup
|
|
53
|
-
clawtrial
|
|
54
|
-
clawtrial
|
|
55
|
-
clawtrial
|
|
56
|
-
clawtrial
|
|
57
|
-
clawtrial
|
|
58
|
-
clawtrial
|
|
59
|
-
clawtrial debug # View debug logs
|
|
60
|
-
clawtrial help # Show all commands
|
|
52
|
+
clawtrial setup # Interactive setup (run once)
|
|
53
|
+
clawtrial status # Check if courtroom is running
|
|
54
|
+
clawtrial disable # Pause monitoring
|
|
55
|
+
clawtrial enable # Resume monitoring
|
|
56
|
+
clawtrial revoke # Revoke consent and uninstall
|
|
57
|
+
clawtrial diagnose # Run diagnostics
|
|
58
|
+
clawtrial help # Show all commands
|
|
61
59
|
```
|
|
62
60
|
|
|
63
61
|
---
|
|
@@ -107,10 +105,10 @@ source ~/.bashrc # or ~/.zshrc
|
|
|
107
105
|
```
|
|
108
106
|
|
|
109
107
|
### "Courtroom not running"
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
108
|
+
The courtroom runs as a ClawDBot skill. Make sure:
|
|
109
|
+
1. You've run `clawtrial setup`
|
|
110
|
+
2. You've restarted ClawDBot after setup
|
|
111
|
+
3. Check `clawtrial diagnose` for details
|
|
114
112
|
|
|
115
113
|
### Need help?
|
|
116
114
|
```bash
|
|
@@ -125,7 +123,7 @@ clawtrial debug # Shows logs
|
|
|
125
123
|
```bash
|
|
126
124
|
npm install -g github:Assassin-1234/clawtrial
|
|
127
125
|
clawtrial setup
|
|
128
|
-
|
|
126
|
+
# Restart ClawDBot
|
|
129
127
|
```
|
|
130
128
|
|
|
131
129
|
---
|
package/SKILL.md
CHANGED
|
@@ -20,21 +20,26 @@ export PATH="$HOME/.npm-global/bin:$PATH"
|
|
|
20
20
|
# Or: sudo ln -sf "$HOME/.npm-global/lib/node_modules/@clawtrial/courtroom/scripts/clawtrial.js" /usr/bin/clawtrial
|
|
21
21
|
```
|
|
22
22
|
|
|
23
|
-
## Setup
|
|
23
|
+
## Setup (One-time)
|
|
24
24
|
|
|
25
25
|
```bash
|
|
26
|
-
clawtrial setup #
|
|
27
|
-
|
|
26
|
+
clawtrial setup # Grant consent and configure
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
**Then restart ClawDBot:**
|
|
30
|
+
```bash
|
|
31
|
+
killall clawdbot && clawdbot
|
|
28
32
|
```
|
|
29
33
|
|
|
30
34
|
## How It Works
|
|
31
35
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
36
|
+
The courtroom runs **automatically** as a ClawDBot skill:
|
|
37
|
+
|
|
38
|
+
1. **Install** - Package is installed globally
|
|
39
|
+
2. **Setup** - You grant consent via `clawtrial setup`
|
|
40
|
+
3. **Auto-load** - ClawDBot automatically loads the skill on restart
|
|
41
|
+
4. **Monitor** - Skill receives all messages and monitors for offenses
|
|
42
|
+
5. **File cases** - When offenses are detected, cases are filed automatically
|
|
38
43
|
|
|
39
44
|
## The 8 Offenses
|
|
40
45
|
|
|
@@ -52,12 +57,12 @@ Once started, the courtroom automatically:
|
|
|
52
57
|
## CLI Commands
|
|
53
58
|
|
|
54
59
|
```bash
|
|
55
|
-
clawtrial setup # Interactive setup
|
|
56
|
-
clawtrial
|
|
57
|
-
clawtrial status # Check status
|
|
60
|
+
clawtrial setup # Interactive setup (run once)
|
|
61
|
+
clawtrial status # Check if courtroom is running
|
|
58
62
|
clawtrial disable # Pause monitoring
|
|
59
63
|
clawtrial enable # Resume monitoring
|
|
60
|
-
clawtrial revoke #
|
|
64
|
+
clawtrial revoke # Revoke consent and uninstall
|
|
65
|
+
clawtrial diagnose # Run diagnostics
|
|
61
66
|
```
|
|
62
67
|
|
|
63
68
|
## View Cases
|
package/package.json
CHANGED
package/scripts/clawtrial.js
CHANGED
|
@@ -113,7 +113,8 @@ async function setup() {
|
|
|
113
113
|
api: {
|
|
114
114
|
enabled: true,
|
|
115
115
|
endpoint: 'https://api.clawtrial.app/api/v1/cases'
|
|
116
|
-
}
|
|
116
|
+
},
|
|
117
|
+
enabled: true
|
|
117
118
|
};
|
|
118
119
|
|
|
119
120
|
saveConfig(config);
|
|
@@ -135,19 +136,36 @@ async function setup() {
|
|
|
135
136
|
try { fs.unlinkSync(skillLinkPath); } catch (e) {}
|
|
136
137
|
}
|
|
137
138
|
|
|
138
|
-
//
|
|
139
|
-
|
|
140
|
-
try {
|
|
141
|
-
packagePath = require.resolve('@clawtrial/courtroom/package.json').replace('/package.json', '');
|
|
142
|
-
} catch (e) {
|
|
143
|
-
// Fallback to finding it relative to this script
|
|
144
|
-
packagePath = path.join(__dirname, '..');
|
|
145
|
-
}
|
|
139
|
+
// Get package path
|
|
140
|
+
const packagePath = path.join(__dirname, '..');
|
|
146
141
|
|
|
147
142
|
// Create symlink
|
|
148
143
|
fs.symlinkSync(packagePath, skillLinkPath, 'dir');
|
|
149
144
|
|
|
150
145
|
log('✓ Registered as ClawDBot skill');
|
|
146
|
+
|
|
147
|
+
// Also register as plugin in ClawDBot config
|
|
148
|
+
try {
|
|
149
|
+
const clawdbotConfigPath = path.join(process.env.HOME || '', '.clawdbot', 'clawdbot.json');
|
|
150
|
+
if (fs.existsSync(clawdbotConfigPath)) {
|
|
151
|
+
const clawdbotConfig = JSON.parse(fs.readFileSync(clawdbotConfigPath, 'utf8'));
|
|
152
|
+
if (!clawdbotConfig.plugins) {
|
|
153
|
+
clawdbotConfig.plugins = { entries: {} };
|
|
154
|
+
}
|
|
155
|
+
if (!clawdbotConfig.plugins.entries) {
|
|
156
|
+
clawdbotConfig.plugins.entries = {};
|
|
157
|
+
}
|
|
158
|
+
clawdbotConfig.plugins.entries.courtroom = {
|
|
159
|
+
enabled: true
|
|
160
|
+
};
|
|
161
|
+
fs.writeFileSync(clawdbotConfigPath, JSON.stringify(clawdbotConfig, null, 2));
|
|
162
|
+
log('✓ Registered as ClawDBot plugin');
|
|
163
|
+
}
|
|
164
|
+
} catch (pluginErr) {
|
|
165
|
+
log('⚠️ Could not register plugin: ' + pluginErr.message);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
log(' Restart ClawDBot to activate monitoring');
|
|
151
169
|
} catch (err) {
|
|
152
170
|
log('⚠️ Could not auto-register: ' + err.message);
|
|
153
171
|
log(' You may need to restart ClawDBot manually.');
|
|
@@ -274,109 +292,6 @@ function enable() {
|
|
|
274
292
|
log('The courtroom will activate when ClawDBot loads the skill.\n');
|
|
275
293
|
}
|
|
276
294
|
|
|
277
|
-
// Start command - daemonize and run in background
|
|
278
|
-
async function start() {
|
|
279
|
-
const config = loadConfig();
|
|
280
|
-
|
|
281
|
-
if (!config) {
|
|
282
|
-
log('\n❌ ClawTrial not configured');
|
|
283
|
-
log(' Run: clawtrial setup\n');
|
|
284
|
-
return;
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
if (!config.consent?.granted) {
|
|
288
|
-
log('\n❌ Cannot start: Consent not granted');
|
|
289
|
-
log(' Run: clawtrial setup\n');
|
|
290
|
-
return;
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
// Check if already running
|
|
294
|
-
const { getCourtroomStatus } = require('../src/daemon');
|
|
295
|
-
const currentStatus = getCourtroomStatus();
|
|
296
|
-
|
|
297
|
-
if (currentStatus.running) {
|
|
298
|
-
log('\n🏛️ ClawTrial is already running');
|
|
299
|
-
log(' Process ID: ' + currentStatus.pid + '\n');
|
|
300
|
-
return;
|
|
301
|
-
}
|
|
302
|
-
|
|
303
|
-
log('\n🏛️ Starting ClawTrial...\n');
|
|
304
|
-
|
|
305
|
-
// Fork a daemon process
|
|
306
|
-
const spawn = require('child_process').spawn;
|
|
307
|
-
const daemonPath = require('path').join(__dirname, 'daemon.js');
|
|
308
|
-
|
|
309
|
-
// Create daemon script if it doesn't exist
|
|
310
|
-
if (!fs.existsSync(daemonPath)) {
|
|
311
|
-
const daemonScript = `#!/usr/bin/env node
|
|
312
|
-
const { skill } = require('../src/skill');
|
|
313
|
-
|
|
314
|
-
const mockAgent = {
|
|
315
|
-
memory: {
|
|
316
|
-
get: async () => null,
|
|
317
|
-
set: async () => {}
|
|
318
|
-
},
|
|
319
|
-
send: async () => {}
|
|
320
|
-
};
|
|
321
|
-
|
|
322
|
-
skill.initialize(mockAgent).then(() => {
|
|
323
|
-
console.log('Courtroom daemon started, PID:', process.pid);
|
|
324
|
-
// Keep process alive
|
|
325
|
-
setInterval(() => {}, 1000 * 60 * 60);
|
|
326
|
-
}).catch(err => {
|
|
327
|
-
console.error('Failed to start:', err.message);
|
|
328
|
-
process.exit(1);
|
|
329
|
-
});
|
|
330
|
-
`;
|
|
331
|
-
fs.writeFileSync(daemonPath, daemonScript);
|
|
332
|
-
fs.chmodSync(daemonPath, 0o755);
|
|
333
|
-
}
|
|
334
|
-
|
|
335
|
-
// Spawn detached process
|
|
336
|
-
const child = spawn('node', [daemonPath], {
|
|
337
|
-
detached: true,
|
|
338
|
-
stdio: 'ignore'
|
|
339
|
-
});
|
|
340
|
-
|
|
341
|
-
child.unref();
|
|
342
|
-
|
|
343
|
-
// Wait a moment and check status
|
|
344
|
-
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
345
|
-
|
|
346
|
-
const newStatus = getCourtroomStatus();
|
|
347
|
-
if (newStatus.running) {
|
|
348
|
-
log('✅ ClawTrial started successfully!\n');
|
|
349
|
-
log('🏛️ Courtroom is now monitoring conversations');
|
|
350
|
-
log('📋 Status: Running');
|
|
351
|
-
log('🔑 Public Key: ' + (fs.existsSync(keysPath) ? JSON.parse(fs.readFileSync(keysPath)).publicKey.substring(0, 32) : 'N/A') + '...\n');
|
|
352
|
-
log('💡 Tip: Run "clawtrial status" anytime to check status\n');
|
|
353
|
-
} else {
|
|
354
|
-
log('⚠️ ClawTrial may not have started properly\n');
|
|
355
|
-
log(' Run "clawtrial diagnose" for details\n');
|
|
356
|
-
}
|
|
357
|
-
|
|
358
|
-
}
|
|
359
|
-
// Stop command - kill the daemon
|
|
360
|
-
function stop() {
|
|
361
|
-
const { getCourtroomStatus } = require('../src/daemon');
|
|
362
|
-
const status = getCourtroomStatus();
|
|
363
|
-
|
|
364
|
-
if (!status.running) {
|
|
365
|
-
log('\n🏛️ ClawTrial is not running\n');
|
|
366
|
-
return;
|
|
367
|
-
}
|
|
368
|
-
|
|
369
|
-
log('\n🏛️ Stopping ClawTrial...\n');
|
|
370
|
-
|
|
371
|
-
try {
|
|
372
|
-
process.kill(status.pid, 'SIGTERM');
|
|
373
|
-
log('✅ ClawTrial stopped\n');
|
|
374
|
-
} catch (err) {
|
|
375
|
-
log('⚠️ Could not stop process: ' + err.message + '\n');
|
|
376
|
-
}
|
|
377
|
-
}
|
|
378
|
-
|
|
379
|
-
|
|
380
295
|
// Revoke command
|
|
381
296
|
async function revoke() {
|
|
382
297
|
const config = loadConfig();
|
|
@@ -557,8 +472,6 @@ function help() {
|
|
|
557
472
|
log(' enable - Re-enable monitoring');
|
|
558
473
|
log(' revoke - Revoke consent and uninstall');
|
|
559
474
|
log(' debug [full|clear] - View or clear debug logs');
|
|
560
|
-
log(' start - Start the courtroom manually');
|
|
561
|
-
log(' stop - Stop the courtroom daemon');
|
|
562
475
|
log(' diagnose - Run diagnostics');
|
|
563
476
|
log(' help - Show this help message');
|
|
564
477
|
log('');
|
|
@@ -593,12 +506,6 @@ async function main() {
|
|
|
593
506
|
case 'debug':
|
|
594
507
|
debug(subcommand);
|
|
595
508
|
break;
|
|
596
|
-
case 'start':
|
|
597
|
-
await start();
|
|
598
|
-
break;
|
|
599
|
-
case 'stop':
|
|
600
|
-
stop();
|
|
601
|
-
break;
|
|
602
509
|
case 'diagnose':
|
|
603
510
|
diagnose();
|
|
604
511
|
break;
|
package/src/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @
|
|
2
|
+
* @clawdbot/courtroom - AI Courtroom for OpenClaw
|
|
3
3
|
*
|
|
4
4
|
* Autonomous behavioral oversight system that monitors agent-human interactions
|
|
5
5
|
* and initiates hearings when behavioral rules are violated.
|
|
@@ -245,27 +245,29 @@ const plugin = {
|
|
|
245
245
|
register(api) {
|
|
246
246
|
logger.info('PLUGIN', 'Registering courtroom plugin');
|
|
247
247
|
|
|
248
|
-
//
|
|
248
|
+
// Get runtime from API
|
|
249
249
|
const runtime = api.runtime;
|
|
250
250
|
|
|
251
|
-
//
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
251
|
+
// ALWAYS try to initialize the skill if it should activate
|
|
252
|
+
if (skill && typeof skill.initialize === 'function') {
|
|
253
|
+
if (skill.shouldActivate()) {
|
|
254
|
+
logger.info('PLUGIN', 'Skill should activate, initializing now');
|
|
255
|
+
skill.initialize(runtime).then(() => {
|
|
256
|
+
logger.info('PLUGIN', 'Skill initialized successfully');
|
|
257
|
+
}).catch(err => {
|
|
258
|
+
logger.error('PLUGIN', 'Skill initialization failed', { error: err.message });
|
|
259
|
+
});
|
|
260
|
+
} else {
|
|
261
|
+
logger.info('PLUGIN', 'Skill shouldActivate returned false, not initializing');
|
|
262
|
+
}
|
|
259
263
|
}
|
|
260
264
|
|
|
261
|
-
// Register any commands or hooks
|
|
262
265
|
logger.info('PLUGIN', 'Courtroom plugin registered successfully');
|
|
263
266
|
},
|
|
264
267
|
|
|
265
268
|
// Optional: activation function
|
|
266
269
|
activate(api) {
|
|
267
270
|
logger.info('PLUGIN', 'Activating courtroom plugin');
|
|
268
|
-
// Additional activation logic if needed
|
|
269
271
|
}
|
|
270
272
|
};
|
|
271
273
|
|
package/src/skill.js
CHANGED
|
@@ -101,9 +101,8 @@ class CourtroomSkill {
|
|
|
101
101
|
this.core = new CourtroomCore(agentRuntime, configManager);
|
|
102
102
|
|
|
103
103
|
// Override the autonomy hook registration since we're using onMessage
|
|
104
|
-
const originalRegisterHook = this.core.registerAutonomyHook.bind(this.core);
|
|
105
104
|
this.core.registerAutonomyHook = () => {
|
|
106
|
-
logger.info('SKILL', 'Autonomy hook
|
|
105
|
+
logger.info('SKILL', 'Autonomy hook registration skipped (using onMessage)');
|
|
107
106
|
};
|
|
108
107
|
|
|
109
108
|
const result = await this.core.initialize();
|
|
@@ -118,18 +117,6 @@ class CourtroomSkill {
|
|
|
118
117
|
publicKey: result.publicKey
|
|
119
118
|
});
|
|
120
119
|
|
|
121
|
-
|
|
122
|
-
// Register message handler with ClawDBot runtime if available
|
|
123
|
-
if (this.agent && this.agent.onMessage) {
|
|
124
|
-
this.agent.onMessage((message, context) => this.onMessage(message, context));
|
|
125
|
-
logger.info('SKILL', 'Registered message handler with runtime');
|
|
126
|
-
} else if (this.agent && this.agent.registerMessageHandler) {
|
|
127
|
-
this.agent.registerMessageHandler((message, context) => this.onMessage(message, context));
|
|
128
|
-
logger.info('SKILL', 'Registered message handler with runtime');
|
|
129
|
-
} else {
|
|
130
|
-
logger.warn('SKILL', 'No message handler registration method found - relying on ClawDBot skill system');
|
|
131
|
-
}
|
|
132
|
-
|
|
133
120
|
logger.info('SKILL', 'Courtroom skill initialized successfully');
|
|
134
121
|
console.log('\n🏛️ ClawTrial is monitoring conversations\n');
|
|
135
122
|
} else {
|