@link-assistant/hive-mind 0.51.7 → 0.51.10

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,59 @@
1
1
  # @link-assistant/hive-mind
2
2
 
3
+ ## 0.51.10
4
+
5
+ ### Patch Changes
6
+
7
+ - 0f20e0b: Add missing language runtimes, agents, and tools to /version command output
8
+
9
+ This patch adds comprehensive version detection for all components installed by the ubuntu-24-server-install.sh script:
10
+
11
+ **New Language Runtimes:**
12
+ - Deno (JavaScript/TypeScript runtime)
13
+ - Go (Golang)
14
+ - Java (via SDKMAN)
15
+ - Lean (theorem prover)
16
+ - Perl (via Perlbrew)
17
+ - OCaml (via Opam)
18
+ - Rocq/Coq (theorem prover)
19
+
20
+ **New Development Tools:**
21
+ - SDKMAN (Java version manager)
22
+ - Elan (Lean version manager)
23
+ - Lake (Lean package manager)
24
+ - Perlbrew (Perl version manager)
25
+ - Opam (OCaml package manager)
26
+
27
+ **New C/C++ Development Tools Section:**
28
+ - Make
29
+ - CMake
30
+ - GCC
31
+ - G++
32
+ - Clang
33
+ - LLVM
34
+ - LLD (LLVM linker)
35
+
36
+ The /version command now displays all installed components that are available in the hive environment.
37
+
38
+ Fixes #1007
39
+
40
+ ## 0.51.9
41
+
42
+ ### Patch Changes
43
+
44
+ - Keep hive user's home directory clean
45
+ - Move Go GOPATH from `~/go` to `~/.go/path` to keep everything under the hidden `.go` directory
46
+ - Move Perlbrew from `~/perl5` to `~/.perl5` (hidden directory)
47
+ - Remove automatic cloning of hive-mind repository to `~/hive-mind`
48
+
49
+ This keeps the user's home directory empty by default, giving users freedom to organize their workspace as they prefer.
50
+
51
+ Fixes #1004
52
+
53
+ fix: ensure log attachment works when PR is merged during session
54
+
55
+ Fixes issue where log files would not be attached to pull requests when the PR was merged during the AI solving session. The `gh pr list` command only returns OPEN PRs by default, causing merged PRs to not be found. Added `--state all` flag to find PRs regardless of their state (OPEN, MERGED, or CLOSED), and added handling to skip operations that don't work on merged PRs (like `gh pr edit` and `gh pr ready`) while still allowing log attachment.
56
+
3
57
  ## 0.51.7
4
58
 
5
59
  ### Patch Changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@link-assistant/hive-mind",
3
- "version": "0.51.7",
3
+ "version": "0.51.10",
4
4
  "description": "AI-powered issue solver and hive mind for collaborative problem solving",
5
5
  "main": "src/hive.mjs",
6
6
  "type": "module",
@@ -417,7 +417,9 @@ export const verifyResults = async (owner, repo, branchName, issueNumber, prNumb
417
417
  await log('\nšŸ” Checking for pull requests from branch ' + branchName + '...');
418
418
 
419
419
  // First, get all PRs from our branch
420
- const allBranchPrsResult = await $`gh pr list --repo ${owner}/${repo} --head ${branchName} --json number,url,createdAt,headRefName,title,state,updatedAt,isDraft`;
420
+ // IMPORTANT: Use --state all to find PRs that may have been merged during the session (Issue #1008)
421
+ // Without --state all, gh pr list only returns OPEN PRs, missing merged ones
422
+ const allBranchPrsResult = await $`gh pr list --repo ${owner}/${repo} --head ${branchName} --state all --json number,url,createdAt,headRefName,title,state,updatedAt,isDraft`;
421
423
 
422
424
  if (allBranchPrsResult.code !== 0) {
423
425
  await log(' āš ļø Failed to check pull requests');
@@ -438,63 +440,72 @@ export const verifyResults = async (owner, repo, branchName, issueNumber, prNumb
438
440
  if (isPrFromSession) {
439
441
  await log(` āœ… Found pull request #${pr.number}: "${pr.title}"`);
440
442
 
441
- // Check if PR body has proper issue linking keywords
442
- const prBodyResult = await $`gh pr view ${pr.number} --repo ${owner}/${repo} --json body --jq .body`;
443
- if (prBodyResult.code === 0) {
444
- const prBody = prBodyResult.stdout.toString();
445
- const issueRef = argv.fork ? `${owner}/${repo}#${issueNumber}` : `#${issueNumber}`;
446
-
447
- // Use the new GitHub linking detection library to check for valid keywords
448
- // This ensures we only detect actual GitHub-recognized linking keywords
449
- // (fixes, closes, resolves and their variants) in proper format
450
- // See: https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue
451
- const hasLinkingKeyword = hasGitHubLinkingKeyword(prBody, issueNumber, argv.fork ? owner : null, argv.fork ? repo : null);
452
-
453
- if (!hasLinkingKeyword) {
454
- await log(` šŸ“ Updating PR body to link issue #${issueNumber}...`);
455
-
456
- // Add proper issue reference to the PR body
457
- const linkingText = `\n\nFixes ${issueRef}`;
458
- const updatedBody = prBody + linkingText;
459
-
460
- // Use --body-file instead of --body to avoid command-line length limits
461
- // and special character escaping issues that can cause hangs/timeouts
462
- const fs = (await use('fs')).promises;
463
- const tempBodyFile = `/tmp/pr-body-update-${pr.number}-${Date.now()}.md`;
464
- await fs.writeFile(tempBodyFile, updatedBody);
465
-
466
- try {
467
- const updateResult = await $`gh pr edit ${pr.number} --repo ${owner}/${repo} --body-file "${tempBodyFile}"`;
468
-
469
- // Clean up temp file
470
- await fs.unlink(tempBodyFile).catch(() => {});
443
+ // Check if PR was merged during the session (Issue #1008)
444
+ const isPrMerged = pr.state === 'MERGED';
445
+ if (isPrMerged) {
446
+ await log(` ā„¹ļø PR #${pr.number} was merged during the session`);
447
+ }
471
448
 
472
- if (updateResult.code === 0) {
473
- await log(` āœ… Updated PR body to include "Fixes ${issueRef}"`);
474
- } else {
475
- await log(` āš ļø Could not update PR body: ${updateResult.stderr ? updateResult.stderr.toString().trim() : 'Unknown error'}`);
449
+ // Skip PR body update and ready conversion for merged PRs (they can't be edited)
450
+ if (!isPrMerged) {
451
+ // Check if PR body has proper issue linking keywords
452
+ const prBodyResult = await $`gh pr view ${pr.number} --repo ${owner}/${repo} --json body --jq .body`;
453
+ if (prBodyResult.code === 0) {
454
+ const prBody = prBodyResult.stdout.toString();
455
+ const issueRef = argv.fork ? `${owner}/${repo}#${issueNumber}` : `#${issueNumber}`;
456
+
457
+ // Use the new GitHub linking detection library to check for valid keywords
458
+ // This ensures we only detect actual GitHub-recognized linking keywords
459
+ // (fixes, closes, resolves and their variants) in proper format
460
+ // See: https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue
461
+ const hasLinkingKeyword = hasGitHubLinkingKeyword(prBody, issueNumber, argv.fork ? owner : null, argv.fork ? repo : null);
462
+
463
+ if (!hasLinkingKeyword) {
464
+ await log(` šŸ“ Updating PR body to link issue #${issueNumber}...`);
465
+
466
+ // Add proper issue reference to the PR body
467
+ const linkingText = `\n\nFixes ${issueRef}`;
468
+ const updatedBody = prBody + linkingText;
469
+
470
+ // Use --body-file instead of --body to avoid command-line length limits
471
+ // and special character escaping issues that can cause hangs/timeouts
472
+ const fs = (await use('fs')).promises;
473
+ const tempBodyFile = `/tmp/pr-body-update-${pr.number}-${Date.now()}.md`;
474
+ await fs.writeFile(tempBodyFile, updatedBody);
475
+
476
+ try {
477
+ const updateResult = await $`gh pr edit ${pr.number} --repo ${owner}/${repo} --body-file "${tempBodyFile}"`;
478
+
479
+ // Clean up temp file
480
+ await fs.unlink(tempBodyFile).catch(() => {});
481
+
482
+ if (updateResult.code === 0) {
483
+ await log(` āœ… Updated PR body to include "Fixes ${issueRef}"`);
484
+ } else {
485
+ await log(` āš ļø Could not update PR body: ${updateResult.stderr ? updateResult.stderr.toString().trim() : 'Unknown error'}`);
486
+ }
487
+ } catch (updateError) {
488
+ // Clean up temp file on error
489
+ await fs.unlink(tempBodyFile).catch(() => {});
490
+ throw updateError;
476
491
  }
477
- } catch (updateError) {
478
- // Clean up temp file on error
479
- await fs.unlink(tempBodyFile).catch(() => {});
480
- throw updateError;
492
+ } else {
493
+ await log(' āœ… PR body already contains issue reference');
481
494
  }
482
- } else {
483
- await log(' āœ… PR body already contains issue reference');
484
495
  }
485
- }
486
496
 
487
- // Check if PR is ready for review (convert from draft if necessary)
488
- if (pr.isDraft) {
489
- await log(' šŸ”„ Converting PR from draft to ready for review...');
490
- const readyResult = await $`gh pr ready ${pr.number} --repo ${owner}/${repo}`;
491
- if (readyResult.code === 0) {
492
- await log(' āœ… PR converted to ready for review');
497
+ // Check if PR is ready for review (convert from draft if necessary)
498
+ if (pr.isDraft) {
499
+ await log(' šŸ”„ Converting PR from draft to ready for review...');
500
+ const readyResult = await $`gh pr ready ${pr.number} --repo ${owner}/${repo}`;
501
+ if (readyResult.code === 0) {
502
+ await log(' āœ… PR converted to ready for review');
503
+ } else {
504
+ await log(` āš ļø Could not convert PR to ready (${readyResult.stderr ? readyResult.stderr.toString().trim() : 'unknown error'})`);
505
+ }
493
506
  } else {
494
- await log(` āš ļø Could not convert PR to ready (${readyResult.stderr ? readyResult.stderr.toString().trim() : 'unknown error'})`);
507
+ await log(' āœ… PR is already ready for review', { verbose: true });
495
508
  }
496
- } else {
497
- await log(' āœ… PR is already ready for review', { verbose: true });
498
509
  }
499
510
 
500
511
  // Upload log file to PR if requested
@@ -116,6 +116,55 @@ export async function getVersionInfo(verbose = false) {
116
116
  console.log(`[VERBOSE] .NET version: ${dotnetVersion}`);
117
117
  }
118
118
 
119
+ // Deno
120
+ const denoVersion = execCommand('deno --version 2>&1 | head -n1', verbose);
121
+ if (verbose && denoVersion) {
122
+ console.log(`[VERBOSE] Deno version: ${denoVersion}`);
123
+ }
124
+
125
+ // Go (Golang)
126
+ const goVersion = execCommand('go version 2>&1', verbose);
127
+ if (verbose && goVersion) {
128
+ console.log(`[VERBOSE] Go version: ${goVersion}`);
129
+ }
130
+
131
+ // Java
132
+ const javaVersion = execCommand('java -version 2>&1 | head -n1', verbose);
133
+ if (verbose && javaVersion) {
134
+ console.log(`[VERBOSE] Java version: ${javaVersion}`);
135
+ }
136
+
137
+ // Lean (theorem prover)
138
+ const leanVersion = execCommand('lean --version 2>&1', verbose);
139
+ if (verbose && leanVersion) {
140
+ console.log(`[VERBOSE] Lean version: ${leanVersion}`);
141
+ }
142
+
143
+ // Perl
144
+ const perlVersion = execCommand("perl -v 2>&1 | grep -oE 'v[0-9]+\\.[0-9]+\\.[0-9]+'", verbose);
145
+ if (verbose && perlVersion) {
146
+ console.log(`[VERBOSE] Perl version: ${perlVersion}`);
147
+ }
148
+
149
+ // OCaml (via opam)
150
+ const ocamlVersion = execCommand('ocaml --version 2>&1', verbose);
151
+ if (verbose && ocamlVersion) {
152
+ console.log(`[VERBOSE] OCaml version: ${ocamlVersion}`);
153
+ }
154
+
155
+ // Rocq/Coq (theorem prover)
156
+ // Try rocq first (Rocq 9.0+), then fall back to coqc (legacy)
157
+ let rocqVersion = execCommand('rocq -v 2>&1 | head -n1', verbose);
158
+ if (!rocqVersion) {
159
+ rocqVersion = execCommand('rocqc --version 2>&1 | head -n1', verbose);
160
+ }
161
+ if (!rocqVersion) {
162
+ rocqVersion = execCommand('coqc --version 2>&1 | head -n1', verbose);
163
+ }
164
+ if (verbose && rocqVersion) {
165
+ console.log(`[VERBOSE] Rocq/Coq version: ${rocqVersion}`);
166
+ }
167
+
119
168
  // === Development Tools ===
120
169
 
121
170
  // Git
@@ -148,6 +197,80 @@ export async function getVersionInfo(verbose = false) {
148
197
  console.log(`[VERBOSE] NPM version: ${npmVersion}`);
149
198
  }
150
199
 
200
+ // SDKMAN (Java version manager)
201
+ const sdkmanVersion = execCommand("sdk version 2>&1 | grep -oE '[0-9]+\\.[0-9]+\\.[0-9]+'", verbose);
202
+ if (verbose && sdkmanVersion) {
203
+ console.log(`[VERBOSE] SDKMAN version: ${sdkmanVersion}`);
204
+ }
205
+
206
+ // Elan (Lean version manager)
207
+ const elanVersion = execCommand('elan --version 2>&1', verbose);
208
+ if (verbose && elanVersion) {
209
+ console.log(`[VERBOSE] Elan version: ${elanVersion}`);
210
+ }
211
+
212
+ // Lake (Lean package manager)
213
+ const lakeVersion = execCommand('lake --version 2>&1', verbose);
214
+ if (verbose && lakeVersion) {
215
+ console.log(`[VERBOSE] Lake version: ${lakeVersion}`);
216
+ }
217
+
218
+ // Perlbrew (Perl version manager)
219
+ const perlbrewVersion = execCommand('perlbrew --version 2>&1', verbose);
220
+ if (verbose && perlbrewVersion) {
221
+ console.log(`[VERBOSE] Perlbrew version: ${perlbrewVersion}`);
222
+ }
223
+
224
+ // Opam (OCaml package manager)
225
+ const opamVersion = execCommand('opam --version 2>&1', verbose);
226
+ if (verbose && opamVersion) {
227
+ console.log(`[VERBOSE] Opam version: ${opamVersion}`);
228
+ }
229
+
230
+ // === C/C++ Development Tools ===
231
+
232
+ // Make
233
+ const makeVersion = execCommand('make --version 2>&1 | head -n1', verbose);
234
+ if (verbose && makeVersion) {
235
+ console.log(`[VERBOSE] Make version: ${makeVersion}`);
236
+ }
237
+
238
+ // CMake
239
+ const cmakeVersion = execCommand('cmake --version 2>&1 | head -n1', verbose);
240
+ if (verbose && cmakeVersion) {
241
+ console.log(`[VERBOSE] CMake version: ${cmakeVersion}`);
242
+ }
243
+
244
+ // GCC
245
+ const gccVersion = execCommand('gcc --version 2>&1 | head -n1', verbose);
246
+ if (verbose && gccVersion) {
247
+ console.log(`[VERBOSE] GCC version: ${gccVersion}`);
248
+ }
249
+
250
+ // G++
251
+ const gppVersion = execCommand('g++ --version 2>&1 | head -n1', verbose);
252
+ if (verbose && gppVersion) {
253
+ console.log(`[VERBOSE] G++ version: ${gppVersion}`);
254
+ }
255
+
256
+ // Clang
257
+ const clangVersion = execCommand('clang --version 2>&1 | head -n1', verbose);
258
+ if (verbose && clangVersion) {
259
+ console.log(`[VERBOSE] Clang version: ${clangVersion}`);
260
+ }
261
+
262
+ // LLVM
263
+ const llvmVersion = execCommand('llvm-config --version 2>&1', verbose);
264
+ if (verbose && llvmVersion) {
265
+ console.log(`[VERBOSE] LLVM version: ${llvmVersion}`);
266
+ }
267
+
268
+ // LLD (LLVM linker)
269
+ const lldVersion = execCommand('lld --version 2>&1 | head -n1', verbose);
270
+ if (verbose && lldVersion) {
271
+ console.log(`[VERBOSE] LLD version: ${lldVersion}`);
272
+ }
273
+
151
274
  // === Platform Information ===
152
275
  const platform = process.platform;
153
276
  const arch = process.arch;
@@ -176,6 +299,13 @@ export async function getVersionInfo(verbose = false) {
176
299
  php: phpVersion,
177
300
  bun: bunVersion,
178
301
  dotnet: dotnetVersion,
302
+ deno: denoVersion,
303
+ go: goVersion,
304
+ java: javaVersion,
305
+ lean: leanVersion,
306
+ perl: perlVersion,
307
+ ocaml: ocamlVersion,
308
+ rocq: rocqVersion,
179
309
 
180
310
  // Development tools
181
311
  git: gitVersion,
@@ -185,6 +315,20 @@ export async function getVersionInfo(verbose = false) {
185
315
  pyenv: pyenvVersion,
186
316
  cargo: cargoVersion,
187
317
  brew: brewVersion,
318
+ sdkman: sdkmanVersion,
319
+ elan: elanVersion,
320
+ lake: lakeVersion,
321
+ perlbrew: perlbrewVersion,
322
+ opam: opamVersion,
323
+
324
+ // C/C++ Development Tools
325
+ make: makeVersion,
326
+ cmake: cmakeVersion,
327
+ gcc: gccVersion,
328
+ gpp: gppVersion,
329
+ clang: clangVersion,
330
+ llvm: llvmVersion,
331
+ lld: lldVersion,
188
332
 
189
333
  // Platform
190
334
  platform: `${platform} (${arch})`,
@@ -266,6 +410,27 @@ export function formatVersionMessage(versions) {
266
410
  if (versions.dotnet) {
267
411
  runtimeLines.push(`• .NET: \`${versions.dotnet}\``);
268
412
  }
413
+ if (versions.deno) {
414
+ runtimeLines.push(`• Deno: \`${versions.deno}\``);
415
+ }
416
+ if (versions.go) {
417
+ runtimeLines.push(`• Go: \`${versions.go}\``);
418
+ }
419
+ if (versions.java) {
420
+ runtimeLines.push(`• Java: \`${versions.java}\``);
421
+ }
422
+ if (versions.lean) {
423
+ runtimeLines.push(`• Lean: \`${versions.lean}\``);
424
+ }
425
+ if (versions.perl) {
426
+ runtimeLines.push(`• Perl: \`${versions.perl}\``);
427
+ }
428
+ if (versions.ocaml) {
429
+ runtimeLines.push(`• OCaml: \`${versions.ocaml}\``);
430
+ }
431
+ if (versions.rocq) {
432
+ runtimeLines.push(`• Rocq/Coq: \`${versions.rocq}\``);
433
+ }
269
434
 
270
435
  if (runtimeLines.length > 0) {
271
436
  lines.push('');
@@ -296,6 +461,21 @@ export function formatVersionMessage(versions) {
296
461
  if (versions.brew) {
297
462
  toolLines.push(`• Homebrew: \`${versions.brew}\``);
298
463
  }
464
+ if (versions.sdkman) {
465
+ toolLines.push(`• SDKMAN: \`${versions.sdkman}\``);
466
+ }
467
+ if (versions.elan) {
468
+ toolLines.push(`• Elan: \`${versions.elan}\``);
469
+ }
470
+ if (versions.lake) {
471
+ toolLines.push(`• Lake: \`${versions.lake}\``);
472
+ }
473
+ if (versions.perlbrew) {
474
+ toolLines.push(`• Perlbrew: \`${versions.perlbrew}\``);
475
+ }
476
+ if (versions.opam) {
477
+ toolLines.push(`• Opam: \`${versions.opam}\``);
478
+ }
299
479
 
300
480
  if (toolLines.length > 0) {
301
481
  lines.push('');
@@ -303,6 +483,36 @@ export function formatVersionMessage(versions) {
303
483
  lines.push(...toolLines);
304
484
  }
305
485
 
486
+ // === C/C++ Development Tools ===
487
+ const cppToolLines = [];
488
+ if (versions.make) {
489
+ cppToolLines.push(`• Make: \`${versions.make}\``);
490
+ }
491
+ if (versions.cmake) {
492
+ cppToolLines.push(`• CMake: \`${versions.cmake}\``);
493
+ }
494
+ if (versions.gcc) {
495
+ cppToolLines.push(`• GCC: \`${versions.gcc}\``);
496
+ }
497
+ if (versions.gpp) {
498
+ cppToolLines.push(`• G++: \`${versions.gpp}\``);
499
+ }
500
+ if (versions.clang) {
501
+ cppToolLines.push(`• Clang: \`${versions.clang}\``);
502
+ }
503
+ if (versions.llvm) {
504
+ cppToolLines.push(`• LLVM: \`${versions.llvm}\``);
505
+ }
506
+ if (versions.lld) {
507
+ cppToolLines.push(`• LLD: \`${versions.lld}\``);
508
+ }
509
+
510
+ if (cppToolLines.length > 0) {
511
+ lines.push('');
512
+ lines.push('*šŸ”§ C/C++ Development Tools*');
513
+ lines.push(...cppToolLines);
514
+ }
515
+
306
516
  // === Platform ===
307
517
  if (versions.platform) {
308
518
  lines.push('');