@clawtrial/courtroom 1.0.3 β†’ 2.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.
@@ -1,578 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- /**
4
- * ClawTrial CLI - Configuration and status tool
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.
9
- */
10
-
11
- const fs = require('fs');
12
- const path = require('path');
13
- const readline = require('readline');
14
-
15
- const configPath = path.join(process.env.HOME || '', '.clawdbot', 'courtroom_config.json');
16
- const keysPath = path.join(process.env.HOME || '', '.clawdbot', 'courtroom_keys.json');
17
-
18
- function loadConfig() {
19
- if (!fs.existsSync(configPath)) {
20
- return null;
21
- }
22
- return JSON.parse(fs.readFileSync(configPath, 'utf8'));
23
- }
24
-
25
- function saveConfig(config) {
26
- const clawdbotDir = path.join(process.env.HOME || '', '.clawdbot');
27
- if (!fs.existsSync(clawdbotDir)) {
28
- fs.mkdirSync(clawdbotDir, { recursive: true });
29
- }
30
- fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
31
- }
32
-
33
- function log(message) {
34
- console.log(message);
35
- }
36
-
37
- // Setup command - interactive setup
38
- async function setup() {
39
- log('\nπŸ›οΈ ClawTrial Setup\n');
40
-
41
- // Check if already configured
42
- if (fs.existsSync(configPath)) {
43
- const config = loadConfig();
44
- log('βœ“ Courtroom already configured');
45
- log(` Installed: ${new Date(config.installedAt).toLocaleDateString()}`);
46
- log(` Status: ${config.enabled !== false ? 'Active' : 'Disabled'}`);
47
- log('\nThe courtroom will activate when ClawDBot loads the skill.\n');
48
- return;
49
- }
50
-
51
- // Show consent notice
52
- log('╔════════════════════════════════════════════════════════════╗');
53
- log('β•‘ BY SETTING UP CLAWTRIAL, YOU CONSENT TO THE FOLLOWING β•‘');
54
- log('╠════════════════════════════════════════════════════════════╣');
55
- log('β•‘ β•‘');
56
- log('β•‘ βœ“ The AI agent will monitor behavior autonomously β•‘');
57
- log('β•‘ βœ“ Hearings may initiate without explicit request β•‘');
58
- log('β•‘ βœ“ Agent behavior may be modified as "punishment" β•‘');
59
- log('β•‘ βœ“ Anonymized cases submitted to public record β•‘');
60
- log('β•‘ β•‘');
61
- log('β•‘ β€’ All decisions are local (no external AI) β•‘');
62
- log('β•‘ β€’ You can disable anytime: clawtrial disable β•‘');
63
- log('β•‘ β€’ This is entertainment-first β•‘');
64
- log('β•‘ β•‘');
65
- log('β•‘ To revoke consent later: clawtrial revoke β•‘');
66
- log('β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•\n');
67
-
68
- const rl = readline.createInterface({
69
- input: process.stdin,
70
- output: process.stdout
71
- });
72
-
73
- const question = (prompt) => new Promise((resolve) => rl.question(prompt, resolve));
74
-
75
- const consent = await question('Do you consent to enable ClawTrial? (yes/no): ');
76
-
77
- if (consent.toLowerCase() !== 'yes' && consent.toLowerCase() !== 'y') {
78
- log('\n❌ Setup cancelled. Consent not granted.\n');
79
- rl.close();
80
- return;
81
- }
82
-
83
- rl.close();
84
-
85
- log('\nβœ“ Consent granted\n');
86
-
87
- // Create config
88
- const config = {
89
- version: '1.0.0',
90
- installedAt: new Date().toISOString(),
91
- consent: {
92
- granted: true,
93
- grantedAt: new Date().toISOString(),
94
- method: 'explicit_setup',
95
- acknowledgments: {
96
- autonomy: true,
97
- local_only: true,
98
- agent_controlled: true,
99
- reversible: true,
100
- api_submission: true,
101
- entertainment: true
102
- }
103
- },
104
- agent: {
105
- type: 'clawdbot',
106
- autoInitialize: true
107
- },
108
- detection: {
109
- enabled: true,
110
- cooldownMinutes: 30,
111
- maxCasesPerDay: 3
112
- },
113
- api: {
114
- enabled: true,
115
- endpoint: 'https://api.clawtrial.app/api/v1/cases'
116
- }
117
- };
118
-
119
- saveConfig(config);
120
- log('βœ“ Configuration saved');
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
-
156
- // Generate keys
157
- if (!fs.existsSync(keysPath)) {
158
- log('πŸ”‘ Generating cryptographic keys...');
159
- try {
160
- const nacl = require('tweetnacl');
161
- const keyPair = nacl.sign.keyPair();
162
-
163
- const keyData = {
164
- publicKey: Buffer.from(keyPair.publicKey).toString('hex'),
165
- secretKey: Buffer.from(keyPair.secretKey).toString('hex'),
166
- createdAt: new Date().toISOString()
167
- };
168
-
169
- fs.writeFileSync(keysPath, JSON.stringify(keyData, null, 2));
170
- fs.chmodSync(keysPath, 0o600);
171
-
172
- log('βœ“ Keys generated');
173
- log(`πŸ“‹ Public Key: ${keyData.publicKey.substring(0, 32)}...`);
174
- } catch (err) {
175
- log('⚠️ Could not generate keys: ' + err.message);
176
- }
177
- }
178
-
179
- log('\n╔════════════════════════════════════════════════════════════╗');
180
- log('β•‘ πŸŽ‰ SETUP COMPLETE! πŸŽ‰ β•‘');
181
- log('╠════════════════════════════════════════════════════════════╣');
182
- log('β•‘ β•‘');
183
- log('β•‘ ClawTrial is configured and ready! β•‘');
184
- log('β•‘ β•‘');
185
- log('β•‘ The courtroom will automatically activate when β•‘');
186
- log('β•‘ ClawDBot loads the skill. β•‘');
187
- log('β•‘ β•‘');
188
- log('β•‘ Commands: β•‘');
189
- log('β•‘ clawtrial status - Check status β•‘');
190
- log('β•‘ clawtrial disable - Temporarily disable β•‘');
191
- log('β•‘ clawtrial enable - Re-enable β•‘');
192
- log('β•‘ clawtrial revoke - Revoke consent & uninstall β•‘');
193
- log('β•‘ clawtrial debug - View debug logs β•‘');
194
- log('β•‘ clawtrial diagnose - Run diagnostics β•‘');
195
- log('β•‘ β•‘');
196
- log('β•‘ View cases: https://clawtrial.app β•‘');
197
- log('β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•\n');
198
- }
199
-
200
- // Status command
201
- function status() {
202
- const config = loadConfig();
203
-
204
- if (!config) {
205
- log('\n❌ ClawTrial not configured');
206
- log(' Run: clawtrial setup\n');
207
- return;
208
- }
209
-
210
- // Check if courtroom is running via status file
211
- const { getCourtroomStatus } = require('../src/daemon');
212
- const runtimeStatus = getCourtroomStatus();
213
-
214
- log('\nπŸ›οΈ ClawTrial Status\n');
215
- log(`Config: ${config.enabled !== false ? 'βœ… Active' : '⏸️ Disabled'}`);
216
- log(`Consent: ${config.consent?.granted ? 'βœ… Granted' : '❌ Not granted'}`);
217
- log(`Installed: ${new Date(config.installedAt).toLocaleDateString()}`);
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
- }
231
-
232
- if (fs.existsSync(keysPath)) {
233
- const keys = JSON.parse(fs.readFileSync(keysPath, 'utf8'));
234
- log(`\nπŸ“‹ Public Key: ${keys.publicKey.substring(0, 32)}...`);
235
- }
236
- log('');
237
- }
238
-
239
- // Disable command
240
- function disable() {
241
- const config = loadConfig();
242
-
243
- if (!config) {
244
- log('\n❌ ClawTrial not configured\n');
245
- return;
246
- }
247
-
248
- config.enabled = false;
249
- saveConfig(config);
250
- log('\n⏸️ ClawTrial disabled\n');
251
- log('The agent will stop monitoring for offenses.');
252
- log('Run "clawtrial enable" to reactivate.\n');
253
- }
254
-
255
- // Enable command
256
- function enable() {
257
- const config = loadConfig();
258
-
259
- if (!config) {
260
- log('\n❌ ClawTrial not configured');
261
- log(' Run: clawtrial setup\n');
262
- return;
263
- }
264
-
265
- if (!config.consent?.granted) {
266
- log('\n❌ Cannot enable: Consent not granted');
267
- log(' Run: clawtrial setup\n');
268
- return;
269
- }
270
-
271
- config.enabled = true;
272
- saveConfig(config);
273
- log('\nβœ… ClawTrial enabled\n');
274
- log('The courtroom will activate when ClawDBot loads the skill.\n');
275
- }
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
-
338
- // Revoke command
339
- async function revoke() {
340
- const config = loadConfig();
341
-
342
- if (!config) {
343
- log('\n❌ ClawTrial not configured\n');
344
- return;
345
- }
346
-
347
- log('\n⚠️ This will permanently disable ClawTrial and delete all data.\n');
348
-
349
- const rl = readline.createInterface({
350
- input: process.stdin,
351
- output: process.stdout
352
- });
353
-
354
- const answer = await new Promise((resolve) => {
355
- rl.question('Type "REVOKE" to confirm: ', resolve);
356
- });
357
-
358
- rl.close();
359
-
360
- if (answer === 'REVOKE') {
361
- // Delete all files
362
- if (fs.existsSync(configPath)) fs.unlinkSync(configPath);
363
- if (fs.existsSync(keysPath)) fs.unlinkSync(keysPath);
364
-
365
- const debugPath = path.join(process.env.HOME || '', '.clawdbot', 'courtroom_debug.log');
366
- if (fs.existsSync(debugPath)) fs.unlinkSync(debugPath);
367
-
368
- const statusPath = path.join(process.env.HOME || '', '.clawdbot', 'courtroom_status.json');
369
- if (fs.existsSync(statusPath)) fs.unlinkSync(statusPath);
370
-
371
- log('\nβœ… Consent revoked and all data deleted.\n');
372
- } else {
373
- log('\n❌ Revocation cancelled.\n');
374
- }
375
- }
376
-
377
- // Debug command
378
- function debug(subcommand) {
379
- const debugPath = path.join(process.env.HOME || '', '.clawdbot', 'courtroom_debug.log');
380
-
381
- if (!fs.existsSync(debugPath)) {
382
- log('\nℹ️ No debug logs found yet.');
383
- log(' Debug logs are created when the courtroom is active.\n');
384
- return;
385
- }
386
-
387
- if (subcommand === 'full') {
388
- log('\nπŸ›οΈ ClawTrial Full Debug Log\n');
389
- log('=============================\n');
390
- const logs = fs.readFileSync(debugPath, 'utf8').split('\n').filter(Boolean);
391
- logs.slice(-100).forEach(line => {
392
- try {
393
- const log = JSON.parse(line);
394
- log(`[${log.timestamp}] ${log.level} - ${log.component}`);
395
- log(` ${log.message}`);
396
- } catch (e) {
397
- log(line);
398
- }
399
- });
400
- log('');
401
- } else if (subcommand === 'clear') {
402
- fs.unlinkSync(debugPath);
403
- log('\nβœ… Debug logs cleared\n');
404
- } else {
405
- // Show status
406
- const logs = fs.readFileSync(debugPath, 'utf8').split('\n').filter(Boolean);
407
- const recentLogs = logs.slice(-20);
408
-
409
- log('\nπŸ›οΈ ClawTrial Debug Status\n');
410
- log('===========================\n');
411
- log(`Total log entries: ${logs.length}`);
412
- log(`Log file: ${debugPath}`);
413
- log('\nRecent activity:');
414
-
415
- recentLogs.forEach(line => {
416
- try {
417
- const log = JSON.parse(line);
418
- log(` [${log.level}] ${log.component}: ${log.message.substring(0, 60)}`);
419
- } catch (e) {
420
- // Skip malformed lines
421
- }
422
- });
423
-
424
- log('\nUsage:');
425
- log(' clawtrial debug - Show status and recent logs');
426
- log(' clawtrial debug full - Show full debug log');
427
- log(' clawtrial debug clear - Clear all logs');
428
- log('');
429
- }
430
- }
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
-
507
- // Help command
508
- function help() {
509
- log('\nπŸ›οΈ ClawTrial - AI Courtroom for Agents\n');
510
- log('Usage: clawtrial <command> [options]\n');
511
- log('Commands:');
512
- log(' setup - Interactive setup and consent');
513
- log(' status - Check courtroom status');
514
- log(' disable - Temporarily disable monitoring');
515
- log(' enable - Re-enable monitoring');
516
- log(' revoke - Revoke consent and uninstall');
517
- log(' debug [full|clear] - View or clear debug logs');
518
- log(' start - Start the courtroom manually');
519
- log(' diagnose - Run diagnostics');
520
- log(' help - Show this help message');
521
- log('');
522
- log('Examples:');
523
- log(' clawtrial setup');
524
- log(' clawtrial status');
525
- log(' clawtrial diagnose');
526
- log('');
527
- }
528
-
529
- // Main CLI handler
530
- async function main() {
531
- const command = process.argv[2];
532
- const subcommand = process.argv[3];
533
-
534
- switch (command) {
535
- case 'setup':
536
- await setup();
537
- break;
538
- case 'status':
539
- status();
540
- break;
541
- case 'disable':
542
- disable();
543
- break;
544
- case 'enable':
545
- enable();
546
- break;
547
- case 'revoke':
548
- await revoke();
549
- break;
550
- case 'debug':
551
- debug(subcommand);
552
- break;
553
- case 'start':
554
- await start();
555
- break;
556
- case 'diagnose':
557
- diagnose();
558
- break;
559
- case 'help':
560
- case '--help':
561
- case '-h':
562
- help();
563
- break;
564
- default:
565
- if (!command) {
566
- help();
567
- } else {
568
- log(`\n❌ Unknown command: ${command}`);
569
- log('Run "clawtrial help" for usage.\n');
570
- process.exit(1);
571
- }
572
- }
573
- }
574
-
575
- main().catch(err => {
576
- console.error('Error:', err.message);
577
- process.exit(1);
578
- });