@clawtrial/courtroom 1.0.3-b ā 1.0.3-d
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/package.json +1 -1
- package/scripts/clawtrial.js +74 -28
- package/scripts/daemon.js +71 -0
package/package.json
CHANGED
package/scripts/clawtrial.js
CHANGED
|
@@ -274,7 +274,7 @@ function enable() {
|
|
|
274
274
|
log('The courtroom will activate when ClawDBot loads the skill.\n');
|
|
275
275
|
}
|
|
276
276
|
|
|
277
|
-
// Start command -
|
|
277
|
+
// Start command - daemonize and run in background
|
|
278
278
|
async function start() {
|
|
279
279
|
const config = loadConfig();
|
|
280
280
|
|
|
@@ -302,35 +302,77 @@ async function start() {
|
|
|
302
302
|
|
|
303
303
|
log('\nšļø Starting ClawTrial...\n');
|
|
304
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
|
+
|
|
305
371
|
try {
|
|
306
|
-
|
|
307
|
-
|
|
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
|
-
}
|
|
372
|
+
process.kill(status.pid, 'SIGTERM');
|
|
373
|
+
log('ā
ClawTrial stopped\n');
|
|
330
374
|
} catch (err) {
|
|
331
|
-
log('
|
|
332
|
-
log('Try running: clawtrial diagnose\n');
|
|
333
|
-
process.exit(1);
|
|
375
|
+
log('ā ļø Could not stop process: ' + err.message + '\n');
|
|
334
376
|
}
|
|
335
377
|
}
|
|
336
378
|
|
|
@@ -516,6 +558,7 @@ function help() {
|
|
|
516
558
|
log(' revoke - Revoke consent and uninstall');
|
|
517
559
|
log(' debug [full|clear] - View or clear debug logs');
|
|
518
560
|
log(' start - Start the courtroom manually');
|
|
561
|
+
log(' stop - Stop the courtroom daemon');
|
|
519
562
|
log(' diagnose - Run diagnostics');
|
|
520
563
|
log(' help - Show this help message');
|
|
521
564
|
log('');
|
|
@@ -553,6 +596,9 @@ async function main() {
|
|
|
553
596
|
case 'start':
|
|
554
597
|
await start();
|
|
555
598
|
break;
|
|
599
|
+
case 'stop':
|
|
600
|
+
stop();
|
|
601
|
+
break;
|
|
556
602
|
case 'diagnose':
|
|
557
603
|
diagnose();
|
|
558
604
|
break;
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Courtroom Daemon - Runs the skill as a background process
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const { skill } = require('../src/skill');
|
|
8
|
+
const { StatusManager } = require('../src/daemon');
|
|
9
|
+
const fs = require('fs');
|
|
10
|
+
const path = require('path');
|
|
11
|
+
|
|
12
|
+
// Create minimal mock agent
|
|
13
|
+
const mockAgent = {
|
|
14
|
+
memory: {
|
|
15
|
+
get: async () => null,
|
|
16
|
+
set: async () => {}
|
|
17
|
+
},
|
|
18
|
+
send: async () => {}
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
// Create status manager
|
|
22
|
+
const statusManager = new StatusManager();
|
|
23
|
+
|
|
24
|
+
// Initialize skill
|
|
25
|
+
skill.initialize(mockAgent).then(() => {
|
|
26
|
+
const status = skill.getStatus();
|
|
27
|
+
if (status.initialized) {
|
|
28
|
+
console.log('šļø Courtroom daemon started, PID:', process.pid);
|
|
29
|
+
|
|
30
|
+
// Update status file
|
|
31
|
+
statusManager.update({
|
|
32
|
+
running: true,
|
|
33
|
+
initialized: true,
|
|
34
|
+
agentType: 'standalone_daemon',
|
|
35
|
+
pid: process.pid,
|
|
36
|
+
startedAt: new Date().toISOString()
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
// Keep process alive with heartbeat
|
|
40
|
+
setInterval(() => {
|
|
41
|
+
statusManager.update({ lastCheck: new Date().toISOString() });
|
|
42
|
+
}, 30000); // Every 30 seconds
|
|
43
|
+
|
|
44
|
+
console.log('šļø Courtroom is monitoring conversations');
|
|
45
|
+
} else {
|
|
46
|
+
console.error('ā Skill failed to initialize');
|
|
47
|
+
process.exit(1);
|
|
48
|
+
}
|
|
49
|
+
}).catch(err => {
|
|
50
|
+
console.error('ā Failed to start daemon:', err.message);
|
|
51
|
+
process.exit(1);
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
// Handle graceful shutdown
|
|
55
|
+
process.on('SIGTERM', async () => {
|
|
56
|
+
console.log('šļø Shutting down courtroom daemon...');
|
|
57
|
+
statusManager.update({ running: false });
|
|
58
|
+
if (skill) {
|
|
59
|
+
await skill.shutdown();
|
|
60
|
+
}
|
|
61
|
+
process.exit(0);
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
process.on('SIGINT', async () => {
|
|
65
|
+
console.log('šļø Shutting down courtroom daemon...');
|
|
66
|
+
statusManager.update({ running: false });
|
|
67
|
+
if (skill) {
|
|
68
|
+
await skill.shutdown();
|
|
69
|
+
}
|
|
70
|
+
process.exit(0);
|
|
71
|
+
});
|