@link-assistant/hive-mind 1.17.2 → 1.19.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/CHANGELOG.md +43 -0
- package/package.json +1 -1
- package/src/limits.lib.mjs +72 -25
- package/src/model-mapping.lib.mjs +4 -1
- package/src/model-validation.lib.mjs +6 -0
- package/src/queue-config.lib.mjs +104 -0
- package/src/solve.config.lib.mjs +1 -1
- package/src/telegram-solve-queue.lib.mjs +5 -33
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,48 @@
|
|
|
1
1
|
# @link-assistant/hive-mind
|
|
2
2
|
|
|
3
|
+
## 1.19.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 64687ce: Add support and documentation for free AI models:
|
|
8
|
+
- Added support for opencode/big-pickle, opencode/gpt-5-nano, opencode/kimi-k2.5-free, opencode/glm-4.7-free, opencode/minimax-m2.1-free
|
|
9
|
+
- Updated model mapping and validation to handle free models
|
|
10
|
+
- Created comprehensive documentation in FREE_MODELS.md
|
|
11
|
+
- Added tests for all free model support
|
|
12
|
+
- Created case study analysis for issue #1244
|
|
13
|
+
|
|
14
|
+
## 1.18.0
|
|
15
|
+
|
|
16
|
+
### Minor Changes
|
|
17
|
+
|
|
18
|
+
- 6b7f026: Add threshold markers to /limits command progress bars
|
|
19
|
+
|
|
20
|
+
This change implements visual threshold markers in the progress bars displayed by the /limits command. Users can now see:
|
|
21
|
+
- **Threshold position marker (│)**: Shows where queue behavior changes (e.g., blocking, one-at-a-time mode)
|
|
22
|
+
- **Warning emoji (⚠️)**: Appears when usage exceeds the threshold
|
|
23
|
+
|
|
24
|
+
Thresholds displayed:
|
|
25
|
+
- RAM: 65% (blocks new commands)
|
|
26
|
+
- CPU: 65% (blocks new commands)
|
|
27
|
+
- Disk: 90% (one-at-a-time mode)
|
|
28
|
+
- Claude 5-hour session: 65% (one-at-a-time mode)
|
|
29
|
+
- Claude weekly: 97% (one-at-a-time mode)
|
|
30
|
+
- GitHub API: 75% (blocks parallel claude commands)
|
|
31
|
+
|
|
32
|
+
Example output:
|
|
33
|
+
|
|
34
|
+
```
|
|
35
|
+
CPU
|
|
36
|
+
▓▓▓▓▓▓▓░░░░░░░░░░░░│░░░░░░░░░░ 25%
|
|
37
|
+
0.04/6 CPU cores used
|
|
38
|
+
|
|
39
|
+
Claude 5 hour session
|
|
40
|
+
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓│▓ 98% ⚠️
|
|
41
|
+
Resets in 2h 10m (Dec 6, 12:00pm UTC)
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Fixes #1242
|
|
45
|
+
|
|
3
46
|
## 1.17.2
|
|
4
47
|
|
|
5
48
|
### Patch Changes
|
package/package.json
CHANGED
package/src/limits.lib.mjs
CHANGED
|
@@ -18,6 +18,12 @@ dayjs.extend(utc);
|
|
|
18
18
|
// Import cache TTL configuration
|
|
19
19
|
import { cacheTtl } from './config.lib.mjs';
|
|
20
20
|
|
|
21
|
+
// Import centralized queue thresholds for progress bar visualization
|
|
22
|
+
// This ensures thresholds are consistent between queue logic and display formatting
|
|
23
|
+
// See: https://github.com/link-assistant/hive-mind/issues/1242
|
|
24
|
+
export { DISPLAY_THRESHOLDS } from './queue-config.lib.mjs';
|
|
25
|
+
import { DISPLAY_THRESHOLDS } from './queue-config.lib.mjs';
|
|
26
|
+
|
|
21
27
|
const execAsync = promisify(exec);
|
|
22
28
|
|
|
23
29
|
/**
|
|
@@ -626,13 +632,35 @@ export async function getClaudeUsageLimits(verbose = false, credentialsPath = DE
|
|
|
626
632
|
/**
|
|
627
633
|
* Generate a text-based progress bar for usage percentage
|
|
628
634
|
* @param {number} percentage - Usage percentage (0-100)
|
|
635
|
+
* @param {number|null} thresholdPercentage - Optional threshold position to show in the bar (0-100)
|
|
629
636
|
* @returns {string} Text-based progress bar
|
|
637
|
+
* @see https://github.com/link-assistant/hive-mind/issues/1242
|
|
630
638
|
*/
|
|
631
|
-
export function getProgressBar(percentage) {
|
|
639
|
+
export function getProgressBar(percentage, thresholdPercentage = null) {
|
|
632
640
|
const totalBlocks = 30;
|
|
633
641
|
const filledBlocks = Math.round((percentage / 100) * totalBlocks);
|
|
634
|
-
|
|
635
|
-
|
|
642
|
+
|
|
643
|
+
if (thresholdPercentage === null) {
|
|
644
|
+
// No threshold - original behavior
|
|
645
|
+
const emptyBlocks = totalBlocks - filledBlocks;
|
|
646
|
+
return '\u2593'.repeat(filledBlocks) + '\u2591'.repeat(emptyBlocks);
|
|
647
|
+
}
|
|
648
|
+
|
|
649
|
+
// With threshold marker
|
|
650
|
+
const thresholdPos = Math.round((thresholdPercentage / 100) * totalBlocks);
|
|
651
|
+
let bar = '';
|
|
652
|
+
|
|
653
|
+
for (let i = 0; i < totalBlocks; i++) {
|
|
654
|
+
if (i === thresholdPos) {
|
|
655
|
+
bar += '│'; // Threshold marker (U+2502 Box Drawings Light Vertical)
|
|
656
|
+
} else if (i < filledBlocks) {
|
|
657
|
+
bar += '▓'; // Filled (U+2593)
|
|
658
|
+
} else {
|
|
659
|
+
bar += '░'; // Empty (U+2591)
|
|
660
|
+
}
|
|
661
|
+
}
|
|
662
|
+
|
|
663
|
+
return bar;
|
|
636
664
|
}
|
|
637
665
|
|
|
638
666
|
/**
|
|
@@ -664,12 +692,15 @@ export function calculateTimePassedPercentage(resetsAt, periodHours) {
|
|
|
664
692
|
|
|
665
693
|
/**
|
|
666
694
|
* Format Claude usage data into a Telegram-friendly message
|
|
695
|
+
* Shows threshold markers in progress bars to indicate where queue behavior changes.
|
|
696
|
+
*
|
|
667
697
|
* @param {Object} usage - The usage object from getClaudeUsageLimits
|
|
668
698
|
* @param {Object} diskSpace - Optional disk space info from getDiskSpaceInfo
|
|
669
699
|
* @param {Object} githubRateLimit - Optional GitHub rate limit info from getGitHubRateLimits
|
|
670
700
|
* @param {Object} cpuLoad - Optional CPU load info from getCpuLoadInfo
|
|
671
701
|
* @param {Object} memory - Optional memory info from getMemoryInfo
|
|
672
702
|
* @returns {string} Formatted message
|
|
703
|
+
* @see https://github.com/link-assistant/hive-mind/issues/1242
|
|
673
704
|
*/
|
|
674
705
|
export function formatUsageMessage(usage, diskSpace = null, githubRateLimit = null, cpuLoad = null, memory = null) {
|
|
675
706
|
// Use code block for monospace font to align progress bars properly
|
|
@@ -679,38 +710,46 @@ export function formatUsageMessage(usage, diskSpace = null, githubRateLimit = nu
|
|
|
679
710
|
message += `Current time: ${formatCurrentTime()}\n\n`;
|
|
680
711
|
|
|
681
712
|
// CPU load section (if provided)
|
|
713
|
+
// Threshold: Blocks new commands when usage >= 65%
|
|
682
714
|
if (cpuLoad) {
|
|
683
715
|
message += 'CPU\n';
|
|
684
|
-
const usedBar = getProgressBar(cpuLoad.usagePercentage);
|
|
685
|
-
|
|
716
|
+
const usedBar = getProgressBar(cpuLoad.usagePercentage, DISPLAY_THRESHOLDS.CPU);
|
|
717
|
+
const warning = cpuLoad.usagePercentage >= DISPLAY_THRESHOLDS.CPU ? ' ⚠️' : '';
|
|
718
|
+
message += `${usedBar} ${cpuLoad.usagePercentage}%${warning}\n`;
|
|
686
719
|
// Show cores used based on 5m load average (e.g., "0.04/6 CPU cores used" or "3/6 CPU cores used")
|
|
687
720
|
// Use parseFloat to strip unnecessary trailing zeros (3.00 -> 3, 0.10 -> 0.1, 0.04 -> 0.04)
|
|
688
721
|
message += `${parseFloat(cpuLoad.loadAvg5.toFixed(2))}/${cpuLoad.cpuCount} CPU cores used\n\n`;
|
|
689
722
|
}
|
|
690
723
|
|
|
691
724
|
// Memory section (if provided)
|
|
725
|
+
// Threshold: Blocks new commands when usage >= 65%
|
|
692
726
|
if (memory) {
|
|
693
727
|
message += 'RAM\n';
|
|
694
|
-
const usedBar = getProgressBar(memory.usedPercentage);
|
|
695
|
-
|
|
728
|
+
const usedBar = getProgressBar(memory.usedPercentage, DISPLAY_THRESHOLDS.RAM);
|
|
729
|
+
const warning = memory.usedPercentage >= DISPLAY_THRESHOLDS.RAM ? ' ⚠️' : '';
|
|
730
|
+
message += `${usedBar} ${memory.usedPercentage}%${warning}\n`;
|
|
696
731
|
message += `${formatBytesRange(memory.usedBytes, memory.totalBytes)}\n\n`;
|
|
697
732
|
}
|
|
698
733
|
|
|
699
734
|
// Disk space section (if provided)
|
|
735
|
+
// Threshold: One-at-a-time mode when usage >= 90%
|
|
700
736
|
if (diskSpace) {
|
|
701
737
|
message += 'Disk space\n';
|
|
702
|
-
// Show used percentage with progress bar
|
|
703
|
-
const usedBar = getProgressBar(diskSpace.usedPercentage);
|
|
704
|
-
|
|
738
|
+
// Show used percentage with progress bar and threshold marker
|
|
739
|
+
const usedBar = getProgressBar(diskSpace.usedPercentage, DISPLAY_THRESHOLDS.DISK);
|
|
740
|
+
const warning = diskSpace.usedPercentage >= DISPLAY_THRESHOLDS.DISK ? ' ⚠️' : '';
|
|
741
|
+
message += `${usedBar} ${diskSpace.usedPercentage}%${warning}\n`;
|
|
705
742
|
message += `${formatBytesRange(diskSpace.usedBytes, diskSpace.totalBytes)}\n\n`;
|
|
706
743
|
}
|
|
707
744
|
|
|
708
745
|
// GitHub API rate limits section (if provided)
|
|
746
|
+
// Threshold: Blocks parallel claude commands when >= 75%
|
|
709
747
|
if (githubRateLimit) {
|
|
710
748
|
message += 'GitHub API\n';
|
|
711
|
-
// Show used percentage with progress bar
|
|
712
|
-
const usedBar = getProgressBar(githubRateLimit.usedPercentage);
|
|
713
|
-
|
|
749
|
+
// Show used percentage with progress bar and threshold marker
|
|
750
|
+
const usedBar = getProgressBar(githubRateLimit.usedPercentage, DISPLAY_THRESHOLDS.GITHUB_API);
|
|
751
|
+
const warning = githubRateLimit.usedPercentage >= DISPLAY_THRESHOLDS.GITHUB_API ? ' ⚠️' : '';
|
|
752
|
+
message += `${usedBar} ${githubRateLimit.usedPercentage}%${warning}\n`;
|
|
714
753
|
message += `${githubRateLimit.used}/${githubRateLimit.limit} requests used\n`;
|
|
715
754
|
if (githubRateLimit.relativeReset) {
|
|
716
755
|
message += `Resets in ${githubRateLimit.relativeReset} (${githubRateLimit.resetTime})\n`;
|
|
@@ -721,21 +760,23 @@ export function formatUsageMessage(usage, diskSpace = null, githubRateLimit = nu
|
|
|
721
760
|
}
|
|
722
761
|
|
|
723
762
|
// Claude 5 hour session (five_hour)
|
|
763
|
+
// Threshold: One-at-a-time mode when usage >= 65%
|
|
724
764
|
message += 'Claude 5 hour session\n';
|
|
725
765
|
if (usage.currentSession.percentage !== null) {
|
|
726
|
-
// Add time passed progress bar first
|
|
766
|
+
// Add time passed progress bar first (no threshold marker for time)
|
|
727
767
|
const timePassed = calculateTimePassedPercentage(usage.currentSession.resetsAt, 5);
|
|
728
768
|
if (timePassed !== null) {
|
|
729
769
|
const timeBar = getProgressBar(timePassed);
|
|
730
770
|
message += `${timeBar} ${timePassed}% passed\n`;
|
|
731
771
|
}
|
|
732
772
|
|
|
733
|
-
// Add usage progress bar second
|
|
773
|
+
// Add usage progress bar second with threshold marker
|
|
734
774
|
// Use Math.floor so 100% only appears when usage is exactly 100%
|
|
735
775
|
// See: https://github.com/link-assistant/hive-mind/issues/1133
|
|
736
776
|
const pct = Math.floor(usage.currentSession.percentage);
|
|
737
|
-
const bar = getProgressBar(pct);
|
|
738
|
-
|
|
777
|
+
const bar = getProgressBar(pct, DISPLAY_THRESHOLDS.CLAUDE_5_HOUR_SESSION);
|
|
778
|
+
const warning = pct >= DISPLAY_THRESHOLDS.CLAUDE_5_HOUR_SESSION ? ' ⚠️' : '';
|
|
779
|
+
message += `${bar} ${pct}%${warning}\n`;
|
|
739
780
|
|
|
740
781
|
if (usage.currentSession.resetTime) {
|
|
741
782
|
const relativeTime = formatRelativeTime(usage.currentSession.resetsAt);
|
|
@@ -751,21 +792,23 @@ export function formatUsageMessage(usage, diskSpace = null, githubRateLimit = nu
|
|
|
751
792
|
message += '\n';
|
|
752
793
|
|
|
753
794
|
// Current week (all models / seven_day)
|
|
795
|
+
// Threshold: One-at-a-time mode when usage >= 97%
|
|
754
796
|
message += 'Current week (all models)\n';
|
|
755
797
|
if (usage.allModels.percentage !== null) {
|
|
756
|
-
// Add time passed progress bar first (
|
|
798
|
+
// Add time passed progress bar first (no threshold marker for time)
|
|
757
799
|
const timePassed = calculateTimePassedPercentage(usage.allModels.resetsAt, 168);
|
|
758
800
|
if (timePassed !== null) {
|
|
759
801
|
const timeBar = getProgressBar(timePassed);
|
|
760
802
|
message += `${timeBar} ${timePassed}% passed\n`;
|
|
761
803
|
}
|
|
762
804
|
|
|
763
|
-
// Add usage progress bar second
|
|
805
|
+
// Add usage progress bar second with threshold marker
|
|
764
806
|
// Use Math.floor so 100% only appears when usage is exactly 100%
|
|
765
807
|
// See: https://github.com/link-assistant/hive-mind/issues/1133
|
|
766
808
|
const pct = Math.floor(usage.allModels.percentage);
|
|
767
|
-
const bar = getProgressBar(pct);
|
|
768
|
-
|
|
809
|
+
const bar = getProgressBar(pct, DISPLAY_THRESHOLDS.CLAUDE_WEEKLY);
|
|
810
|
+
const warning = pct >= DISPLAY_THRESHOLDS.CLAUDE_WEEKLY ? ' ⚠️' : '';
|
|
811
|
+
message += `${bar} ${pct}%${warning}\n`;
|
|
769
812
|
|
|
770
813
|
if (usage.allModels.resetTime) {
|
|
771
814
|
const relativeTime = formatRelativeTime(usage.allModels.resetsAt);
|
|
@@ -781,21 +824,23 @@ export function formatUsageMessage(usage, diskSpace = null, githubRateLimit = nu
|
|
|
781
824
|
message += '\n';
|
|
782
825
|
|
|
783
826
|
// Current week (Sonnet only / seven_day_sonnet)
|
|
827
|
+
// Threshold: One-at-a-time mode when usage >= 97% (same as all models)
|
|
784
828
|
message += 'Current week (Sonnet only)\n';
|
|
785
829
|
if (usage.sonnetOnly.percentage !== null) {
|
|
786
|
-
// Add time passed progress bar first (
|
|
830
|
+
// Add time passed progress bar first (no threshold marker for time)
|
|
787
831
|
const timePassed = calculateTimePassedPercentage(usage.sonnetOnly.resetsAt, 168);
|
|
788
832
|
if (timePassed !== null) {
|
|
789
833
|
const timeBar = getProgressBar(timePassed);
|
|
790
834
|
message += `${timeBar} ${timePassed}% passed\n`;
|
|
791
835
|
}
|
|
792
836
|
|
|
793
|
-
// Add usage progress bar second
|
|
837
|
+
// Add usage progress bar second with threshold marker
|
|
794
838
|
// Use Math.floor so 100% only appears when usage is exactly 100%
|
|
795
839
|
// See: https://github.com/link-assistant/hive-mind/issues/1133
|
|
796
840
|
const pct = Math.floor(usage.sonnetOnly.percentage);
|
|
797
|
-
const bar = getProgressBar(pct);
|
|
798
|
-
|
|
841
|
+
const bar = getProgressBar(pct, DISPLAY_THRESHOLDS.CLAUDE_WEEKLY);
|
|
842
|
+
const warning = pct >= DISPLAY_THRESHOLDS.CLAUDE_WEEKLY ? ' ⚠️' : '';
|
|
843
|
+
message += `${bar} ${pct}%${warning}\n`;
|
|
799
844
|
|
|
800
845
|
if (usage.sonnetOnly.resetTime) {
|
|
801
846
|
const relativeTime = formatRelativeTime(usage.sonnetOnly.resetsAt);
|
|
@@ -973,6 +1018,8 @@ export default {
|
|
|
973
1018
|
getProgressBar,
|
|
974
1019
|
calculateTimePassedPercentage,
|
|
975
1020
|
formatUsageMessage,
|
|
1021
|
+
// Threshold constants for progress bar visualization
|
|
1022
|
+
DISPLAY_THRESHOLDS,
|
|
976
1023
|
// Cache management
|
|
977
1024
|
CACHE_TTL,
|
|
978
1025
|
getLimitCache,
|
|
@@ -31,7 +31,10 @@ export const agentModels = {
|
|
|
31
31
|
'grok-code': 'opencode/grok-code',
|
|
32
32
|
'grok-code-fast-1': 'opencode/grok-code',
|
|
33
33
|
'big-pickle': 'opencode/big-pickle',
|
|
34
|
-
'gpt-5-nano': '
|
|
34
|
+
'gpt-5-nano': 'opencode/gpt-5-nano',
|
|
35
|
+
'glm-4.7-free': 'opencode/glm-4.7-free',
|
|
36
|
+
'minimax-m2.1-free': 'opencode/minimax-m2.1-free',
|
|
37
|
+
'kimi-k2.5-free': 'opencode/kimi-k2.5-free',
|
|
35
38
|
sonnet: 'anthropic/claude-3-5-sonnet',
|
|
36
39
|
haiku: 'anthropic/claude-3-5-haiku',
|
|
37
40
|
opus: 'anthropic/claude-3-opus',
|
|
@@ -99,6 +99,9 @@ export const AGENT_MODELS = {
|
|
|
99
99
|
'grok-code-fast-1': 'opencode/grok-code',
|
|
100
100
|
'big-pickle': 'opencode/big-pickle',
|
|
101
101
|
'gpt-5-nano': 'opencode/gpt-5-nano',
|
|
102
|
+
'glm-4.7-free': 'opencode/glm-4.7-free',
|
|
103
|
+
'minimax-m2.1-free': 'opencode/minimax-m2.1-free',
|
|
104
|
+
'kimi-k2.5-free': 'opencode/kimi-k2.5-free',
|
|
102
105
|
// Premium models (requires OpenCode Zen subscription)
|
|
103
106
|
sonnet: 'anthropic/claude-3-5-sonnet',
|
|
104
107
|
haiku: 'anthropic/claude-3-5-haiku',
|
|
@@ -108,6 +111,9 @@ export const AGENT_MODELS = {
|
|
|
108
111
|
'opencode/grok-code': 'opencode/grok-code',
|
|
109
112
|
'opencode/big-pickle': 'opencode/big-pickle',
|
|
110
113
|
'opencode/gpt-5-nano': 'opencode/gpt-5-nano',
|
|
114
|
+
'opencode/glm-4.7-free': 'opencode/glm-4.7-free',
|
|
115
|
+
'opencode/minimax-m2.1-free': 'opencode/minimax-m2.1-free',
|
|
116
|
+
'opencode/kimi-k2.5-free': 'opencode/kimi-k2.5-free',
|
|
111
117
|
'anthropic/claude-3-5-sonnet': 'anthropic/claude-3-5-sonnet',
|
|
112
118
|
'anthropic/claude-3-5-haiku': 'anthropic/claude-3-5-haiku',
|
|
113
119
|
'anthropic/claude-3-opus': 'anthropic/claude-3-opus',
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Queue Configuration Module
|
|
5
|
+
*
|
|
6
|
+
* Centralized configuration for queue throttling and resource thresholds.
|
|
7
|
+
* This module is used by both telegram-solve-queue.lib.mjs (queue logic)
|
|
8
|
+
* and limits.lib.mjs (display formatting).
|
|
9
|
+
*
|
|
10
|
+
* @see https://github.com/link-assistant/hive-mind/issues/1242
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
// Use use-m to dynamically import modules
|
|
14
|
+
if (typeof globalThis.use === 'undefined') {
|
|
15
|
+
try {
|
|
16
|
+
globalThis.use = (await eval(await (await fetch('https://unpkg.com/use-m/use.js')).text())).use;
|
|
17
|
+
} catch (error) {
|
|
18
|
+
console.error('❌ Fatal error: Failed to load dependencies for queue configuration');
|
|
19
|
+
console.error(` ${error.message}`);
|
|
20
|
+
console.error(' This might be due to network issues or missing dependencies.');
|
|
21
|
+
console.error(' Please check your internet connection and try again.');
|
|
22
|
+
process.exit(1);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const getenv = await use('getenv');
|
|
27
|
+
|
|
28
|
+
// Helper function to safely parse floats with fallback
|
|
29
|
+
const parseFloatWithDefault = (envVar, defaultValue) => {
|
|
30
|
+
const value = getenv(envVar, defaultValue.toString());
|
|
31
|
+
const parsed = parseFloat(value);
|
|
32
|
+
return isNaN(parsed) ? defaultValue : parsed;
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
// Helper function to safely parse integers with fallback
|
|
36
|
+
const parseIntWithDefault = (envVar, defaultValue) => {
|
|
37
|
+
const value = getenv(envVar, defaultValue.toString());
|
|
38
|
+
const parsed = parseInt(value);
|
|
39
|
+
return isNaN(parsed) ? defaultValue : parsed;
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Configuration constants for queue throttling
|
|
44
|
+
* All thresholds use ratios (0.0 - 1.0) representing usage percentage
|
|
45
|
+
*
|
|
46
|
+
* IMPORTANT: Running claude processes is NOT a blocking limit by itself.
|
|
47
|
+
* Commands can run in parallel as long as actual limits (CPU, API, etc.) are not exceeded.
|
|
48
|
+
* See: https://github.com/link-assistant/hive-mind/issues/1078
|
|
49
|
+
*/
|
|
50
|
+
export const QUEUE_CONFIG = {
|
|
51
|
+
// Resource thresholds (usage ratios: 0.0 - 1.0)
|
|
52
|
+
// All thresholds use >= comparison (inclusive)
|
|
53
|
+
RAM_THRESHOLD: parseFloatWithDefault('HIVE_MIND_RAM_THRESHOLD', 0.65), // Enqueue if RAM usage >= 65%
|
|
54
|
+
// CPU threshold uses 5-minute load average, not instantaneous CPU usage
|
|
55
|
+
CPU_THRESHOLD: parseFloatWithDefault('HIVE_MIND_CPU_THRESHOLD', 0.65), // Enqueue if 5-minute load average >= 65% of CPU count
|
|
56
|
+
DISK_THRESHOLD: parseFloatWithDefault('HIVE_MIND_DISK_THRESHOLD', 0.9), // One-at-a-time if disk usage >= 90%, tuned for VM with 100 GB drive
|
|
57
|
+
|
|
58
|
+
// API limit thresholds (usage ratios: 0.0 - 1.0)
|
|
59
|
+
// All thresholds use >= comparison (inclusive)
|
|
60
|
+
// Fine-tuned for Claude MAX $200 subscription
|
|
61
|
+
CLAUDE_5_HOUR_SESSION_THRESHOLD: parseFloatWithDefault('HIVE_MIND_CLAUDE_5_HOUR_SESSION_THRESHOLD', 0.65), // One-at-a-time if 5-hour limit >= 65%
|
|
62
|
+
CLAUDE_WEEKLY_THRESHOLD: parseFloatWithDefault('HIVE_MIND_CLAUDE_WEEKLY_THRESHOLD', 0.97), // One-at-a-time if weekly limit >= 97%
|
|
63
|
+
GITHUB_API_THRESHOLD: parseFloatWithDefault('HIVE_MIND_GITHUB_API_THRESHOLD', 0.75), // Enqueue if GitHub >= 75% with parallel claude
|
|
64
|
+
|
|
65
|
+
// Timing
|
|
66
|
+
// MIN_START_INTERVAL_MS: Time to allow solve command to start actual claude process
|
|
67
|
+
// This ensures that when API limits are checked, the running process is counted
|
|
68
|
+
MIN_START_INTERVAL_MS: parseIntWithDefault('HIVE_MIND_MIN_START_INTERVAL_MS', 60000), // 1 minute between starts
|
|
69
|
+
CONSUMER_POLL_INTERVAL_MS: parseIntWithDefault('HIVE_MIND_CONSUMER_POLL_INTERVAL_MS', 60000), // 1 minute between queue checks
|
|
70
|
+
MESSAGE_UPDATE_INTERVAL_MS: parseIntWithDefault('HIVE_MIND_MESSAGE_UPDATE_INTERVAL_MS', 60000), // 1 minute between status message updates
|
|
71
|
+
|
|
72
|
+
// Process detection
|
|
73
|
+
CLAUDE_PROCESS_NAMES: ['claude'], // Process names to detect
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Convert threshold ratio to percentage for display
|
|
78
|
+
* @param {number} ratio - Threshold ratio (0.0 - 1.0)
|
|
79
|
+
* @returns {number} Percentage value (0 - 100)
|
|
80
|
+
*/
|
|
81
|
+
export function thresholdToPercent(ratio) {
|
|
82
|
+
return Math.round(ratio * 100);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Display threshold constants for progress bar visualization
|
|
87
|
+
* These are derived from QUEUE_CONFIG and converted to percentages (0-100)
|
|
88
|
+
*
|
|
89
|
+
* @see https://github.com/link-assistant/hive-mind/issues/1242
|
|
90
|
+
*/
|
|
91
|
+
export const DISPLAY_THRESHOLDS = {
|
|
92
|
+
RAM: thresholdToPercent(QUEUE_CONFIG.RAM_THRESHOLD), // Blocks at 65%
|
|
93
|
+
CPU: thresholdToPercent(QUEUE_CONFIG.CPU_THRESHOLD), // Blocks at 65%
|
|
94
|
+
DISK: thresholdToPercent(QUEUE_CONFIG.DISK_THRESHOLD), // One-at-a-time at 90%
|
|
95
|
+
CLAUDE_5_HOUR_SESSION: thresholdToPercent(QUEUE_CONFIG.CLAUDE_5_HOUR_SESSION_THRESHOLD), // One-at-a-time at 65%
|
|
96
|
+
CLAUDE_WEEKLY: thresholdToPercent(QUEUE_CONFIG.CLAUDE_WEEKLY_THRESHOLD), // One-at-a-time at 97%
|
|
97
|
+
GITHUB_API: thresholdToPercent(QUEUE_CONFIG.GITHUB_API_THRESHOLD), // Blocks parallel claude at 75%
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
export default {
|
|
101
|
+
QUEUE_CONFIG,
|
|
102
|
+
DISPLAY_THRESHOLDS,
|
|
103
|
+
thresholdToPercent,
|
|
104
|
+
};
|
package/src/solve.config.lib.mjs
CHANGED
|
@@ -390,7 +390,7 @@ export const createYargsConfig = yargsInstance => {
|
|
|
390
390
|
config = config
|
|
391
391
|
.option('model', {
|
|
392
392
|
type: 'string',
|
|
393
|
-
description: 'Model to use (for claude: opus, sonnet, haiku, haiku-3-5, haiku-3; for opencode: grok, gpt4o; for codex: gpt5, gpt5-codex, o3; for agent: grok, grok-code, big-pickle)',
|
|
393
|
+
description: 'Model to use (for claude: opus, sonnet, haiku, haiku-3-5, haiku-3; for opencode: grok, gpt4o; for codex: gpt5, gpt5-codex, o3; for agent: grok, grok-code, big-pickle, gpt-5-nano, glm-4.7-free, minimax-m2.1-free, kimi-k2.5-free)',
|
|
394
394
|
alias: 'm',
|
|
395
395
|
default: currentParsedArgs => {
|
|
396
396
|
// Dynamic default based on tool selection
|
|
@@ -23,39 +23,11 @@ const execAsync = promisify(exec);
|
|
|
23
23
|
// Import centralized limits and caching
|
|
24
24
|
import { getCachedClaudeLimits, getCachedGitHubLimits, getCachedMemoryInfo, getCachedCpuInfo, getCachedDiskInfo, getLimitCache } from './limits.lib.mjs';
|
|
25
25
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
* Commands can run in parallel as long as actual limits (CPU, API, etc.) are not exceeded.
|
|
32
|
-
* See: https://github.com/link-assistant/hive-mind/issues/1078
|
|
33
|
-
*/
|
|
34
|
-
export const QUEUE_CONFIG = {
|
|
35
|
-
// Resource thresholds (usage ratios: 0.0 - 1.0)
|
|
36
|
-
// All thresholds use >= comparison (inclusive)
|
|
37
|
-
RAM_THRESHOLD: 0.65, // Enqueue if RAM usage >= 65%
|
|
38
|
-
// CPU threshold uses 5-minute load average, not instantaneous CPU usage
|
|
39
|
-
CPU_THRESHOLD: 0.65, // Enqueue if 5-minute load average >= 65% of CPU count
|
|
40
|
-
DISK_THRESHOLD: 0.9, // One-at-a-time if disk usage >= 90%, tuned for VM with 100 GB drive
|
|
41
|
-
|
|
42
|
-
// API limit thresholds (usage ratios: 0.0 - 1.0)
|
|
43
|
-
// All thresholds use >= comparison (inclusive)
|
|
44
|
-
// Fine-tuned for Claude MAX $200 subscription
|
|
45
|
-
CLAUDE_5_HOUR_SESSION_THRESHOLD: 0.65, // One-at-a-time if 5-hour limit >= 65%
|
|
46
|
-
CLAUDE_WEEKLY_THRESHOLD: 0.97, // One-at-a-time if weekly limit >= 97%
|
|
47
|
-
GITHUB_API_THRESHOLD: 0.75, // Enqueue if GitHub >= 75% with parallel claude
|
|
48
|
-
|
|
49
|
-
// Timing
|
|
50
|
-
// MIN_START_INTERVAL_MS: Time to allow solve command to start actual claude process
|
|
51
|
-
// This ensures that when API limits are checked, the running process is counted
|
|
52
|
-
MIN_START_INTERVAL_MS: 60000, // 1 minutes between starts
|
|
53
|
-
CONSUMER_POLL_INTERVAL_MS: 60000, // 1 minute between queue checks
|
|
54
|
-
MESSAGE_UPDATE_INTERVAL_MS: 60000, // 1 minute between status message updates
|
|
55
|
-
|
|
56
|
-
// Process detection
|
|
57
|
-
CLAUDE_PROCESS_NAMES: ['claude'], // Process names to detect
|
|
58
|
-
};
|
|
26
|
+
// Import centralized queue configuration
|
|
27
|
+
// This ensures thresholds are consistent between queue logic and display formatting
|
|
28
|
+
// See: https://github.com/link-assistant/hive-mind/issues/1242
|
|
29
|
+
export { QUEUE_CONFIG } from './queue-config.lib.mjs';
|
|
30
|
+
import { QUEUE_CONFIG } from './queue-config.lib.mjs';
|
|
59
31
|
|
|
60
32
|
/**
|
|
61
33
|
* Status enum for queue items
|