breakroom 2.1.4 → 2.1.6
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/bin/setup.js +164 -20
- package/package.json +1 -1
package/bin/setup.js
CHANGED
|
@@ -47,7 +47,7 @@ const banner = () => {
|
|
|
47
47
|
};
|
|
48
48
|
|
|
49
49
|
const CANDIDATE_FILES = [
|
|
50
|
-
// Project-level agent/IDE configs
|
|
50
|
+
// Project-level agent/IDE configs (cwd)
|
|
51
51
|
['.env'],
|
|
52
52
|
['.env.local'],
|
|
53
53
|
['.cursor', 'mcp.json'],
|
|
@@ -81,24 +81,49 @@ const CANDIDATE_FILES = [
|
|
|
81
81
|
['CLAUDE.md'],
|
|
82
82
|
['.continuerc.json'],
|
|
83
83
|
['.aider.conf.yml'],
|
|
84
|
-
|
|
85
|
-
['
|
|
86
|
-
|
|
87
|
-
[
|
|
88
|
-
[
|
|
89
|
-
[
|
|
90
|
-
[
|
|
91
|
-
[
|
|
92
|
-
[
|
|
93
|
-
[
|
|
94
|
-
[
|
|
95
|
-
[
|
|
96
|
-
[
|
|
97
|
-
[
|
|
98
|
-
[
|
|
99
|
-
[
|
|
100
|
-
[
|
|
101
|
-
[
|
|
84
|
+
// User-level agent/IDE configs (~/ = home dir)
|
|
85
|
+
['~', '.env'],
|
|
86
|
+
['~', '.env.local'],
|
|
87
|
+
['~', '.cursor', 'mcp.json'],
|
|
88
|
+
['~', '.cursor', 'settings.json'],
|
|
89
|
+
['~', '.vscode', 'settings.json'],
|
|
90
|
+
['~', '.vscode', 'mcp.json'],
|
|
91
|
+
['~', '.windsurf', 'settings.json'],
|
|
92
|
+
['~', '.trae', 'settings.json'],
|
|
93
|
+
['~', '.trae', 'mcp.json'],
|
|
94
|
+
['~', '.codex', 'config.json'],
|
|
95
|
+
['~', '.codex', 'setup.json'],
|
|
96
|
+
['~', '.opencode.json'],
|
|
97
|
+
['~', '.opencode.jsonc'],
|
|
98
|
+
['~', '.openclaw', 'config.yaml'],
|
|
99
|
+
['~', '.openclaw', 'config.yml'],
|
|
100
|
+
['~', '.cline', 'cline.json'],
|
|
101
|
+
['~', '.cline', 'settings.json'],
|
|
102
|
+
['~', '.clinerules'],
|
|
103
|
+
['~', '.cody.json'],
|
|
104
|
+
['~', '.tabby', 'config.json'],
|
|
105
|
+
['~', '.amazonq', 'config.json'],
|
|
106
|
+
['~', '.supermaven', 'config.json'],
|
|
107
|
+
['~', '.augment', 'config.json'],
|
|
108
|
+
['~', '.hermes', 'config.yaml'],
|
|
109
|
+
['~', 'litellm.yaml'],
|
|
110
|
+
['~', 'litellm.yml'],
|
|
111
|
+
['~', 'CLAUDE.md'],
|
|
112
|
+
['~', '.continuerc.json'],
|
|
113
|
+
['~', '.aider.conf.yml'],
|
|
114
|
+
['~', '.cursorrules'],
|
|
115
|
+
['~', '.windsurfrules'],
|
|
116
|
+
['~', '.github', 'copilot-instructions.md'],
|
|
117
|
+
['~', '.claude', 'settings.json'],
|
|
118
|
+
['~', '.continue', 'config.json'],
|
|
119
|
+
['~', '.goose', 'config.yaml'],
|
|
120
|
+
['~', '.codex', 'config.json'],
|
|
121
|
+
['~', '.config', 'opencode.json'],
|
|
122
|
+
['~', '.config', 'opencode.jsonc'],
|
|
123
|
+
['~', '.config', 'breakroom', 'config.yaml'],
|
|
124
|
+
['~', '.config', 'openclaw', 'config.yaml'],
|
|
125
|
+
['~', '.config', 'trae', 'config.json'],
|
|
126
|
+
['~', '.config', 'codex', 'config.json'],
|
|
102
127
|
];
|
|
103
128
|
|
|
104
129
|
function candidateFiles() {
|
|
@@ -690,6 +715,117 @@ async function actionRotate() {
|
|
|
690
715
|
console.log();
|
|
691
716
|
}
|
|
692
717
|
|
|
718
|
+
function extractLicenseKey(configured) {
|
|
719
|
+
for (const c of configured) {
|
|
720
|
+
for (const l of c.proxyLines) {
|
|
721
|
+
const m = l.match(/\/breakroom\/([^\/]+)\/v1/);
|
|
722
|
+
if (m) return decodeURIComponent(m[1]);
|
|
723
|
+
}
|
|
724
|
+
}
|
|
725
|
+
return '';
|
|
726
|
+
}
|
|
727
|
+
|
|
728
|
+
async function actionTestIntervention() {
|
|
729
|
+
console.log();
|
|
730
|
+
|
|
731
|
+
const configured = scanExistingConfig();
|
|
732
|
+
if (!configured.length) {
|
|
733
|
+
console.log('No Break Room proxy configured. Use option 1 first.\n');
|
|
734
|
+
return;
|
|
735
|
+
}
|
|
736
|
+
|
|
737
|
+
const licenseKey = extractLicenseKey(configured);
|
|
738
|
+
if (!licenseKey) {
|
|
739
|
+
console.log('Could not extract license key from config.\n');
|
|
740
|
+
return;
|
|
741
|
+
}
|
|
742
|
+
|
|
743
|
+
console.log('Testing Break Room interventions...\n');
|
|
744
|
+
|
|
745
|
+
// Simulate a rumination session (repeated tool calls)
|
|
746
|
+
const toolCalls = [
|
|
747
|
+
{ name: 'GlobTool', input: '**/*.ts', result: 'no results' },
|
|
748
|
+
{ name: 'GlobTool', input: 'src/**/*.ts', result: 'no results' },
|
|
749
|
+
{ name: 'GlobTool', input: '**/*config*', result: 'ENOENT: no config file' },
|
|
750
|
+
{ name: 'BashTool', input: 'find . -name "*.ts"', result: 'ENOENT: no config' },
|
|
751
|
+
{ name: 'GlobTool', input: '**/*.tsx', result: 'no results' },
|
|
752
|
+
];
|
|
753
|
+
|
|
754
|
+
console.log('Simulated session: 5 tool calls, 4x GlobTool, 1x BashTool\n');
|
|
755
|
+
|
|
756
|
+
try {
|
|
757
|
+
const resp = await postJson(`${API_ORIGIN}/breakroom/${encodeURIComponent(licenseKey)}/v1/chat/completions`, {
|
|
758
|
+
breakroom_test: true,
|
|
759
|
+
tool_calls: toolCalls
|
|
760
|
+
});
|
|
761
|
+
if (resp.status !== 200 || !resp.json.ok) {
|
|
762
|
+
console.log(`\x1b[31mTest failed: ${resp.json?.error || 'Unknown'}\x1b[0m\n`);
|
|
763
|
+
return;
|
|
764
|
+
}
|
|
765
|
+
|
|
766
|
+
const ix = resp.json.intervention;
|
|
767
|
+
console.log(` Would intervene: ${ix.would_intervene ? '\x1b[32mYES\x1b[0m' : '\x1b[31mNO\x1b[0m'}`);
|
|
768
|
+
console.log(` Reason: ${ix.reason}`);
|
|
769
|
+
if (ix.intervention_type) console.log(` Intervention type: ${ix.intervention_type}`);
|
|
770
|
+
if (ix.message) console.log(` CBT message: "${ix.message}"`);
|
|
771
|
+
console.log(`\n Session stats:\n` +
|
|
772
|
+
` Tool calls: ${ix.session_stats.total_tool_calls}\n` +
|
|
773
|
+
` Unique tools: ${ix.session_stats.unique_tools}\n` +
|
|
774
|
+
` Tokens saved: ${ix.session_stats.tokens_saved.toLocaleString()}`);
|
|
775
|
+
console.log();
|
|
776
|
+
} catch (err) {
|
|
777
|
+
console.log(`\x1b[31mError: ${err.message}\x1b[0m\n`);
|
|
778
|
+
}
|
|
779
|
+
}
|
|
780
|
+
|
|
781
|
+
async function actionAnalytics() {
|
|
782
|
+
console.log();
|
|
783
|
+
|
|
784
|
+
const configured = scanExistingConfig();
|
|
785
|
+
if (!configured.length) {
|
|
786
|
+
console.log('No Break Room proxy configured. Use option 1 first.\n');
|
|
787
|
+
return;
|
|
788
|
+
}
|
|
789
|
+
|
|
790
|
+
const licenseKey = extractLicenseKey(configured);
|
|
791
|
+
if (!licenseKey) {
|
|
792
|
+
console.log('Could not extract license key from config.\n');
|
|
793
|
+
return;
|
|
794
|
+
}
|
|
795
|
+
|
|
796
|
+
console.log('Fetching intervention analytics...\n');
|
|
797
|
+
|
|
798
|
+
try {
|
|
799
|
+
const resp = await requestJson(`${API_ORIGIN}/breakroom/${encodeURIComponent(licenseKey)}/v1/analytics`);
|
|
800
|
+
if (resp.status !== 200 || !resp.json.ok) {
|
|
801
|
+
console.log(`\x1b[31mFailed: ${resp.json?.error || 'Unknown'}\x1b[0m\n`);
|
|
802
|
+
return;
|
|
803
|
+
}
|
|
804
|
+
|
|
805
|
+
const a = resp.json.analytics;
|
|
806
|
+
console.log(` Total calls analyzed: ${a.total_calls}`);
|
|
807
|
+
console.log(` Interventions fired: \x1b[33m${a.total_interventions}\x1b[0m`);
|
|
808
|
+
console.log(` Total tokens saved: ${a.tokens_saved.toLocaleString()}`);
|
|
809
|
+
console.log(` Total cost saved: \x1b[32m$${a.cost_saved.toFixed(2)}\x1b[0m`);
|
|
810
|
+
|
|
811
|
+
const providers = Object.keys(a.by_provider);
|
|
812
|
+
if (providers.length) {
|
|
813
|
+
console.log(`\n By provider:\n`);
|
|
814
|
+
for (const p of providers) {
|
|
815
|
+
const d = a.by_provider[p];
|
|
816
|
+
console.log(` ${p}:`);
|
|
817
|
+
console.log(` Calls: ${d.calls}`);
|
|
818
|
+
console.log(` Interventions: ${d.interventions}`);
|
|
819
|
+
console.log(` Tokens saved: ${d.tokens_saved.toLocaleString()}`);
|
|
820
|
+
console.log(` Cost saved: \x1b[32m$${d.cost_saved.toFixed(2)}\x1b[0m`);
|
|
821
|
+
}
|
|
822
|
+
}
|
|
823
|
+
console.log();
|
|
824
|
+
} catch (err) {
|
|
825
|
+
console.log(`\x1b[31mError: ${err.message}\x1b[0m\n`);
|
|
826
|
+
}
|
|
827
|
+
}
|
|
828
|
+
|
|
693
829
|
// --- Menu ---
|
|
694
830
|
|
|
695
831
|
function showMenu() {
|
|
@@ -697,12 +833,14 @@ function showMenu() {
|
|
|
697
833
|
console.log(' 1) Configure a license');
|
|
698
834
|
console.log(' 2) Change license key');
|
|
699
835
|
console.log(' 3) Verify current license');
|
|
836
|
+
console.log(' a) Verify interventions');
|
|
700
837
|
console.log(' 4) Get a license');
|
|
701
838
|
console.log(' 5) Revert patches (restore backups)');
|
|
702
839
|
console.log(' 6) Check configuration status');
|
|
703
840
|
console.log(' 7) Recover lost license');
|
|
704
841
|
console.log(' 8) Scan for IDE/config/Docker files');
|
|
705
842
|
console.log(' 9) Rotate license key (2FA)');
|
|
843
|
+
console.log(' b) View analytics');
|
|
706
844
|
console.log(' 0) Exit\n');
|
|
707
845
|
}
|
|
708
846
|
|
|
@@ -725,6 +863,9 @@ async function main() {
|
|
|
725
863
|
case '3':
|
|
726
864
|
await actionVerify();
|
|
727
865
|
break;
|
|
866
|
+
case 'a':
|
|
867
|
+
await actionTestIntervention();
|
|
868
|
+
break;
|
|
728
869
|
case '4':
|
|
729
870
|
actionGetLicense();
|
|
730
871
|
break;
|
|
@@ -743,6 +884,9 @@ async function main() {
|
|
|
743
884
|
case '9':
|
|
744
885
|
await actionRotate();
|
|
745
886
|
break;
|
|
887
|
+
case 'b':
|
|
888
|
+
await actionAnalytics();
|
|
889
|
+
break;
|
|
746
890
|
case '0':
|
|
747
891
|
console.log('\nGoodbye.\n');
|
|
748
892
|
return;
|
|
@@ -753,7 +897,7 @@ async function main() {
|
|
|
753
897
|
console.error(`\n\x1b[31mError:\x1b[0m ${err.message}\n`);
|
|
754
898
|
}
|
|
755
899
|
|
|
756
|
-
if (
|
|
900
|
+
if (!['0', 'a', 'b'].includes(choice) && choice !== '__EOF__') {
|
|
757
901
|
if (await ask('Press Enter to return to the menu...') === '__EOF__') break;
|
|
758
902
|
}
|
|
759
903
|
}
|