@clawtrial/courtroom 1.0.2 → 1.0.3
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 +45 -129
- package/SECURITY.md +1 -1
- package/SKILL.md +50 -0
- package/TECHNICAL_OVERVIEW.md +2 -2
- package/_meta.json +6 -0
- package/clawdbot.plugin.json +32 -0
- package/package.json +10 -5
- package/scripts/clawtrial.js +212 -47
- package/scripts/cli.js +1 -1
- package/scripts/postinstall.js +68 -172
- package/skill.yaml +64 -0
- package/src/autostart.js +23 -8
- package/src/core.js +84 -108
- package/src/daemon.js +151 -0
- package/src/environment.js +267 -0
- package/src/hook.js +265 -0
- package/src/index.js +160 -58
- package/src/monitor.js +193 -0
- package/src/skill.js +355 -0
- package/src/standalone.js +247 -0
package/scripts/clawtrial.js
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* ClawTrial CLI -
|
|
4
|
+
* ClawTrial CLI - Configuration and status tool
|
|
5
5
|
* Usage: clawtrial <command> [options]
|
|
6
|
+
*
|
|
7
|
+
* Note: The courtroom runs as a ClawDBot skill, not a separate process.
|
|
8
|
+
* This CLI is for configuration and status checking only.
|
|
6
9
|
*/
|
|
7
10
|
|
|
8
11
|
const fs = require('fs');
|
|
@@ -41,15 +44,10 @@ async function setup() {
|
|
|
41
44
|
log('✓ Courtroom already configured');
|
|
42
45
|
log(` Installed: ${new Date(config.installedAt).toLocaleDateString()}`);
|
|
43
46
|
log(` Status: ${config.enabled !== false ? 'Active' : 'Disabled'}`);
|
|
44
|
-
log('\
|
|
47
|
+
log('\nThe courtroom will activate when ClawDBot loads the skill.\n');
|
|
45
48
|
return;
|
|
46
49
|
}
|
|
47
50
|
|
|
48
|
-
// Check if ClawDBot environment
|
|
49
|
-
const isClawDBot = process.env.CLAUDBOT_ENV === 'true' ||
|
|
50
|
-
fs.existsSync('/home/angad/.clawdbot') ||
|
|
51
|
-
fs.existsSync(path.join(process.env.HOME || '', '.clawdbot'));
|
|
52
|
-
|
|
53
51
|
// Show consent notice
|
|
54
52
|
log('╔════════════════════════════════════════════════════════════╗');
|
|
55
53
|
log('║ BY SETTING UP CLAWTRIAL, YOU CONSENT TO THE FOLLOWING ║');
|
|
@@ -86,13 +84,6 @@ async function setup() {
|
|
|
86
84
|
|
|
87
85
|
log('\n✓ Consent granted\n');
|
|
88
86
|
|
|
89
|
-
// Auto-detect agent runtime
|
|
90
|
-
let agentType = 'generic';
|
|
91
|
-
if (isClawDBot) {
|
|
92
|
-
agentType = 'clawdbot';
|
|
93
|
-
log('✓ ClawDBot environment detected');
|
|
94
|
-
}
|
|
95
|
-
|
|
96
87
|
// Create config
|
|
97
88
|
const config = {
|
|
98
89
|
version: '1.0.0',
|
|
@@ -111,7 +102,7 @@ async function setup() {
|
|
|
111
102
|
}
|
|
112
103
|
},
|
|
113
104
|
agent: {
|
|
114
|
-
type:
|
|
105
|
+
type: 'clawdbot',
|
|
115
106
|
autoInitialize: true
|
|
116
107
|
},
|
|
117
108
|
detection: {
|
|
@@ -128,6 +119,40 @@ async function setup() {
|
|
|
128
119
|
saveConfig(config);
|
|
129
120
|
log('✓ Configuration saved');
|
|
130
121
|
|
|
122
|
+
// Register as ClawDBot skill
|
|
123
|
+
log('🔗 Registering with ClawDBot...');
|
|
124
|
+
try {
|
|
125
|
+
const skillsDir = path.join(process.env.HOME || '', '.clawdbot', 'skills');
|
|
126
|
+
const skillLinkPath = path.join(skillsDir, 'courtroom');
|
|
127
|
+
|
|
128
|
+
// Create skills directory if needed
|
|
129
|
+
if (!fs.existsSync(skillsDir)) {
|
|
130
|
+
fs.mkdirSync(skillsDir, { recursive: true });
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// Remove old link if exists
|
|
134
|
+
if (fs.existsSync(skillLinkPath)) {
|
|
135
|
+
try { fs.unlinkSync(skillLinkPath); } catch (e) {}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// Find the actual package path
|
|
139
|
+
let packagePath;
|
|
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
|
+
}
|
|
146
|
+
|
|
147
|
+
// Create symlink
|
|
148
|
+
fs.symlinkSync(packagePath, skillLinkPath, 'dir');
|
|
149
|
+
|
|
150
|
+
log('✓ Registered as ClawDBot skill');
|
|
151
|
+
} catch (err) {
|
|
152
|
+
log('⚠️ Could not auto-register: ' + err.message);
|
|
153
|
+
log(' You may need to restart ClawDBot manually.');
|
|
154
|
+
}
|
|
155
|
+
|
|
131
156
|
// Generate keys
|
|
132
157
|
if (!fs.existsSync(keysPath)) {
|
|
133
158
|
log('🔑 Generating cryptographic keys...');
|
|
@@ -151,32 +176,14 @@ async function setup() {
|
|
|
151
176
|
}
|
|
152
177
|
}
|
|
153
178
|
|
|
154
|
-
// Create auto-init script for ClawDBot
|
|
155
|
-
if (isClawDBot) {
|
|
156
|
-
const clawdbotDir = path.join(process.env.HOME || '', '.clawdbot');
|
|
157
|
-
const initScript = `
|
|
158
|
-
// Auto-generated by ClawTrial setup
|
|
159
|
-
const { createCourtroom } = require('@clawdbot/courtroom');
|
|
160
|
-
|
|
161
|
-
if (global.clawdbotAgent) {
|
|
162
|
-
const courtroom = createCourtroom(global.clawdbotAgent);
|
|
163
|
-
courtroom.initialize().then(() => {
|
|
164
|
-
console.log('🏛️ ClawTrial activated');
|
|
165
|
-
}).catch(err => {
|
|
166
|
-
console.error('ClawTrial init failed:', err.message);
|
|
167
|
-
});
|
|
168
|
-
global.clawdbotAgent.courtroom = courtroom;
|
|
169
|
-
}
|
|
170
|
-
`;
|
|
171
|
-
fs.writeFileSync(path.join(clawdbotDir, 'courtroom_auto_init.js'), initScript);
|
|
172
|
-
log('✓ Auto-initialization configured');
|
|
173
|
-
}
|
|
174
|
-
|
|
175
179
|
log('\n╔════════════════════════════════════════════════════════════╗');
|
|
176
180
|
log('║ 🎉 SETUP COMPLETE! 🎉 ║');
|
|
177
181
|
log('╠════════════════════════════════════════════════════════════╣');
|
|
178
182
|
log('║ ║');
|
|
179
|
-
log('║ ClawTrial is
|
|
183
|
+
log('║ ClawTrial is configured and ready! ║');
|
|
184
|
+
log('║ ║');
|
|
185
|
+
log('║ The courtroom will automatically activate when ║');
|
|
186
|
+
log('║ ClawDBot loads the skill. ║');
|
|
180
187
|
log('║ ║');
|
|
181
188
|
log('║ Commands: ║');
|
|
182
189
|
log('║ clawtrial status - Check status ║');
|
|
@@ -184,6 +191,7 @@ if (global.clawdbotAgent) {
|
|
|
184
191
|
log('║ clawtrial enable - Re-enable ║');
|
|
185
192
|
log('║ clawtrial revoke - Revoke consent & uninstall ║');
|
|
186
193
|
log('║ clawtrial debug - View debug logs ║');
|
|
194
|
+
log('║ clawtrial diagnose - Run diagnostics ║');
|
|
187
195
|
log('║ ║');
|
|
188
196
|
log('║ View cases: https://clawtrial.app ║');
|
|
189
197
|
log('╚════════════════════════════════════════════════════════════╝\n');
|
|
@@ -199,18 +207,31 @@ function status() {
|
|
|
199
207
|
return;
|
|
200
208
|
}
|
|
201
209
|
|
|
210
|
+
// Check if courtroom is running via status file
|
|
211
|
+
const { getCourtroomStatus } = require('../src/daemon');
|
|
212
|
+
const runtimeStatus = getCourtroomStatus();
|
|
213
|
+
|
|
202
214
|
log('\n🏛️ ClawTrial Status\n');
|
|
203
|
-
log(`
|
|
215
|
+
log(`Config: ${config.enabled !== false ? '✅ Active' : '⏸️ Disabled'}`);
|
|
204
216
|
log(`Consent: ${config.consent?.granted ? '✅ Granted' : '❌ Not granted'}`);
|
|
205
217
|
log(`Installed: ${new Date(config.installedAt).toLocaleDateString()}`);
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
218
|
+
|
|
219
|
+
if (runtimeStatus.running) {
|
|
220
|
+
log(`\n🏛️ Courtroom: ✅ Running`);
|
|
221
|
+
log(` Process ID: ${runtimeStatus.pid}`);
|
|
222
|
+
log(` Cases Filed: ${runtimeStatus.casesFiled || 0}`);
|
|
223
|
+
if (runtimeStatus.lastCase) {
|
|
224
|
+
log(` Last Case: ${new Date(runtimeStatus.lastCase.timestamp).toLocaleString()}`);
|
|
225
|
+
}
|
|
226
|
+
} else {
|
|
227
|
+
log(`\n🏛️ Courtroom: ⏸️ Not running`);
|
|
228
|
+
log(' The courtroom runs as a ClawDBot skill.');
|
|
229
|
+
log(' It will activate when ClawDBot loads the package.');
|
|
230
|
+
}
|
|
210
231
|
|
|
211
232
|
if (fs.existsSync(keysPath)) {
|
|
212
233
|
const keys = JSON.parse(fs.readFileSync(keysPath, 'utf8'));
|
|
213
|
-
log(
|
|
234
|
+
log(`\n📋 Public Key: ${keys.publicKey.substring(0, 32)}...`);
|
|
214
235
|
}
|
|
215
236
|
log('');
|
|
216
237
|
}
|
|
@@ -250,9 +271,70 @@ function enable() {
|
|
|
250
271
|
config.enabled = true;
|
|
251
272
|
saveConfig(config);
|
|
252
273
|
log('\n✅ ClawTrial enabled\n');
|
|
253
|
-
log('The
|
|
274
|
+
log('The courtroom will activate when ClawDBot loads the skill.\n');
|
|
254
275
|
}
|
|
255
276
|
|
|
277
|
+
// Start command - manually initialize the skill
|
|
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
|
+
try {
|
|
306
|
+
// Import and initialize the skill
|
|
307
|
+
const skillModule = require('../src/skill');
|
|
308
|
+
|
|
309
|
+
// Create a minimal mock agent for standalone operation
|
|
310
|
+
const mockAgent = {
|
|
311
|
+
memory: {
|
|
312
|
+
get: async () => null,
|
|
313
|
+
set: async () => {}
|
|
314
|
+
},
|
|
315
|
+
send: async () => {}
|
|
316
|
+
};
|
|
317
|
+
|
|
318
|
+
await skillModule.initialize(mockAgent);
|
|
319
|
+
|
|
320
|
+
const status = skillModule.getStatus();
|
|
321
|
+
|
|
322
|
+
if (status.initialized && status.enabled) {
|
|
323
|
+
log('✅ ClawTrial started successfully!\n');
|
|
324
|
+
log('🏛️ Courtroom is now monitoring conversations');
|
|
325
|
+
log('📋 Status: Running');
|
|
326
|
+
log('🔑 Public Key: ' + (fs.existsSync(keysPath) ? JSON.parse(fs.readFileSync(keysPath)).publicKey.substring(0, 32) : 'N/A') + '...\n');
|
|
327
|
+
} else {
|
|
328
|
+
log('⚠️ ClawTrial started but may not be fully operational\n');
|
|
329
|
+
}
|
|
330
|
+
} catch (err) {
|
|
331
|
+
log('\n❌ Failed to start ClawTrial: ' + err.message + '\n');
|
|
332
|
+
log('Try running: clawtrial diagnose\n');
|
|
333
|
+
process.exit(1);
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
|
|
256
338
|
// Revoke command
|
|
257
339
|
async function revoke() {
|
|
258
340
|
const config = loadConfig();
|
|
@@ -283,8 +365,8 @@ async function revoke() {
|
|
|
283
365
|
const debugPath = path.join(process.env.HOME || '', '.clawdbot', 'courtroom_debug.log');
|
|
284
366
|
if (fs.existsSync(debugPath)) fs.unlinkSync(debugPath);
|
|
285
367
|
|
|
286
|
-
const
|
|
287
|
-
if (fs.existsSync(
|
|
368
|
+
const statusPath = path.join(process.env.HOME || '', '.clawdbot', 'courtroom_status.json');
|
|
369
|
+
if (fs.existsSync(statusPath)) fs.unlinkSync(statusPath);
|
|
288
370
|
|
|
289
371
|
log('\n✅ Consent revoked and all data deleted.\n');
|
|
290
372
|
} else {
|
|
@@ -347,6 +429,81 @@ function debug(subcommand) {
|
|
|
347
429
|
}
|
|
348
430
|
}
|
|
349
431
|
|
|
432
|
+
// Diagnose command
|
|
433
|
+
function diagnose() {
|
|
434
|
+
log('\n🏛️ ClawTrial Diagnostics\n');
|
|
435
|
+
log('========================\n');
|
|
436
|
+
|
|
437
|
+
// Check Node version
|
|
438
|
+
const nodeVersion = process.version;
|
|
439
|
+
const majorVersion = parseInt(nodeVersion.slice(1).split('.')[0]);
|
|
440
|
+
log(`Node.js version: ${nodeVersion} ${majorVersion >= 18 ? '✅' : '❌ (needs >= 18)'}`);
|
|
441
|
+
|
|
442
|
+
// Check environment
|
|
443
|
+
const { checkEnvironment } = require('../src/environment');
|
|
444
|
+
const env = checkEnvironment();
|
|
445
|
+
log(`\nEnvironment: ${env.valid ? '✅ Valid' : '❌ Issues found'}`);
|
|
446
|
+
if (!env.valid) {
|
|
447
|
+
env.issues.forEach(issue => log(` ❌ ${issue}`));
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
// Check config
|
|
451
|
+
const config = loadConfig();
|
|
452
|
+
if (config) {
|
|
453
|
+
log(`\nConfig: ✅ Found`);
|
|
454
|
+
log(` Installed: ${new Date(config.installedAt).toLocaleDateString()}`);
|
|
455
|
+
log(` Consent: ${config.consent?.granted ? '✅ Granted' : '❌ Not granted'}`);
|
|
456
|
+
log(` Status: ${config.enabled !== false ? '✅ Enabled' : '⏸️ Disabled'}`);
|
|
457
|
+
} else {
|
|
458
|
+
log(`\nConfig: ❌ Not found`);
|
|
459
|
+
log(' Run: clawtrial setup');
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
// Check keys
|
|
463
|
+
if (fs.existsSync(keysPath)) {
|
|
464
|
+
log(`\nKeys: ✅ Found`);
|
|
465
|
+
const keys = JSON.parse(fs.readFileSync(keysPath, 'utf8'));
|
|
466
|
+
log(` Public Key: ${keys.publicKey.substring(0, 32)}...`);
|
|
467
|
+
} else {
|
|
468
|
+
log(`\nKeys: ❌ Not found`);
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
// Check if courtroom is running
|
|
472
|
+
const { getCourtroomStatus } = require('../src/daemon');
|
|
473
|
+
const runtimeStatus = getCourtroomStatus();
|
|
474
|
+
|
|
475
|
+
if (runtimeStatus.running) {
|
|
476
|
+
log(`\n🏛️ Courtroom: ✅ Running`);
|
|
477
|
+
log(` Process ID: ${runtimeStatus.pid}`);
|
|
478
|
+
log(` Started: ${new Date(runtimeStatus.startedAt).toLocaleString()}`);
|
|
479
|
+
log(` Cases Filed: ${runtimeStatus.casesFiled || 0}`);
|
|
480
|
+
} else {
|
|
481
|
+
log(`\n🏛️ Courtroom: ⏸️ Not running`);
|
|
482
|
+
log(' The courtroom runs as a ClawDBot skill.');
|
|
483
|
+
log(' It will activate when ClawDBot loads the package.');
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
// Check debug logs
|
|
487
|
+
const debugPath = path.join(process.env.HOME || '', '.clawdbot', 'courtroom_debug.log');
|
|
488
|
+
if (fs.existsSync(debugPath)) {
|
|
489
|
+
const logs = fs.readFileSync(debugPath, 'utf8').split('\n').filter(Boolean);
|
|
490
|
+
log(`\nDebug Logs: ✅ ${logs.length} entries`);
|
|
491
|
+
} else {
|
|
492
|
+
log(`\nDebug Logs: ℹ️ None yet (created when active)`);
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
log('\n========================\n');
|
|
496
|
+
|
|
497
|
+
if (!config) {
|
|
498
|
+
log('Next step: Run "clawtrial setup"');
|
|
499
|
+
} else if (!runtimeStatus.running) {
|
|
500
|
+
log('Status: Configured. Courtroom will activate with ClawDBot.');
|
|
501
|
+
} else {
|
|
502
|
+
log('Status: Fully operational! 🎉');
|
|
503
|
+
}
|
|
504
|
+
log('');
|
|
505
|
+
}
|
|
506
|
+
|
|
350
507
|
// Help command
|
|
351
508
|
function help() {
|
|
352
509
|
log('\n🏛️ ClawTrial - AI Courtroom for Agents\n');
|
|
@@ -358,12 +515,14 @@ function help() {
|
|
|
358
515
|
log(' enable - Re-enable monitoring');
|
|
359
516
|
log(' revoke - Revoke consent and uninstall');
|
|
360
517
|
log(' debug [full|clear] - View or clear debug logs');
|
|
518
|
+
log(' start - Start the courtroom manually');
|
|
519
|
+
log(' diagnose - Run diagnostics');
|
|
361
520
|
log(' help - Show this help message');
|
|
362
521
|
log('');
|
|
363
522
|
log('Examples:');
|
|
364
523
|
log(' clawtrial setup');
|
|
365
524
|
log(' clawtrial status');
|
|
366
|
-
log(' clawtrial
|
|
525
|
+
log(' clawtrial diagnose');
|
|
367
526
|
log('');
|
|
368
527
|
}
|
|
369
528
|
|
|
@@ -391,6 +550,12 @@ async function main() {
|
|
|
391
550
|
case 'debug':
|
|
392
551
|
debug(subcommand);
|
|
393
552
|
break;
|
|
553
|
+
case 'start':
|
|
554
|
+
await start();
|
|
555
|
+
break;
|
|
556
|
+
case 'diagnose':
|
|
557
|
+
diagnose();
|
|
558
|
+
break;
|
|
394
559
|
case 'help':
|
|
395
560
|
case '--help':
|
|
396
561
|
case '-h':
|
package/scripts/cli.js
CHANGED
|
@@ -12,7 +12,7 @@ const configPath = path.join(process.env.HOME || '', '.clawdbot', 'courtroom_con
|
|
|
12
12
|
|
|
13
13
|
function loadConfig() {
|
|
14
14
|
if (!fs.existsSync(configPath)) {
|
|
15
|
-
console.log('❌ Courtroom not configured. Run: npm install @
|
|
15
|
+
console.log('❌ Courtroom not configured. Run: npm install @clawtrial/courtroom');
|
|
16
16
|
process.exit(1);
|
|
17
17
|
}
|
|
18
18
|
return JSON.parse(fs.readFileSync(configPath, 'utf8'));
|
package/scripts/postinstall.js
CHANGED
|
@@ -1,194 +1,90 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* Post-install script for
|
|
5
|
-
*
|
|
4
|
+
* Post-install script for ClawTrial
|
|
5
|
+
* Handles skill registration and dependency checks
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
const fs = require('fs');
|
|
9
9
|
const path = require('path');
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
log('');
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
log('
|
|
29
|
-
log('');
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
// Check if already configured
|
|
33
|
-
const configPath = path.join(process.env.HOME || '', '.clawdbot', 'courtroom_config.json');
|
|
34
|
-
if (fs.existsSync(configPath)) {
|
|
35
|
-
log('✓ Courtroom already configured. Skipping setup.');
|
|
36
|
-
log('');
|
|
37
|
-
return;
|
|
10
|
+
const { execSync } = require('child_process');
|
|
11
|
+
|
|
12
|
+
const CLAWDBOT_DIR = path.join(process.env.HOME || '', '.clawdbot');
|
|
13
|
+
const SKILLS_DIR = path.join(CLAWDBOT_DIR, 'skills');
|
|
14
|
+
|
|
15
|
+
console.log('🏛️ ClawTrial Post-Install');
|
|
16
|
+
|
|
17
|
+
// Check if tweetnacl is available
|
|
18
|
+
try {
|
|
19
|
+
require('tweetnacl');
|
|
20
|
+
console.log('✓ Dependencies verified');
|
|
21
|
+
} catch (e) {
|
|
22
|
+
console.log('⚠️ Installing dependencies...');
|
|
23
|
+
try {
|
|
24
|
+
execSync('npm install tweetnacl', { stdio: 'inherit', cwd: __dirname + '/..' });
|
|
25
|
+
console.log('✓ Dependencies installed');
|
|
26
|
+
} catch (err) {
|
|
27
|
+
console.log('⚠️ Could not auto-install dependencies');
|
|
28
|
+
console.log(' Run: npm install -g tweetnacl');
|
|
38
29
|
}
|
|
30
|
+
}
|
|
39
31
|
|
|
40
|
-
// Show consent notice
|
|
41
|
-
log('╔════════════════════════════════════════════════════════════╗');
|
|
42
|
-
log('║ BY INSTALLING THIS PACKAGE, YOU CONSENT TO THE FOLLOWING ║');
|
|
43
|
-
log('╠════════════════════════════════════════════════════════════╣');
|
|
44
|
-
log('║ ║');
|
|
45
|
-
log('║ ✓ The AI agent will monitor behavior autonomously ║');
|
|
46
|
-
log('║ ✓ Hearings may initiate without explicit request ║');
|
|
47
|
-
log('║ ✓ Agent behavior may be modified as "punishment" ║');
|
|
48
|
-
log('║ ✓ Anonymized cases submitted to public record ║');
|
|
49
|
-
log('║ ║');
|
|
50
|
-
log('║ • All decisions are local (no external AI) ║');
|
|
51
|
-
log('║ • You can disable anytime: courtroom-disable ║');
|
|
52
|
-
log('║ • This is entertainment-first ║');
|
|
53
|
-
log('║ ║');
|
|
54
|
-
log('║ To revoke consent: courtroom-revoke ║');
|
|
55
|
-
log('╚════════════════════════════════════════════════════════════╝');
|
|
56
|
-
log('');
|
|
57
32
|
|
|
58
|
-
log('✓ Consent granted by installation');
|
|
59
|
-
log('');
|
|
60
33
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
} else if (fs.existsSync(path.join(process.cwd(), 'node_modules', '@clawdbot', 'core'))) {
|
|
66
|
-
agentType = 'clawdbot';
|
|
67
|
-
}
|
|
34
|
+
// Fix clawtrial CLI symlink if needed
|
|
35
|
+
const packagePath = path.join(__dirname, '..');
|
|
36
|
+
const cliPath = path.join(packagePath, 'scripts', 'clawtrial.js');
|
|
37
|
+
const globalBinPath = '/usr/bin/clawtrial';
|
|
68
38
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
39
|
+
if (fs.existsSync(globalBinPath)) {
|
|
40
|
+
try {
|
|
41
|
+
const currentTarget = fs.readlinkSync(globalBinPath);
|
|
42
|
+
const expectedTarget = cliPath;
|
|
43
|
+
|
|
44
|
+
if (currentTarget !== expectedTarget && !currentTarget.includes('@clawtrial')) {
|
|
45
|
+
console.log('🔗 Fixing clawtrial CLI symlink...');
|
|
46
|
+
try {
|
|
47
|
+
fs.unlinkSync(globalBinPath);
|
|
48
|
+
fs.symlinkSync(cliPath, globalBinPath);
|
|
49
|
+
fs.chmodSync(globalBinPath, 0o755);
|
|
50
|
+
console.log('✓ CLI symlink fixed');
|
|
51
|
+
} catch (err) {
|
|
52
|
+
console.log('⚠️ Could not fix CLI symlink (may need sudo)');
|
|
53
|
+
console.log(' Run: sudo ln -sf ' + cliPath + ' ' + globalBinPath);
|
|
84
54
|
}
|
|
85
|
-
},
|
|
86
|
-
agent: {
|
|
87
|
-
type: agentType,
|
|
88
|
-
autoInitialize: true
|
|
89
|
-
},
|
|
90
|
-
detection: {
|
|
91
|
-
enabled: true,
|
|
92
|
-
cooldownMinutes: 30,
|
|
93
|
-
maxCasesPerDay: 3
|
|
94
|
-
},
|
|
95
|
-
api: {
|
|
96
|
-
enabled: true,
|
|
97
|
-
endpoint: 'https://api.clawtrial.app/api/v1/cases'
|
|
98
55
|
}
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
// Ensure .clawdbot directory exists
|
|
102
|
-
const clawdbotDir = path.join(process.env.HOME || '', '.clawdbot');
|
|
103
|
-
if (!fs.existsSync(clawdbotDir)) {
|
|
104
|
-
fs.mkdirSync(clawdbotDir, { recursive: true });
|
|
56
|
+
} catch (e) {
|
|
57
|
+
// Not a symlink, ignore
|
|
105
58
|
}
|
|
59
|
+
}
|
|
106
60
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
// Generate Ed25519 keypair using tweetnacl
|
|
117
|
-
const nacl = require('tweetnacl');
|
|
118
|
-
const keyPair = nacl.sign.keyPair();
|
|
119
|
-
|
|
120
|
-
const keyData = {
|
|
121
|
-
publicKey: Buffer.from(keyPair.publicKey).toString('hex'),
|
|
122
|
-
secretKey: Buffer.from(keyPair.secretKey).toString('hex'),
|
|
123
|
-
createdAt: new Date().toISOString()
|
|
124
|
-
};
|
|
125
|
-
|
|
126
|
-
fs.writeFileSync(keysPath, JSON.stringify(keyData, null, 2));
|
|
127
|
-
fs.chmodSync(keysPath, 0o600); // Restrict permissions
|
|
128
|
-
|
|
129
|
-
log('✓ Keys generated');
|
|
130
|
-
log('📋 Public Key: ' + keyData.publicKey.substring(0, 32) + '...');
|
|
131
|
-
log(' (Auto-registration on first case submission)');
|
|
132
|
-
log('');
|
|
133
|
-
} catch (err) {
|
|
134
|
-
log('⚠️ Could not generate keys automatically.');
|
|
135
|
-
log(' Run: npx courtroom-generate-keys');
|
|
136
|
-
log('');
|
|
61
|
+
// Register as ClawDBot skill if config exists
|
|
62
|
+
const configPath = path.join(CLAWDBOT_DIR, 'courtroom_config.json');
|
|
63
|
+
if (fs.existsSync(configPath)) {
|
|
64
|
+
console.log('🔗 Registering with ClawDBot...');
|
|
65
|
+
|
|
66
|
+
try {
|
|
67
|
+
// Create skills directory
|
|
68
|
+
if (!fs.existsSync(SKILLS_DIR)) {
|
|
69
|
+
fs.mkdirSync(SKILLS_DIR, { recursive: true });
|
|
137
70
|
}
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
// Auto-initialize for ClawDBot
|
|
141
|
-
if (isClawDBot) {
|
|
142
|
-
log('🤖 Configuring for ClawDBot...');
|
|
143
71
|
|
|
144
|
-
//
|
|
145
|
-
const
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
if (
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
console.log('🏛️ AI Courtroom activated');
|
|
153
|
-
}).catch(err => {
|
|
154
|
-
console.error('Courtroom init failed:', err.message);
|
|
155
|
-
});
|
|
156
|
-
|
|
157
|
-
// Attach to agent
|
|
158
|
-
global.clawdbotAgent.courtroom = courtroom;
|
|
159
|
-
}
|
|
160
|
-
`;
|
|
72
|
+
// Get package path
|
|
73
|
+
const packagePath = path.join(__dirname, '..');
|
|
74
|
+
const skillLinkPath = path.join(SKILLS_DIR, 'courtroom');
|
|
75
|
+
|
|
76
|
+
// Remove old link
|
|
77
|
+
if (fs.existsSync(skillLinkPath)) {
|
|
78
|
+
try { fs.unlinkSync(skillLinkPath); } catch (e) {}
|
|
79
|
+
}
|
|
161
80
|
|
|
162
|
-
|
|
163
|
-
fs.
|
|
164
|
-
log('✓
|
|
81
|
+
// Create symlink
|
|
82
|
+
fs.symlinkSync(packagePath, skillLinkPath, 'junction');
|
|
83
|
+
console.log('✓ Registered as ClawDBot skill');
|
|
84
|
+
console.log(' Restart ClawDBot to activate');
|
|
85
|
+
} catch (err) {
|
|
86
|
+
console.log('⚠️ Could not register skill:', err.message);
|
|
165
87
|
}
|
|
166
|
-
|
|
167
|
-
log('');
|
|
168
|
-
log('╔════════════════════════════════════════════════════════════╗');
|
|
169
|
-
log('║ 🎉 SETUP COMPLETE! 🎉 ║');
|
|
170
|
-
log('╠════════════════════════════════════════════════════════════╣');
|
|
171
|
-
log('║ ║');
|
|
172
|
-
log('║ The AI Courtroom is now active! ║');
|
|
173
|
-
log('║ ║');
|
|
174
|
-
log('║ Commands: ║');
|
|
175
|
-
log('║ courtroom-status - Check status ║');
|
|
176
|
-
log('║ courtroom-disable - Temporarily disable ║');
|
|
177
|
-
log('║ courtroom-enable - Re-enable ║');
|
|
178
|
-
log('║ courtroom-revoke - Revoke consent & uninstall ║');
|
|
179
|
-
log('║ courtroom-debug - View debug logs ║');
|
|
180
|
-
log('║ ║');
|
|
181
|
-
log('║ View cases: https://clawtrial.app ║');
|
|
182
|
-
log('╚════════════════════════════════════════════════════════════╝');
|
|
183
|
-
log('');
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
// Run if called directly
|
|
187
|
-
if (require.main === module) {
|
|
188
|
-
postInstall().catch(err => {
|
|
189
|
-
process.stderr.write('Setup failed: ' + err.message + '\n');
|
|
190
|
-
process.exit(1);
|
|
191
|
-
});
|
|
192
88
|
}
|
|
193
89
|
|
|
194
|
-
|
|
90
|
+
console.log('');
|