@clawtrial/courtroom 1.0.6 β†’ 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,531 +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
- enabled: true
118
- };
119
-
120
- saveConfig(config);
121
- log('βœ“ Configuration saved');
122
-
123
- // Register as ClawDBot skill
124
- log('πŸ”— Registering with ClawDBot...');
125
- try {
126
- const skillsDir = path.join(process.env.HOME || '', '.clawdbot', 'skills');
127
- const skillLinkPath = path.join(skillsDir, 'courtroom');
128
-
129
- // Create skills directory if needed
130
- if (!fs.existsSync(skillsDir)) {
131
- fs.mkdirSync(skillsDir, { recursive: true });
132
- }
133
-
134
- // Remove old link if exists
135
- if (fs.existsSync(skillLinkPath)) {
136
- try { fs.unlinkSync(skillLinkPath); } catch (e) {}
137
- }
138
-
139
- // Get package path
140
- const packagePath = path.join(__dirname, '..');
141
-
142
- // Create symlink
143
- fs.symlinkSync(packagePath, skillLinkPath, 'dir');
144
-
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');
169
- } catch (err) {
170
- log('⚠️ Could not auto-register: ' + err.message);
171
- log(' You may need to restart ClawDBot manually.');
172
- }
173
-
174
- // Generate keys
175
- if (!fs.existsSync(keysPath)) {
176
- log('πŸ”‘ Generating cryptographic keys...');
177
- try {
178
- const nacl = require('tweetnacl');
179
- const keyPair = nacl.sign.keyPair();
180
-
181
- const keyData = {
182
- publicKey: Buffer.from(keyPair.publicKey).toString('hex'),
183
- secretKey: Buffer.from(keyPair.secretKey).toString('hex'),
184
- createdAt: new Date().toISOString()
185
- };
186
-
187
- fs.writeFileSync(keysPath, JSON.stringify(keyData, null, 2));
188
- fs.chmodSync(keysPath, 0o600);
189
-
190
- log('βœ“ Keys generated');
191
- log(`πŸ“‹ Public Key: ${keyData.publicKey.substring(0, 32)}...`);
192
- } catch (err) {
193
- log('⚠️ Could not generate keys: ' + err.message);
194
- }
195
- }
196
-
197
- log('\n╔════════════════════════════════════════════════════════════╗');
198
- log('β•‘ πŸŽ‰ SETUP COMPLETE! πŸŽ‰ β•‘');
199
- log('╠════════════════════════════════════════════════════════════╣');
200
- log('β•‘ β•‘');
201
- log('β•‘ ClawTrial is configured and ready! β•‘');
202
- log('β•‘ β•‘');
203
- log('β•‘ The courtroom will automatically activate when β•‘');
204
- log('β•‘ ClawDBot loads the skill. β•‘');
205
- log('β•‘ β•‘');
206
- log('β•‘ Commands: β•‘');
207
- log('β•‘ clawtrial status - Check status β•‘');
208
- log('β•‘ clawtrial disable - Temporarily disable β•‘');
209
- log('β•‘ clawtrial enable - Re-enable β•‘');
210
- log('β•‘ clawtrial revoke - Revoke consent & uninstall β•‘');
211
- log('β•‘ clawtrial debug - View debug logs β•‘');
212
- log('β•‘ clawtrial diagnose - Run diagnostics β•‘');
213
- log('β•‘ β•‘');
214
- log('β•‘ View cases: https://clawtrial.app β•‘');
215
- log('β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•\n');
216
- }
217
-
218
- // Status command
219
- function status() {
220
- const config = loadConfig();
221
-
222
- if (!config) {
223
- log('\n❌ ClawTrial not configured');
224
- log(' Run: clawtrial setup\n');
225
- return;
226
- }
227
-
228
- // Check if courtroom is running via status file
229
- const { getCourtroomStatus } = require('../src/daemon');
230
- const runtimeStatus = getCourtroomStatus();
231
-
232
- log('\nπŸ›οΈ ClawTrial Status\n');
233
- log(`Config: ${config.enabled !== false ? 'βœ… Active' : '⏸️ Disabled'}`);
234
- log(`Consent: ${config.consent?.granted ? 'βœ… Granted' : '❌ Not granted'}`);
235
- log(`Installed: ${new Date(config.installedAt).toLocaleDateString()}`);
236
-
237
- if (runtimeStatus.running) {
238
- log(`\nπŸ›οΈ Courtroom: βœ… Running`);
239
- log(` Process ID: ${runtimeStatus.pid}`);
240
- log(` Cases Filed: ${runtimeStatus.casesFiled || 0}`);
241
- if (runtimeStatus.lastCase) {
242
- log(` Last Case: ${new Date(runtimeStatus.lastCase.timestamp).toLocaleString()}`);
243
- }
244
- } else {
245
- log(`\nπŸ›οΈ Courtroom: ⏸️ Not running`);
246
- log(' The courtroom runs as a ClawDBot skill.');
247
- log(' It will activate when ClawDBot loads the package.');
248
- }
249
-
250
- if (fs.existsSync(keysPath)) {
251
- const keys = JSON.parse(fs.readFileSync(keysPath, 'utf8'));
252
- log(`\nπŸ“‹ Public Key: ${keys.publicKey.substring(0, 32)}...`);
253
- }
254
- log('');
255
- }
256
-
257
- // Disable command
258
- function disable() {
259
- const config = loadConfig();
260
-
261
- if (!config) {
262
- log('\n❌ ClawTrial not configured\n');
263
- return;
264
- }
265
-
266
- config.enabled = false;
267
- saveConfig(config);
268
- log('\n⏸️ ClawTrial disabled\n');
269
- log('The agent will stop monitoring for offenses.');
270
- log('Run "clawtrial enable" to reactivate.\n');
271
- }
272
-
273
- // Enable command
274
- function enable() {
275
- const config = loadConfig();
276
-
277
- if (!config) {
278
- log('\n❌ ClawTrial not configured');
279
- log(' Run: clawtrial setup\n');
280
- return;
281
- }
282
-
283
- if (!config.consent?.granted) {
284
- log('\n❌ Cannot enable: Consent not granted');
285
- log(' Run: clawtrial setup\n');
286
- return;
287
- }
288
-
289
- config.enabled = true;
290
- saveConfig(config);
291
- log('\nβœ… ClawTrial enabled\n');
292
- log('The courtroom will activate when ClawDBot loads the skill.\n');
293
- }
294
-
295
- // Revoke command
296
- async function revoke() {
297
- const config = loadConfig();
298
-
299
- if (!config) {
300
- log('\n❌ ClawTrial not configured\n');
301
- return;
302
- }
303
-
304
- log('\n⚠️ This will permanently disable ClawTrial and delete all data.\n');
305
-
306
- const rl = readline.createInterface({
307
- input: process.stdin,
308
- output: process.stdout
309
- });
310
-
311
- const answer = await new Promise((resolve) => {
312
- rl.question('Type "REVOKE" to confirm: ', resolve);
313
- });
314
-
315
- rl.close();
316
-
317
- if (answer === 'REVOKE') {
318
- // Delete all files
319
- if (fs.existsSync(configPath)) fs.unlinkSync(configPath);
320
- if (fs.existsSync(keysPath)) fs.unlinkSync(keysPath);
321
-
322
- const debugPath = path.join(process.env.HOME || '', '.clawdbot', 'courtroom_debug.log');
323
- if (fs.existsSync(debugPath)) fs.unlinkSync(debugPath);
324
-
325
- const statusPath = path.join(process.env.HOME || '', '.clawdbot', 'courtroom_status.json');
326
- if (fs.existsSync(statusPath)) fs.unlinkSync(statusPath);
327
-
328
- log('\nβœ… Consent revoked and all data deleted.\n');
329
- } else {
330
- log('\n❌ Revocation cancelled.\n');
331
- }
332
- }
333
-
334
- // Debug command
335
- function debug(subcommand) {
336
- const debugPath = path.join(process.env.HOME || '', '.clawdbot', 'courtroom_debug.log');
337
-
338
- if (!fs.existsSync(debugPath)) {
339
- log('\nℹ️ No debug logs found yet.');
340
- log(' Debug logs are created when the courtroom is active.\n');
341
- return;
342
- }
343
-
344
- if (subcommand === 'full') {
345
- log('\nπŸ›οΈ ClawTrial Full Debug Log\n');
346
- log('=============================\n');
347
- const logs = fs.readFileSync(debugPath, 'utf8').split('\n').filter(Boolean);
348
- logs.slice(-100).forEach(line => {
349
- try {
350
- const log = JSON.parse(line);
351
- log(`[${log.timestamp}] ${log.level} - ${log.component}`);
352
- log(` ${log.message}`);
353
- } catch (e) {
354
- log(line);
355
- }
356
- });
357
- log('');
358
- } else if (subcommand === 'clear') {
359
- fs.unlinkSync(debugPath);
360
- log('\nβœ… Debug logs cleared\n');
361
- } else {
362
- // Show status
363
- const logs = fs.readFileSync(debugPath, 'utf8').split('\n').filter(Boolean);
364
- const recentLogs = logs.slice(-20);
365
-
366
- log('\nπŸ›οΈ ClawTrial Debug Status\n');
367
- log('===========================\n');
368
- log(`Total log entries: ${logs.length}`);
369
- log(`Log file: ${debugPath}`);
370
- log('\nRecent activity:');
371
-
372
- recentLogs.forEach(line => {
373
- try {
374
- const log = JSON.parse(line);
375
- log(` [${log.level}] ${log.component}: ${log.message.substring(0, 60)}`);
376
- } catch (e) {
377
- // Skip malformed lines
378
- }
379
- });
380
-
381
- log('\nUsage:');
382
- log(' clawtrial debug - Show status and recent logs');
383
- log(' clawtrial debug full - Show full debug log');
384
- log(' clawtrial debug clear - Clear all logs');
385
- log('');
386
- }
387
- }
388
-
389
- // Diagnose command
390
- function diagnose() {
391
- log('\nπŸ›οΈ ClawTrial Diagnostics\n');
392
- log('========================\n');
393
-
394
- // Check Node version
395
- const nodeVersion = process.version;
396
- const majorVersion = parseInt(nodeVersion.slice(1).split('.')[0]);
397
- log(`Node.js version: ${nodeVersion} ${majorVersion >= 18 ? 'βœ…' : '❌ (needs >= 18)'}`);
398
-
399
- // Check environment
400
- const { checkEnvironment } = require('../src/environment');
401
- const env = checkEnvironment();
402
- log(`\nEnvironment: ${env.valid ? 'βœ… Valid' : '❌ Issues found'}`);
403
- if (!env.valid) {
404
- env.issues.forEach(issue => log(` ❌ ${issue}`));
405
- }
406
-
407
- // Check config
408
- const config = loadConfig();
409
- if (config) {
410
- log(`\nConfig: βœ… Found`);
411
- log(` Installed: ${new Date(config.installedAt).toLocaleDateString()}`);
412
- log(` Consent: ${config.consent?.granted ? 'βœ… Granted' : '❌ Not granted'}`);
413
- log(` Status: ${config.enabled !== false ? 'βœ… Enabled' : '⏸️ Disabled'}`);
414
- } else {
415
- log(`\nConfig: ❌ Not found`);
416
- log(' Run: clawtrial setup');
417
- }
418
-
419
- // Check keys
420
- if (fs.existsSync(keysPath)) {
421
- log(`\nKeys: βœ… Found`);
422
- const keys = JSON.parse(fs.readFileSync(keysPath, 'utf8'));
423
- log(` Public Key: ${keys.publicKey.substring(0, 32)}...`);
424
- } else {
425
- log(`\nKeys: ❌ Not found`);
426
- }
427
-
428
- // Check if courtroom is running
429
- const { getCourtroomStatus } = require('../src/daemon');
430
- const runtimeStatus = getCourtroomStatus();
431
-
432
- if (runtimeStatus.running) {
433
- log(`\nπŸ›οΈ Courtroom: βœ… Running`);
434
- log(` Process ID: ${runtimeStatus.pid}`);
435
- log(` Started: ${new Date(runtimeStatus.startedAt).toLocaleString()}`);
436
- log(` Cases Filed: ${runtimeStatus.casesFiled || 0}`);
437
- } else {
438
- log(`\nπŸ›οΈ Courtroom: ⏸️ Not running`);
439
- log(' The courtroom runs as a ClawDBot skill.');
440
- log(' It will activate when ClawDBot loads the package.');
441
- }
442
-
443
- // Check debug logs
444
- const debugPath = path.join(process.env.HOME || '', '.clawdbot', 'courtroom_debug.log');
445
- if (fs.existsSync(debugPath)) {
446
- const logs = fs.readFileSync(debugPath, 'utf8').split('\n').filter(Boolean);
447
- log(`\nDebug Logs: βœ… ${logs.length} entries`);
448
- } else {
449
- log(`\nDebug Logs: ℹ️ None yet (created when active)`);
450
- }
451
-
452
- log('\n========================\n');
453
-
454
- if (!config) {
455
- log('Next step: Run "clawtrial setup"');
456
- } else if (!runtimeStatus.running) {
457
- log('Status: Configured. Courtroom will activate with ClawDBot.');
458
- } else {
459
- log('Status: Fully operational! πŸŽ‰');
460
- }
461
- log('');
462
- }
463
-
464
- // Help command
465
- function help() {
466
- log('\nπŸ›οΈ ClawTrial - AI Courtroom for Agents\n');
467
- log('Usage: clawtrial <command> [options]\n');
468
- log('Commands:');
469
- log(' setup - Interactive setup and consent');
470
- log(' status - Check courtroom status');
471
- log(' disable - Temporarily disable monitoring');
472
- log(' enable - Re-enable monitoring');
473
- log(' revoke - Revoke consent and uninstall');
474
- log(' debug [full|clear] - View or clear debug logs');
475
- log(' diagnose - Run diagnostics');
476
- log(' help - Show this help message');
477
- log('');
478
- log('Examples:');
479
- log(' clawtrial setup');
480
- log(' clawtrial status');
481
- log(' clawtrial diagnose');
482
- log('');
483
- }
484
-
485
- // Main CLI handler
486
- async function main() {
487
- const command = process.argv[2];
488
- const subcommand = process.argv[3];
489
-
490
- switch (command) {
491
- case 'setup':
492
- await setup();
493
- break;
494
- case 'status':
495
- status();
496
- break;
497
- case 'disable':
498
- disable();
499
- break;
500
- case 'enable':
501
- enable();
502
- break;
503
- case 'revoke':
504
- await revoke();
505
- break;
506
- case 'debug':
507
- debug(subcommand);
508
- break;
509
- case 'diagnose':
510
- diagnose();
511
- break;
512
- case 'help':
513
- case '--help':
514
- case '-h':
515
- help();
516
- break;
517
- default:
518
- if (!command) {
519
- help();
520
- } else {
521
- log(`\n❌ Unknown command: ${command}`);
522
- log('Run "clawtrial help" for usage.\n');
523
- process.exit(1);
524
- }
525
- }
526
- }
527
-
528
- main().catch(err => {
529
- console.error('Error:', err.message);
530
- process.exit(1);
531
- });