@link-assistant/hive-mind 1.54.0 → 1.54.2

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,33 @@
1
1
  # @link-assistant/hive-mind
2
2
 
3
+ ## 1.54.2
4
+
5
+ ### Patch Changes
6
+
7
+ - 9d4e473: Cap `/limits` CPU cores display at available CPU count when load average demand exceeds capacity.
8
+ - ea0b9f5: Use Anthropic's native Claude Code installer in Docker images so the CLI binary is installed even when Bun blocks dependency postinstall scripts.
9
+
10
+ ## 1.54.1
11
+
12
+ ### Patch Changes
13
+
14
+ - 5f70953: fix(solve): post tool-generated PR comments again after v1.53.1 regression
15
+
16
+ `postTrackedComment()` in `src/tool-comments.lib.mjs` (added in #1626) was
17
+ passing the comment body to `gh api --input -` via `$({ input: payload })`,
18
+ but command-stream's option is `stdin`, not `input`. The misnamed key was
19
+ silently ignored, so `gh` read from the parent's stdin, sent an empty POST
20
+ body, and GitHub's edge returned `HTTP 400 "Whoa there!"`. Every tool-posted
21
+ comment — `AI Work Session Started`, log-upload link, `Ready to merge`,
22
+ `Auto-merged`, billing-limit notice, usage-limit notice — failed from this
23
+ one call path starting with v1.53.1.
24
+
25
+ Fix: use the documented `stdin` option so the JSON payload actually reaches
26
+ the child's stdin. The regression test pins the option name so a future
27
+ rename can't silently recur.
28
+
29
+ Fixes #1631.
30
+
3
31
  ## 1.54.0
4
32
 
5
33
  ### Minor Changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@link-assistant/hive-mind",
3
- "version": "1.54.0",
3
+ "version": "1.54.2",
4
4
  "description": "AI-powered issue solver and hive mind for collaborative problem solving",
5
5
  "main": "src/hive.mjs",
6
6
  "type": "module",
@@ -13,7 +13,7 @@
13
13
  "hive-telegram-bot": "./src/telegram-bot.mjs"
14
14
  },
15
15
  "scripts": {
16
- "test": "node tests/solve-queue.test.mjs && node tests/limits-display.test.mjs && node tests/test-usage-limit.mjs && node tests/test-issue-1616-pr-issue-link-preservation.mjs && node tests/test-telegram-message-filters.mjs && node tests/test-telegram-bot-command-aliases.mjs && node tests/test-solve-queue-command.mjs && node tests/test-queue-display-1267.mjs && node tests/test-telegram-bot-launcher.mjs",
16
+ "test": "node tests/solve-queue.test.mjs && node tests/limits-display.test.mjs && node tests/test-usage-limit.mjs && node tests/test-claude-code-install-method.mjs && node tests/test-issue-1616-pr-issue-link-preservation.mjs && node tests/test-telegram-message-filters.mjs && node tests/test-telegram-bot-command-aliases.mjs && node tests/test-solve-queue-command.mjs && node tests/test-queue-display-1267.mjs && node tests/test-telegram-bot-launcher.mjs",
17
17
  "test:queue": "node tests/solve-queue.test.mjs",
18
18
  "test:limits-display": "node tests/limits-display.test.mjs",
19
19
  "test:usage-limit": "node tests/test-usage-limit.mjs",
@@ -297,6 +297,15 @@ function formatBytesRange(usedBytes, totalBytes) {
297
297
  return `${usedValue.toFixed(decimals)}/${totalValue.toFixed(decimals)} ${sizes[i]} used`;
298
298
  }
299
299
 
300
+ function formatRoundedNumber(value, decimals = 2) {
301
+ return parseFloat(value.toFixed(decimals));
302
+ }
303
+
304
+ function getDisplayCpuCoresUsed(loadAvg5, cpuCount) {
305
+ const boundedLoad = Math.min(Math.max(loadAvg5, 0), cpuCount);
306
+ return formatRoundedNumber(boundedLoad);
307
+ }
308
+
300
309
  /**
301
310
  * Get GitHub API rate limits by calling gh api rate_limit
302
311
  * Returns rate limit info for core, search, graphql, and other resources
@@ -428,6 +437,7 @@ export async function getCpuLoadInfo(verbose = false) {
428
437
  // Load average of 1.0 per CPU = 100% utilization
429
438
  // Using 5m average for consistency with solve queue (see issue #1137)
430
439
  const usagePercentage = Math.min(100, Math.round((loadAvg5 / cpuCount) * 100));
440
+ const usedCpuCores = getDisplayCpuCoresUsed(loadAvg5, cpuCount);
431
441
 
432
442
  if (verbose) {
433
443
  console.log(`[VERBOSE] /limits CPU load: ${loadAvg1.toFixed(2)} (1m), ${loadAvg5.toFixed(2)} (5m), ${loadAvg15.toFixed(2)} (15m), ${cpuCount} CPUs, ${usagePercentage}% used`);
@@ -441,6 +451,7 @@ export async function getCpuLoadInfo(verbose = false) {
441
451
  loadAvg15,
442
452
  cpuCount,
443
453
  usagePercentage,
454
+ usedCpuCores,
444
455
  },
445
456
  };
446
457
  } catch (error) {
@@ -1027,9 +1038,14 @@ export function formatUsageMessage(usage, diskSpace = null, githubRateLimit = nu
1027
1038
  // See: https://github.com/link-assistant/hive-mind/issues/1267
1028
1039
  const suffix = cpuLoad.usagePercentage >= DISPLAY_THRESHOLDS.CPU ? ' ⚠️' : ' used';
1029
1040
  section += `${usedBar} ${cpuLoad.usagePercentage}%${suffix}\n`;
1030
- // Show cores used based on 5m load average (e.g., "0.04/6 CPU cores used" or "3/6 CPU cores used")
1031
- // Use parseFloat to strip unnecessary trailing zeros (3.00 -> 3, 0.10 -> 0.1, 0.04 -> 0.04)
1032
- section += `${parseFloat(cpuLoad.loadAvg5.toFixed(2))}/${cpuLoad.cpuCount} CPU cores\n`;
1041
+ // Linux load average is demand, not bounded CPU time. Keep the cores-used
1042
+ // display within CPU capacity and show raw load average only when saturated.
1043
+ const usedCpuCores = cpuLoad.usedCpuCores ?? getDisplayCpuCoresUsed(cpuLoad.loadAvg5, cpuLoad.cpuCount);
1044
+ let cpuCoresLine = `${formatRoundedNumber(usedCpuCores)}/${cpuLoad.cpuCount} CPU cores used`;
1045
+ if (cpuLoad.loadAvg5 > cpuLoad.cpuCount) {
1046
+ cpuCoresLine += ` (5m load avg ${formatRoundedNumber(cpuLoad.loadAvg5)})`;
1047
+ }
1048
+ section += `${cpuCoresLine}\n`;
1033
1049
  sections.push(section);
1034
1050
  }
1035
1051
 
@@ -199,13 +199,14 @@ export const postTrackedComment = async ({ $, owner, repo, targetNumber, body })
199
199
  const apiPath = `repos/${owner}/${repo}/issues/${targetNumber}/comments`;
200
200
  const payload = JSON.stringify({ body });
201
201
 
202
- // `gh api --input -` reads from stdin. command-stream supports .stdin(...)
203
- // on the returned process handle (same API used in interactive-mode.lib.mjs
204
- // via execFileAsync). We build the invocation through $ so callers can
205
- // inject a mock.
202
+ // command-stream's options key is `stdin`, not `input` unknown keys are
203
+ // silently ignored, which previously left stdin inherited from the parent
204
+ // and caused `gh api --input -` to POST an empty body. GitHub's edge
205
+ // replied with HTTP 400 "Whoa there!" *before* the API layer ran. See
206
+ // issue #1631.
206
207
  let result;
207
208
  try {
208
- result = await $({ input: payload })`gh api ${apiPath} -X POST --input -`;
209
+ result = await $({ stdin: payload })`gh api ${apiPath} -X POST --input -`;
209
210
  } catch (err) {
210
211
  return { ok: false, commentId: null, stderr: err && err.message ? err.message : String(err) };
211
212
  }