@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 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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@link-assistant/hive-mind",
3
- "version": "1.17.2",
3
+ "version": "1.19.0",
4
4
  "description": "AI-powered issue solver and hive mind for collaborative problem solving",
5
5
  "main": "src/hive.mjs",
6
6
  "type": "module",
@@ -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
- const emptyBlocks = totalBlocks - filledBlocks;
635
- return '\u2593'.repeat(filledBlocks) + '\u2591'.repeat(emptyBlocks);
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
- message += `${usedBar} ${cpuLoad.usagePercentage}% used\n`;
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
- message += `${usedBar} ${memory.usedPercentage}% used\n`;
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
- message += `${usedBar} ${diskSpace.usedPercentage}% used\n`;
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
- message += `${usedBar} ${githubRateLimit.usedPercentage}% used\n`;
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
- message += `${bar} ${pct}% used\n`;
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 (168 hours = 7 days)
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
- message += `${bar} ${pct}% used\n`;
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 (168 hours = 7 days)
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
- message += `${bar} ${pct}% used\n`;
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': 'openai/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
+ };
@@ -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
- * Configuration constants for queue throttling
28
- * All thresholds use ratios (0.0 - 1.0) representing usage percentage
29
- *
30
- * IMPORTANT: Running claude processes is NOT a blocking limit by itself.
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