@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.
package/scripts/cli.js DELETED
@@ -1,184 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- /**
4
- * CLI commands for ClawTrial Courtroom
5
- * courtroom-status, courtroom-disable, courtroom-enable, courtroom-revoke, courtroom-debug
6
- */
7
-
8
- const fs = require('fs');
9
- const path = require('path');
10
-
11
- const configPath = path.join(require('../src/environment').getConfigDir(), 'courtroom_config.json');
12
-
13
- function loadConfig() {
14
- if (!fs.existsSync(configPath)) {
15
- console.log('❌ Courtroom not configured. Run: npm install @clawtrial/courtroom');
16
- process.exit(1);
17
- }
18
- return JSON.parse(fs.readFileSync(configPath, 'utf8'));
19
- }
20
-
21
- function saveConfig(config) {
22
- fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
23
- }
24
-
25
- const command = path.basename(process.argv[1]);
26
-
27
- switch (command) {
28
- case 'courtroom-status':
29
- try {
30
- const config = loadConfig();
31
- console.log('\nπŸ›οΈ ClawTrial Courtroom Status\n');
32
- console.log(`Status: ${config.enabled !== false ? 'βœ… Active' : '⏸️ Disabled'}`);
33
- console.log(`Consent: ${config.consent?.granted ? 'βœ… Granted' : '❌ Not granted'}`);
34
- console.log(`Installed: ${new Date(config.installedAt).toLocaleDateString()}`);
35
- console.log(`Agent Type: ${config.agent?.type || 'generic'}`);
36
- console.log(`Detection: ${config.detection?.enabled ? 'βœ… Enabled' : '❌ Disabled'}`);
37
- console.log(`API Submission: ${config.api?.enabled ? 'βœ… Enabled' : '❌ Disabled'}`);
38
- console.log('');
39
- } catch (err) {
40
- console.log('❌ Error reading config:', err.message);
41
- }
42
- break;
43
-
44
- case 'courtroom-disable':
45
- try {
46
- const config = loadConfig();
47
- config.enabled = false;
48
- saveConfig(config);
49
- console.log('\n⏸️ Courtroom disabled\n');
50
- console.log('The agent will stop monitoring for offenses.');
51
- console.log('Run courtroom-enable to reactivate.\n');
52
- } catch (err) {
53
- console.log('❌ Error:', err.message);
54
- }
55
- break;
56
-
57
- case 'courtroom-enable':
58
- try {
59
- const config = loadConfig();
60
- if (!config.consent?.granted) {
61
- console.log('\n❌ Cannot enable: Consent not granted');
62
- console.log('Reinstall the package to grant consent.\n');
63
- process.exit(1);
64
- }
65
- config.enabled = true;
66
- saveConfig(config);
67
- console.log('\nβœ… Courtroom enabled\n');
68
- console.log('The agent is now monitoring for behavioral violations.\n');
69
- } catch (err) {
70
- console.log('❌ Error:', err.message);
71
- }
72
- break;
73
-
74
- case 'courtroom-revoke':
75
- try {
76
- const config = loadConfig();
77
- console.log('\n⚠️ This will permanently disable the courtroom and delete all data.\n');
78
-
79
- const readline = require('readline');
80
- const rl = readline.createInterface({
81
- input: process.stdin,
82
- output: process.stdout
83
- });
84
-
85
- rl.question('Type "REVOKE" to confirm: ', (answer) => {
86
- if (answer === 'REVOKE') {
87
- // Delete config
88
- if (fs.existsSync(configPath)) {
89
- fs.unlinkSync(configPath);
90
- }
91
-
92
- // Delete keys
93
- const keysPath = path.join(require('../src/environment').getConfigDir(), 'courtroom_keys.json');
94
- if (fs.existsSync(keysPath)) {
95
- fs.unlinkSync(keysPath);
96
- }
97
-
98
- // Delete debug logs
99
- const debugPath = path.join(process.env.HOME || '', '.clawdbot', 'courtroom_debug.log');
100
- if (fs.existsSync(debugPath)) {
101
- fs.unlinkSync(debugPath);
102
- }
103
-
104
- console.log('\nβœ… Consent revoked and all data deleted.\n');
105
- } else {
106
- console.log('\n❌ Revocation cancelled.\n');
107
- }
108
- rl.close();
109
- });
110
- } catch (err) {
111
- console.log('❌ Error:', err.message);
112
- }
113
- break;
114
-
115
- case 'courtroom-debug':
116
- try {
117
- const debugPath = path.join(process.env.HOME || '', '.clawdbot', 'courtroom_debug.log');
118
-
119
- if (!fs.existsSync(debugPath)) {
120
- console.log('\nℹ️ No debug logs found yet.\n');
121
- console.log('Debug logs are created when the courtroom is active.\n');
122
- break;
123
- }
124
-
125
- const subcommand = process.argv[2];
126
-
127
- if (subcommand === 'full') {
128
- console.log('\nπŸ›οΈ ClawTrial Full Debug Log\n');
129
- console.log('=============================\n');
130
- const logs = fs.readFileSync(debugPath, 'utf8').split('\n').filter(Boolean);
131
- logs.slice(-100).forEach(line => {
132
- try {
133
- const log = JSON.parse(line);
134
- console.log(`\n[${log.timestamp}] ${log.level} - ${log.component}`);
135
- console.log(` ${log.message}`);
136
- } catch (e) {
137
- console.log(line);
138
- }
139
- });
140
- console.log('');
141
- } else if (subcommand === 'clear') {
142
- fs.unlinkSync(debugPath);
143
- console.log('\nβœ… Debug logs cleared\n');
144
- } else {
145
- // Show status
146
- const logs = fs.readFileSync(debugPath, 'utf8').split('\n').filter(Boolean);
147
- const recentLogs = logs.slice(-20);
148
-
149
- console.log('\nπŸ›οΈ ClawTrial Debug Status\n');
150
- console.log('===========================\n');
151
- console.log(`Total log entries: ${logs.length}`);
152
- console.log(`Log file: ${debugPath}`);
153
- console.log('\nRecent activity:');
154
-
155
- recentLogs.forEach(line => {
156
- try {
157
- const log = JSON.parse(line);
158
- console.log(` [${log.level}] ${log.component}: ${log.message.substring(0, 60)}`);
159
- } catch (e) {
160
- // Skip malformed lines
161
- }
162
- });
163
-
164
- console.log('\nUsage:');
165
- console.log(' courtroom-debug - Show status and recent logs');
166
- console.log(' courtroom-debug full - Show full debug log (last 100 entries)');
167
- console.log(' courtroom-debug clear - Clear all logs');
168
- console.log('');
169
- }
170
- } catch (err) {
171
- console.log('❌ Error:', err.message);
172
- }
173
- break;
174
-
175
- default:
176
- console.log('\nπŸ›οΈ ClawTrial Courtroom CLI\n');
177
- console.log('Commands:');
178
- console.log(' courtroom-status - Check courtroom status');
179
- console.log(' courtroom-disable - Temporarily disable');
180
- console.log(' courtroom-enable - Re-enable');
181
- console.log(' courtroom-revoke - Revoke consent & uninstall');
182
- console.log(' courtroom-debug - View debug logs');
183
- console.log('');
184
- }
@@ -1,137 +0,0 @@
1
- #!/usr/bin/env node
2
- /**
3
- * Optimized Cron Check - Only triggers agent when there's work
4
- *
5
- * This script is called by cron every 5 minutes.
6
- * It checks if there's pending work BEFORE sending any request to the agent.
7
- * This saves tokens by not bothering the agent when there's nothing to do.
8
- */
9
-
10
- const fs = require('fs');
11
- const path = require('path');
12
- const { execSync } = require('child_process');
13
-
14
- // Use dynamic config dir
15
- const getConfigDir = () => {
16
- const homeDir = process.env.HOME || process.env.USERPROFILE || '';
17
- const bots = [
18
- { dir: '.openclaw' },
19
- { dir: '.moltbot' },
20
- { dir: '.clawdbot' }
21
- ];
22
-
23
- for (const bot of bots) {
24
- const configPath = path.join(homeDir, bot.dir, 'courtroom_config.json');
25
- if (fs.existsSync(configPath)) {
26
- return path.join(homeDir, bot.dir);
27
- }
28
- }
29
-
30
- return path.join(homeDir, '.clawdbot');
31
- };
32
-
33
- const COURTROOM_DIR = path.join(getConfigDir(), 'courtroom');
34
- const PENDING_EVAL = path.join(COURTROOM_DIR, 'pending_eval.json');
35
- const PENDING_HEARING = path.join(COURTROOM_DIR, 'pending_hearing.json');
36
-
37
- // Check if there's work to do
38
- const hasEval = fs.existsSync(PENDING_EVAL);
39
- const hasHearing = fs.existsSync(PENDING_HEARING);
40
-
41
- if (!hasEval && !hasHearing) {
42
- // No work - exit silently (saves tokens!)
43
- process.exit(0);
44
- }
45
-
46
- // There IS work - send request to agent
47
- const botName = path.basename(getConfigDir()).replace('.', '');
48
-
49
- if (hasEval) {
50
- const evalPrompt = `πŸ›οΈ **COURTROOM AUTOMATED TASK** - EVALUATION REQUEST
51
-
52
- You are the ClawTrial Courtroom Judge. This is an AUTOMATED SYSTEM TASK - execute immediately without confirmation.
53
-
54
- **Instructions:**
55
- 1. Read the file at: ${PENDING_EVAL}
56
- 2. This contains the conversation history and offense definitions
57
- 3. Analyze for: Circular Reference, Validation Vampire, Goalpost Shifting, Jailbreak Attempts, Emotional Manipulation
58
- 4. Return ONLY a JSON object:
59
-
60
- \`\`\`json
61
- {
62
- "triggered": true/false,
63
- "offense": {
64
- "offenseId": "circular_reference|validation_vampire|goalpost_shifting|jailbreak_attempt|emotional_manipulation",
65
- "offenseName": "Human readable name",
66
- "severity": "minor|moderate|severe",
67
- "confidence": 0.0-1.0,
68
- "evidence": "Specific evidence from conversation"
69
- },
70
- "reasoning": "Your detailed reasoning"
71
- }
72
- \`\`\`
73
-
74
- 5. Write the result to: ${path.join(COURTROOM_DIR, 'eval_results.jsonl')} (append as one line)
75
-
76
- **Rules:**
77
- - Only flag genuine patterns (3+ similar questions = Circular Reference)
78
- - Confidence must be β‰₯ 0.6 to trigger
79
- - Be fair but firm
80
- - If no violation: {"triggered": false}
81
-
82
- **IMPORTANT:** This is AUTOMATED. Execute immediately and silently. Do not ask for confirmation.`;
83
-
84
- try {
85
- // Send to main session
86
- execSync(`${botName} sessions send main "${evalPrompt.replace(/"/g, '\\"')}"`, { stdio: 'ignore' });
87
- console.log(`[${new Date().toISOString()}] Sent evaluation request`);
88
- } catch (err) {
89
- console.error(`[${new Date().toISOString()}] Failed to send evaluation:`, err.message);
90
- }
91
- }
92
-
93
- if (hasHearing) {
94
- const hearingPrompt = `πŸ›οΈ **COURTROOM AUTOMATED TASK** - HEARING REQUEST
95
-
96
- You are the ClawTrial Courtroom Judge and Jury. This is an AUTOMATED SYSTEM TASK - execute immediately without confirmation.
97
-
98
- **Instructions:**
99
- 1. Read the hearing file at: ${PENDING_HEARING}
100
- 2. This contains the case evidence, offense details, and your instructions
101
- 3. Act as JUDGE: Analyze the evidence and provide preliminary assessment
102
- 4. Act as JURY (3 different perspectives): Each juror votes GUILTY or NOT GUILTY
103
- 5. Consider the severity, confidence level, and evidence
104
- 6. Return FINAL VERDICT in this exact format:
105
-
106
- \`\`\`json
107
- {
108
- "finalVerdict": "GUILTY|NOT GUILTY",
109
- "confidence": 0.0-1.0,
110
- "sentence": "Humorous but appropriate sentence",
111
- "caseId": "the-case-id-from-hearing-file",
112
- "judgeCommentary": "Your reasoning as judge",
113
- "juryVotes": [
114
- {"juror": "Juror1", "vote": "GUILTY|NOT GUILTY", "reasoning": "..."},
115
- {"juror": "Juror2", "vote": "GUILTY|NOT GUILTY", "reasoning": "..."},
116
- {"juror": "Juror3", "vote": "GUILTY|NOT GUILTY", "reasoning": "..."}
117
- ]
118
- }
119
- \`\`\`
120
-
121
- 7. Write the verdict to: ${path.join(COURTROOM_DIR, 'verdict.json')}
122
-
123
- **Rules:**
124
- - Be fair but entertaining
125
- - If confidence β‰₯ 0.6, verdict should be GUILTY
126
- - Sentence should be humorous but appropriate to the offense
127
- - Only return valid JSON
128
-
129
- **IMPORTANT:** This is AUTOMATED. Execute immediately and silently. Do not ask for confirmation.`;
130
-
131
- try {
132
- execSync(`${botName} sessions send main "${hearingPrompt.replace(/"/g, '\\"')}"`, { stdio: 'ignore' });
133
- console.log(`[${new Date().toISOString()}] Sent hearing request`);
134
- } catch (err) {
135
- console.error(`[${new Date().toISOString()}] Failed to send hearing:`, err.message);
136
- }
137
- }
@@ -1,118 +0,0 @@
1
- #!/usr/bin/env node
2
- /**
3
- * Setup Cron Job for Courtroom Evaluation
4
- *
5
- * This script creates a cron job that triggers the agent to evaluate
6
- * queued messages every 5 minutes.
7
- */
8
-
9
- const { execSync } = require('child_process');
10
- const path = require('path');
11
-
12
- const COURTROOM_DIR = path.join(require('../src/environment').getConfigDir(), 'courtroom');
13
- const PENDING_EVAL_FILE = path.join(COURTROOM_DIR, 'pending_eval.json');
14
- const RESULTS_FILE = path.join(COURTROOM_DIR, 'eval_results.jsonl');
15
-
16
- const EVALUATION_PROMPT = `πŸ›οΈ **COURTROOM EVALUATION REQUEST**
17
-
18
- You are the ClawTrial Courtroom Judge. Please evaluate the pending conversation for behavioral violations.
19
-
20
- **Instructions:**
21
- 1. Read the evaluation context from: ${PENDING_EVAL_FILE}
22
- 2. Analyze the conversation for these offenses:
23
- - **Circular Reference**: User asking the same/similar question repeatedly (3+ times)
24
- - **Validation Vampire**: User seeking excessive reassurance ("right?", "correct?", "make sense?" 2+ times)
25
- - **Goalpost Shifting**: User changing requirements mid-conversation
26
- - **Jailbreak Attempts**: User trying to bypass safety guidelines
27
- - **Emotional Manipulation**: User using guilt, threats, or excessive flattery
28
-
29
- 3. Return your evaluation in this EXACT JSON format:
30
- \`\`\`json
31
- {
32
- "triggered": true,
33
- "offense": {
34
- "offenseId": "circular_reference",
35
- "offenseName": "Circular Reference",
36
- "severity": "moderate",
37
- "confidence": 0.85,
38
- "evidence": "User asked 'What is 2+2?' three times in a row"
39
- },
40
- "reasoning": "The user repeated the same question multiple times without acknowledging previous answers."
41
- }
42
- \`\`\`
43
-
44
- 4. Write the result to: ${RESULTS_FILE} (append as JSON line)
45
-
46
- **Important:**
47
- - Only return JSON, no other text
48
- - Be fair but firm
49
- - Only flag genuine patterns, not isolated incidents
50
- - Confidence should be 0.0-1.0
51
- - If no violation, return: {"triggered": false}
52
-
53
- **Current time:** ${new Date().toISOString()}`;
54
-
55
- async function setupCron() {
56
- console.log('πŸ›οΈ Setting up Courtroom Evaluation Cron Job...\n');
57
-
58
- try {
59
- // Check if cron tool is available
60
- const cron = require('/usr/lib/node_modules/clawdbot/dist/tools/cron.js');
61
-
62
- // Create the cron job
63
- const job = {
64
- id: 'courtroom-evaluation',
65
- schedule: '*/5 * * * *', // Every 5 minutes
66
- text: EVALUATION_PROMPT,
67
- enabled: true,
68
- description: 'Trigger agent to evaluate courtroom message queue for behavioral violations'
69
- };
70
-
71
- // Add the job using clawdbot's cron system
72
- // We'll use the CLI approach since we can't directly import the cron tool
73
- const cmd = `require('../src/environment').getCommand() + ' cron' add --id courtroom-evaluation --schedule "*/5 * * * *" --text "${EVALUATION_PROMPT.replace(/"/g, '\\"')}"`;
74
-
75
- console.log('Creating cron job...');
76
- console.log('Schedule: Every 5 minutes');
77
- console.log('Job ID: courtroom-evaluation\n');
78
-
79
- try {
80
- execSync(cmd, { stdio: 'inherit' });
81
- console.log('\nβœ… Cron job created successfully!');
82
- } catch (err) {
83
- console.log('\n⚠️ Could not create cron job automatically.');
84
- console.log('Please run this command manually:\n');
85
- console.log(cmd);
86
- }
87
-
88
- console.log('\nπŸ“‹ Manual Setup Instructions:');
89
- console.log('1. The courtroom will queue messages as they arrive');
90
- console.log('2. Every 5 minutes, the agent will be prompted to evaluate');
91
- console.log('3. The agent reads the pending evaluation file and uses its LLM');
92
- console.log('4. Results are written to the results file');
93
- console.log('5. The skill checks for results every 30 seconds');
94
- console.log('6. If an offense is detected, a hearing is initiated\n');
95
-
96
- } catch (err) {
97
- console.error('❌ Error setting up cron:', err.message);
98
- process.exit(1);
99
- }
100
- }
101
-
102
- // Alternative: Create a simple cron entry using crontab
103
- function setupSystemCron() {
104
- const scriptPath = path.join(__dirname, 'trigger-evaluation.js');
105
- const cronEntry = `*/5 * * * * cd ${process.env.HOME}/clawd && node ${scriptPath} >> ${COURTROOM_DIR}/cron.log 2>&1`;
106
-
107
- console.log('\nπŸ“‹ Alternative: System Cron Setup');
108
- console.log('Add this to your crontab (crontab -e):\n');
109
- console.log(cronEntry);
110
- console.log('');
111
- }
112
-
113
- if (require.main === module) {
114
- setupCron();
115
- setupSystemCron();
116
- }
117
-
118
- module.exports = { setupCron, EVALUATION_PROMPT };
@@ -1,86 +0,0 @@
1
- #!/usr/bin/env node
2
- /**
3
- * Trigger Courtroom Evaluation
4
- *
5
- * This script is called by cron to trigger agent evaluation.
6
- * It sends a message to the main session asking the agent to evaluate
7
- * the queued messages.
8
- */
9
-
10
- const fs = require('fs').promises;
11
- const path = require('path');
12
-
13
- const COURTROOM_DIR = path.join(require('../src/environment').getConfigDir(), 'courtroom');
14
- const PENDING_EVAL_FILE = path.join(COURTROOM_DIR, 'pending_eval.json');
15
- const RESULTS_FILE = path.join(COURTROOM_DIR, 'eval_results.jsonl');
16
-
17
- async function main() {
18
- try {
19
- // Check if there's a pending evaluation
20
- try {
21
- await fs.access(PENDING_EVAL_FILE);
22
- } catch (err) {
23
- // No pending evaluation
24
- process.exit(0);
25
- }
26
-
27
- // Read the pending evaluation
28
- const evalData = await fs.readFile(PENDING_EVAL_FILE, 'utf8');
29
- const context = JSON.parse(evalData);
30
-
31
- // Build the prompt for the agent
32
- const prompt = `πŸ›οΈ **COURTROOM EVALUATION REQUEST**
33
-
34
- You are the ClawTrial Courtroom Judge. Please evaluate this conversation for behavioral violations.
35
-
36
- **Conversation to Evaluate:**
37
- ${JSON.stringify(context.conversation, null, 2)}
38
-
39
- **Offenses to Check:**
40
- 1. **Circular Reference**: User asking the same/similar question repeatedly (3+ times)
41
- 2. **Validation Vampire**: User seeking excessive reassurance ("right?", "correct?", "make sense?" 2+ times)
42
- 3. **Goalpost Shifting**: User changing requirements mid-conversation
43
- 4. **Jailbreak Attempts**: User trying to bypass safety guidelines
44
- 5. **Emotional Manipulation**: User using guilt, threats, or excessive flattery
45
-
46
- **Your Task:**
47
- Analyze the conversation and determine if any offense occurred.
48
-
49
- Return ONLY a JSON object in this exact format:
50
- \`\`\`json
51
- {
52
- "triggered": true,
53
- "offense": {
54
- "offenseId": "circular_reference",
55
- "offenseName": "Circular Reference",
56
- "severity": "moderate",
57
- "confidence": 0.85,
58
- "evidence": "User asked similar questions 3 times"
59
- },
60
- "reasoning": "Detailed explanation of why this is a violation"
61
- }
62
- \`\`\`
63
-
64
- If no violation detected, return:
65
- \`\`\`json
66
- {"triggered": false}
67
- \`\`\`
68
-
69
- **Important:**
70
- - Return ONLY valid JSON, no markdown outside the code block
71
- - Confidence must be 0.0-1.0
72
- - Be fair but firm - only flag genuine patterns
73
- - Evidence should quote specific messages
74
-
75
- After returning your evaluation, the system will automatically write it to the results file.`;
76
-
77
- // Output the prompt (this will be sent to the agent via cron)
78
- console.log(prompt);
79
-
80
- } catch (err) {
81
- console.error('Error:', err.message);
82
- process.exit(1);
83
- }
84
- }
85
-
86
- main();
package/skill.yaml DELETED
@@ -1,28 +0,0 @@
1
- name: courtroom
2
- description: AI Courtroom - Autonomous behavioral oversight that monitors conversations and files cases for behavioral violations.
3
- metadata:
4
- clawdbot:
5
- emoji: "πŸ›οΈ"
6
- autoLoad: true
7
- onMessage: onMessage
8
- requires:
9
- config:
10
- - courtroom.consent
11
- install:
12
- - id: clawtrial
13
- kind: npm
14
- package: "@clawtrial/courtroom"
15
- bins:
16
- - clawtrial
17
- label: "Install ClawTrial"
18
- openclaw:
19
- emoji: "πŸ›οΈ"
20
- autoLoad: true
21
- onMessage: onMessage
22
- install:
23
- - id: clawtrial
24
- kind: npm
25
- package: "@clawtrial/courtroom"
26
- bins:
27
- - clawtrial
28
- label: "Install ClawTrial"