@link-assistant/hive-mind 1.23.13 → 1.23.14
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 +12 -0
- package/package.json +1 -1
- package/src/version-info.lib.mjs +355 -403
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# @link-assistant/hive-mind
|
|
2
2
|
|
|
3
|
+
## 1.23.14
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 069d437: Parallelize version gathering with Promise.all for 6-30x performance improvement
|
|
8
|
+
- Replaced sequential `execSync` calls with parallel `execAsync` using `Promise.all`
|
|
9
|
+
- Reduced execution time from 30-150s to ~2-5s for version info gathering
|
|
10
|
+
- Added support for all `--tool` options: agent, codex, opencode, qwen-code, gemini, copilot
|
|
11
|
+
- Reorganized Telegram output to group tools by programming language instead of generic categories
|
|
12
|
+
- Consolidated hive-mind version display to show single version with restart warning when process version differs from installed
|
|
13
|
+
- Added `gatherTimeMs` metric to track performance
|
|
14
|
+
|
|
3
15
|
## 1.23.13
|
|
4
16
|
|
|
5
17
|
### Patch Changes
|
package/package.json
CHANGED
package/src/version-info.lib.mjs
CHANGED
|
@@ -2,42 +2,152 @@
|
|
|
2
2
|
|
|
3
3
|
// Version information library for hive-mind project
|
|
4
4
|
// Provides comprehensive version information for bot, commands, and runtime
|
|
5
|
+
//
|
|
6
|
+
// Performance optimization (issue #1320):
|
|
7
|
+
// Uses Promise.all for parallel command execution instead of sequential execSync.
|
|
8
|
+
// This reduces version gathering time from ~30-150s to ~5s (limited by slowest command).
|
|
5
9
|
|
|
6
10
|
import { getVersion } from './version.lib.mjs';
|
|
7
|
-
import {
|
|
11
|
+
import { exec } from 'child_process';
|
|
12
|
+
import { promisify } from 'util';
|
|
13
|
+
|
|
14
|
+
const execAsync = promisify(exec);
|
|
8
15
|
|
|
9
16
|
/**
|
|
10
|
-
* Execute a command and return its output, or null if it fails
|
|
17
|
+
* Execute a command asynchronously and return its output, or null if it fails
|
|
11
18
|
* @param {string} command - Command to execute
|
|
12
|
-
* @param {
|
|
13
|
-
* @returns {string|null} Command output or null
|
|
19
|
+
* @param {number} timeout - Timeout in milliseconds (default: 5000ms)
|
|
20
|
+
* @returns {Promise<string|null>} Command output or null
|
|
14
21
|
*/
|
|
15
|
-
function
|
|
22
|
+
async function execCommandAsync(command, timeout = 5000) {
|
|
16
23
|
try {
|
|
17
|
-
const
|
|
18
|
-
const trimmed =
|
|
24
|
+
const { stdout } = await execAsync(command, { timeout, maxBuffer: 1024 * 1024 });
|
|
25
|
+
const trimmed = stdout.trim();
|
|
19
26
|
// Return null if the output looks like an error message
|
|
20
27
|
if (trimmed.includes('not found') || trimmed.includes('command not found') || trimmed === '') {
|
|
21
28
|
return null;
|
|
22
29
|
}
|
|
23
30
|
return trimmed;
|
|
24
|
-
} catch
|
|
25
|
-
if (verbose) {
|
|
26
|
-
console.log(`[VERBOSE] Command failed: ${command}`, error.message);
|
|
27
|
-
}
|
|
31
|
+
} catch {
|
|
28
32
|
return null;
|
|
29
33
|
}
|
|
30
34
|
}
|
|
31
35
|
|
|
36
|
+
/**
|
|
37
|
+
* Command definitions for version checking
|
|
38
|
+
* Each entry has: key, command, and optional fallbacks
|
|
39
|
+
* @type {Array<{key: string, command: string, fallbacks?: string[]}>}
|
|
40
|
+
*/
|
|
41
|
+
const VERSION_COMMANDS = [
|
|
42
|
+
// AI Agents and Tools (--tool options)
|
|
43
|
+
{ key: 'claudeCode', command: 'claude --version 2>&1' },
|
|
44
|
+
{ key: 'agent', command: 'agent --version 2>&1' },
|
|
45
|
+
{ key: 'codex', command: 'codex --version 2>&1' },
|
|
46
|
+
{ key: 'opencode', command: 'opencode --version 2>&1' },
|
|
47
|
+
{ key: 'qwenCode', command: 'qwen-code --version 2>&1' },
|
|
48
|
+
{ key: 'gemini', command: 'gemini --version 2>&1' },
|
|
49
|
+
{ key: 'copilot', command: 'copilot --version 2>&1' },
|
|
50
|
+
|
|
51
|
+
// Browser Automation
|
|
52
|
+
{ key: 'playwright', command: 'playwright --version 2>&1' },
|
|
53
|
+
{ key: 'playwrightMcp', command: "npm list -g @playwright/mcp --depth=0 2>&1 | grep @playwright/mcp | awk '{print $2}'" },
|
|
54
|
+
|
|
55
|
+
// JavaScript/Node.js ecosystem
|
|
56
|
+
{ key: 'bun', command: 'bun --version 2>&1' },
|
|
57
|
+
{ key: 'deno', command: 'deno --version 2>&1 | head -n1' },
|
|
58
|
+
{ key: 'npm', command: 'npm --version 2>&1' },
|
|
59
|
+
{ key: 'nvm', command: 'nvm --version 2>&1' },
|
|
60
|
+
|
|
61
|
+
// Python ecosystem
|
|
62
|
+
{ key: 'python', command: 'python --version 2>&1' },
|
|
63
|
+
{ key: 'pyenv', command: 'pyenv --version 2>&1' },
|
|
64
|
+
|
|
65
|
+
// Rust ecosystem
|
|
66
|
+
{ key: 'rust', command: 'rustc --version 2>&1' },
|
|
67
|
+
{ key: 'cargo', command: 'cargo --version 2>&1' },
|
|
68
|
+
|
|
69
|
+
// Java ecosystem
|
|
70
|
+
{ key: 'java', command: 'java -version 2>&1 | head -n1' },
|
|
71
|
+
{ key: 'sdkman', command: "sdk version 2>&1 | grep -oE '[0-9]+\\.[0-9]+\\.[0-9]+'" },
|
|
72
|
+
|
|
73
|
+
// Go
|
|
74
|
+
{ key: 'go', command: 'go version 2>&1' },
|
|
75
|
+
|
|
76
|
+
// PHP
|
|
77
|
+
{ key: 'php', command: 'php --version 2>&1 | head -n1' },
|
|
78
|
+
|
|
79
|
+
// .NET
|
|
80
|
+
{ key: 'dotnet', command: 'dotnet --version 2>&1' },
|
|
81
|
+
|
|
82
|
+
// Perl ecosystem
|
|
83
|
+
{ key: 'perl', command: "perl -v 2>&1 | grep -oE 'v[0-9]+\\.[0-9]+\\.[0-9]+'" },
|
|
84
|
+
{ key: 'perlbrew', command: 'perlbrew --version 2>&1' },
|
|
85
|
+
|
|
86
|
+
// OCaml/Rocq ecosystem
|
|
87
|
+
{ key: 'ocaml', command: 'ocaml --version 2>&1' },
|
|
88
|
+
{ key: 'opam', command: 'opam --version 2>&1' },
|
|
89
|
+
// Rocq has fallback commands (rocq -> rocqc -> coqc)
|
|
90
|
+
{ key: 'rocq', command: 'rocq -v 2>&1 | head -n1', fallbacks: ['rocqc --version 2>&1 | head -n1', 'coqc --version 2>&1 | head -n1'] },
|
|
91
|
+
|
|
92
|
+
// Lean ecosystem
|
|
93
|
+
{ key: 'lean', command: 'lean --version 2>&1' },
|
|
94
|
+
{ key: 'elan', command: 'elan --version 2>&1' },
|
|
95
|
+
{ key: 'lake', command: 'lake --version 2>&1' },
|
|
96
|
+
|
|
97
|
+
// C/C++ Development Tools
|
|
98
|
+
{ key: 'gcc', command: 'gcc --version 2>&1 | head -n1' },
|
|
99
|
+
{ key: 'gpp', command: 'g++ --version 2>&1 | head -n1' },
|
|
100
|
+
{ key: 'clang', command: 'clang --version 2>&1 | head -n1' },
|
|
101
|
+
{ key: 'llvm', command: 'llvm-config --version 2>&1' },
|
|
102
|
+
{ key: 'lld', command: 'lld --version 2>&1 | head -n1' },
|
|
103
|
+
{ key: 'make', command: 'make --version 2>&1 | head -n1' },
|
|
104
|
+
{ key: 'cmake', command: 'cmake --version 2>&1 | head -n1' },
|
|
105
|
+
|
|
106
|
+
// Development Tools
|
|
107
|
+
{ key: 'git', command: 'git --version 2>&1' },
|
|
108
|
+
{ key: 'gh', command: 'gh --version 2>&1 | head -n1' },
|
|
109
|
+
{ key: 'brew', command: 'brew --version 2>&1 | head -n1' },
|
|
110
|
+
];
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Execute a version command with optional fallbacks
|
|
114
|
+
* @param {{key: string, command: string, fallbacks?: string[]}} cmdDef - Command definition
|
|
115
|
+
* @param {boolean} verbose - Enable verbose logging
|
|
116
|
+
* @returns {Promise<{key: string, value: string|null}>}
|
|
117
|
+
*/
|
|
118
|
+
async function executeVersionCommand(cmdDef, verbose) {
|
|
119
|
+
let result = await execCommandAsync(cmdDef.command);
|
|
120
|
+
|
|
121
|
+
// Try fallbacks if primary command failed
|
|
122
|
+
if (!result && cmdDef.fallbacks) {
|
|
123
|
+
for (const fallback of cmdDef.fallbacks) {
|
|
124
|
+
result = await execCommandAsync(fallback);
|
|
125
|
+
if (result) break;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
if (verbose && result) {
|
|
130
|
+
console.log(`[VERBOSE] ${cmdDef.key}: ${result}`);
|
|
131
|
+
} else if (verbose && !result) {
|
|
132
|
+
console.log(`[VERBOSE] ${cmdDef.key}: not found`);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
return { key: cmdDef.key, value: result };
|
|
136
|
+
}
|
|
137
|
+
|
|
32
138
|
/**
|
|
33
139
|
* Get comprehensive version information for all components
|
|
140
|
+
* Uses Promise.all for parallel execution (issue #1320)
|
|
34
141
|
* @param {boolean} verbose - Enable verbose logging
|
|
142
|
+
* @param {string} [processVersion] - Optional: version from the running process (for restart warning)
|
|
35
143
|
* @returns {Promise<Object>} Version information object
|
|
36
144
|
*/
|
|
37
|
-
export async function getVersionInfo(verbose = false) {
|
|
145
|
+
export async function getVersionInfo(verbose = false, processVersion = null) {
|
|
146
|
+
const startTime = Date.now();
|
|
147
|
+
|
|
38
148
|
try {
|
|
39
149
|
if (verbose) {
|
|
40
|
-
console.log('[VERBOSE] Gathering version information...');
|
|
150
|
+
console.log('[VERBOSE] Gathering version information (parallel execution)...');
|
|
41
151
|
}
|
|
42
152
|
|
|
43
153
|
// Get hive-mind package version
|
|
@@ -46,297 +156,120 @@ export async function getVersionInfo(verbose = false) {
|
|
|
46
156
|
console.log(`[VERBOSE] Package version: ${packageVersion}`);
|
|
47
157
|
}
|
|
48
158
|
|
|
49
|
-
//
|
|
159
|
+
// Execute all version commands in parallel
|
|
160
|
+
const results = await Promise.all(VERSION_COMMANDS.map(cmd => executeVersionCommand(cmd, verbose)));
|
|
50
161
|
|
|
51
|
-
//
|
|
52
|
-
const
|
|
53
|
-
|
|
54
|
-
|
|
162
|
+
// Convert results array to object
|
|
163
|
+
const versions = {};
|
|
164
|
+
for (const { key, value } of results) {
|
|
165
|
+
versions[key] = value;
|
|
55
166
|
}
|
|
56
167
|
|
|
57
|
-
//
|
|
58
|
-
|
|
59
|
-
if (verbose && playwrightVersion) {
|
|
60
|
-
console.log(`[VERBOSE] Playwright version: ${playwrightVersion}`);
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
// Playwright MCP (check if installed via npm)
|
|
64
|
-
const playwrightMcpVersion = execCommand("npm list -g @playwright/mcp --depth=0 2>&1 | grep @playwright/mcp | awk '{print $2}'", verbose);
|
|
65
|
-
if (verbose && playwrightMcpVersion) {
|
|
66
|
-
console.log(`[VERBOSE] Playwright MCP version: ${playwrightMcpVersion}`);
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
// === Language Runtimes ===
|
|
70
|
-
|
|
71
|
-
// Node.js (from process, always available)
|
|
72
|
-
const nodeVersion = process.version;
|
|
168
|
+
// Add Node.js version (always available from process)
|
|
169
|
+
versions.node = process.version;
|
|
73
170
|
if (verbose) {
|
|
74
|
-
console.log(`[VERBOSE] Node.js version: ${
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
// Python
|
|
78
|
-
const pythonVersion = execCommand('python --version 2>&1', verbose);
|
|
79
|
-
if (verbose && pythonVersion) {
|
|
80
|
-
console.log(`[VERBOSE] Python version: ${pythonVersion}`);
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
// Pyenv
|
|
84
|
-
const pyenvVersion = execCommand('pyenv --version 2>&1', verbose);
|
|
85
|
-
if (verbose && pyenvVersion) {
|
|
86
|
-
console.log(`[VERBOSE] Pyenv version: ${pyenvVersion}`);
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
// Rust
|
|
90
|
-
const rustVersion = execCommand('rustc --version 2>&1', verbose);
|
|
91
|
-
if (verbose && rustVersion) {
|
|
92
|
-
console.log(`[VERBOSE] Rust version: ${rustVersion}`);
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
// Cargo
|
|
96
|
-
const cargoVersion = execCommand('cargo --version 2>&1', verbose);
|
|
97
|
-
if (verbose && cargoVersion) {
|
|
98
|
-
console.log(`[VERBOSE] Cargo version: ${cargoVersion}`);
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
// PHP
|
|
102
|
-
const phpVersion = execCommand('php --version 2>&1 | head -n1', verbose);
|
|
103
|
-
if (verbose && phpVersion) {
|
|
104
|
-
console.log(`[VERBOSE] PHP version: ${phpVersion}`);
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
// Bun
|
|
108
|
-
const bunVersion = execCommand('bun --version 2>&1', verbose);
|
|
109
|
-
if (verbose && bunVersion) {
|
|
110
|
-
console.log(`[VERBOSE] Bun version: ${bunVersion}`);
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
// .NET
|
|
114
|
-
const dotnetVersion = execCommand('dotnet --version 2>&1', verbose);
|
|
115
|
-
if (verbose && dotnetVersion) {
|
|
116
|
-
console.log(`[VERBOSE] .NET version: ${dotnetVersion}`);
|
|
117
|
-
}
|
|
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
|
-
|
|
168
|
-
// === Development Tools ===
|
|
169
|
-
|
|
170
|
-
// Git
|
|
171
|
-
const gitVersion = execCommand('git --version 2>&1', verbose);
|
|
172
|
-
if (verbose && gitVersion) {
|
|
173
|
-
console.log(`[VERBOSE] Git version: ${gitVersion}`);
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
// GitHub CLI
|
|
177
|
-
const ghVersion = execCommand('gh --version 2>&1 | head -n1', verbose);
|
|
178
|
-
if (verbose && ghVersion) {
|
|
179
|
-
console.log(`[VERBOSE] GitHub CLI version: ${ghVersion}`);
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
// NVM
|
|
183
|
-
const nvmVersion = execCommand('nvm --version 2>&1', verbose);
|
|
184
|
-
if (verbose && nvmVersion) {
|
|
185
|
-
console.log(`[VERBOSE] NVM version: ${nvmVersion}`);
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
// Homebrew
|
|
189
|
-
const brewVersion = execCommand('brew --version 2>&1 | head -n1', verbose);
|
|
190
|
-
if (verbose && brewVersion) {
|
|
191
|
-
console.log(`[VERBOSE] Homebrew version: ${brewVersion}`);
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
// NPM
|
|
195
|
-
const npmVersion = execCommand('npm --version 2>&1', verbose);
|
|
196
|
-
if (verbose && npmVersion) {
|
|
197
|
-
console.log(`[VERBOSE] NPM version: ${npmVersion}`);
|
|
198
|
-
}
|
|
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}`);
|
|
171
|
+
console.log(`[VERBOSE] Node.js version: ${versions.node}`);
|
|
272
172
|
}
|
|
273
173
|
|
|
274
|
-
//
|
|
174
|
+
// Platform information
|
|
275
175
|
const platform = process.platform;
|
|
276
176
|
const arch = process.arch;
|
|
177
|
+
versions.platform = `${platform} (${arch})`;
|
|
277
178
|
if (verbose) {
|
|
278
|
-
console.log(`[VERBOSE] Platform: ${platform}
|
|
179
|
+
console.log(`[VERBOSE] Platform: ${versions.platform}`);
|
|
279
180
|
}
|
|
280
181
|
|
|
182
|
+
// Check if process version differs from installed version (restart warning)
|
|
183
|
+
const needsRestart = processVersion && processVersion !== packageVersion;
|
|
184
|
+
|
|
281
185
|
// Build version info object
|
|
282
186
|
const versionInfo = {
|
|
283
187
|
success: true,
|
|
284
188
|
versions: {
|
|
285
|
-
//
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
// Agents
|
|
291
|
-
claudeCode:
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
//
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
cargo:
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
189
|
+
// Hive-mind package (single entry, not duplicated)
|
|
190
|
+
hiveMind: packageVersion,
|
|
191
|
+
processVersion: processVersion || packageVersion,
|
|
192
|
+
needsRestart,
|
|
193
|
+
|
|
194
|
+
// AI Agents (--tool options)
|
|
195
|
+
claudeCode: versions.claudeCode,
|
|
196
|
+
agent: versions.agent,
|
|
197
|
+
codex: versions.codex,
|
|
198
|
+
opencode: versions.opencode,
|
|
199
|
+
qwenCode: versions.qwenCode,
|
|
200
|
+
gemini: versions.gemini,
|
|
201
|
+
copilot: versions.copilot,
|
|
202
|
+
|
|
203
|
+
// Browser Automation
|
|
204
|
+
playwright: versions.playwright,
|
|
205
|
+
playwrightMcp: versions.playwrightMcp,
|
|
206
|
+
|
|
207
|
+
// JavaScript/Node.js
|
|
208
|
+
node: versions.node,
|
|
209
|
+
bun: versions.bun,
|
|
210
|
+
deno: versions.deno,
|
|
211
|
+
npm: versions.npm,
|
|
212
|
+
nvm: versions.nvm,
|
|
213
|
+
|
|
214
|
+
// Python
|
|
215
|
+
python: versions.python,
|
|
216
|
+
pyenv: versions.pyenv,
|
|
217
|
+
|
|
218
|
+
// Rust
|
|
219
|
+
rust: versions.rust,
|
|
220
|
+
cargo: versions.cargo,
|
|
221
|
+
|
|
222
|
+
// Java
|
|
223
|
+
java: versions.java,
|
|
224
|
+
sdkman: versions.sdkman,
|
|
225
|
+
|
|
226
|
+
// Go
|
|
227
|
+
go: versions.go,
|
|
228
|
+
|
|
229
|
+
// PHP
|
|
230
|
+
php: versions.php,
|
|
231
|
+
|
|
232
|
+
// .NET
|
|
233
|
+
dotnet: versions.dotnet,
|
|
234
|
+
|
|
235
|
+
// Perl
|
|
236
|
+
perl: versions.perl,
|
|
237
|
+
perlbrew: versions.perlbrew,
|
|
238
|
+
|
|
239
|
+
// OCaml/Rocq
|
|
240
|
+
ocaml: versions.ocaml,
|
|
241
|
+
opam: versions.opam,
|
|
242
|
+
rocq: versions.rocq,
|
|
243
|
+
|
|
244
|
+
// Lean
|
|
245
|
+
lean: versions.lean,
|
|
246
|
+
elan: versions.elan,
|
|
247
|
+
lake: versions.lake,
|
|
248
|
+
|
|
249
|
+
// C/C++
|
|
250
|
+
gcc: versions.gcc,
|
|
251
|
+
gpp: versions.gpp,
|
|
252
|
+
clang: versions.clang,
|
|
253
|
+
llvm: versions.llvm,
|
|
254
|
+
lld: versions.lld,
|
|
255
|
+
make: versions.make,
|
|
256
|
+
cmake: versions.cmake,
|
|
257
|
+
|
|
258
|
+
// Development Tools
|
|
259
|
+
git: versions.git,
|
|
260
|
+
gh: versions.gh,
|
|
261
|
+
brew: versions.brew,
|
|
332
262
|
|
|
333
263
|
// Platform
|
|
334
|
-
platform:
|
|
264
|
+
platform: versions.platform,
|
|
335
265
|
},
|
|
266
|
+
// Performance metrics
|
|
267
|
+
gatherTimeMs: Date.now() - startTime,
|
|
336
268
|
};
|
|
337
269
|
|
|
338
270
|
if (verbose) {
|
|
339
|
-
console.log(
|
|
271
|
+
console.log(`[VERBOSE] Version info gathered in ${versionInfo.gatherTimeMs}ms`);
|
|
272
|
+
console.log('[VERBOSE] Version info:', JSON.stringify(versionInfo, null, 2));
|
|
340
273
|
}
|
|
341
274
|
|
|
342
275
|
return versionInfo;
|
|
@@ -348,134 +281,183 @@ export async function getVersionInfo(verbose = false) {
|
|
|
348
281
|
return {
|
|
349
282
|
success: false,
|
|
350
283
|
error: error.message || 'Failed to gather version information',
|
|
284
|
+
gatherTimeMs: Date.now() - startTime,
|
|
351
285
|
};
|
|
352
286
|
}
|
|
353
287
|
}
|
|
354
288
|
|
|
289
|
+
/**
|
|
290
|
+
* Helper to add version line if version exists
|
|
291
|
+
* @param {string[]} lines - Array to push to
|
|
292
|
+
* @param {string} label - Display label
|
|
293
|
+
* @param {string|null} version - Version string or null
|
|
294
|
+
*/
|
|
295
|
+
function addVersionLine(lines, label, version) {
|
|
296
|
+
if (version) {
|
|
297
|
+
lines.push(`• ${label}: \`${version}\``);
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
|
|
355
301
|
/**
|
|
356
302
|
* Format version information as a Telegram message
|
|
303
|
+
* Groups tools by programming language for better readability (issue #1320)
|
|
357
304
|
* @param {Object} versions - Version information object
|
|
358
305
|
* @returns {string} Formatted message
|
|
359
306
|
*/
|
|
360
307
|
export function formatVersionMessage(versions) {
|
|
361
308
|
const lines = [];
|
|
362
309
|
|
|
363
|
-
// ===
|
|
364
|
-
lines.push('*🤖
|
|
365
|
-
if (versions.
|
|
366
|
-
lines.push(`•
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
}
|
|
371
|
-
if (versions.hive) {
|
|
372
|
-
lines.push(`• hive: \`${versions.hive}\``);
|
|
310
|
+
// === Hive-Mind Package (single entry with restart warning) ===
|
|
311
|
+
lines.push('*🤖 Hive-Mind*');
|
|
312
|
+
if (versions.hiveMind) {
|
|
313
|
+
lines.push(`• Version: \`${versions.hiveMind}\``);
|
|
314
|
+
if (versions.needsRestart) {
|
|
315
|
+
lines.push(`⚠️ _Process running: \`${versions.processVersion}\` (restart needed)_`);
|
|
316
|
+
}
|
|
373
317
|
}
|
|
374
318
|
|
|
375
|
-
// === Agents ===
|
|
319
|
+
// === AI Agents (--tool options) ===
|
|
376
320
|
const agentLines = [];
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
agentLines.push(`• Playwright MCP: \`${versions.playwrightMcp}\``);
|
|
385
|
-
}
|
|
321
|
+
addVersionLine(agentLines, 'Claude Code', versions.claudeCode);
|
|
322
|
+
addVersionLine(agentLines, 'Agent CLI', versions.agent);
|
|
323
|
+
addVersionLine(agentLines, 'OpenAI Codex', versions.codex);
|
|
324
|
+
addVersionLine(agentLines, 'OpenCode', versions.opencode);
|
|
325
|
+
addVersionLine(agentLines, 'Qwen Code', versions.qwenCode);
|
|
326
|
+
addVersionLine(agentLines, 'Gemini CLI', versions.gemini);
|
|
327
|
+
addVersionLine(agentLines, 'GitHub Copilot', versions.copilot);
|
|
386
328
|
|
|
387
329
|
if (agentLines.length > 0) {
|
|
388
330
|
lines.push('');
|
|
389
|
-
lines.push('*🎭 Agents*');
|
|
331
|
+
lines.push('*🎭 AI Agents*');
|
|
390
332
|
lines.push(...agentLines);
|
|
391
333
|
}
|
|
392
334
|
|
|
393
|
-
// ===
|
|
394
|
-
const
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
if (
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
runtimeLines.push(`• PHP: \`${versions.php}\``);
|
|
335
|
+
// === JavaScript/Node.js ===
|
|
336
|
+
const jsLines = [];
|
|
337
|
+
addVersionLine(jsLines, 'Node.js', versions.node);
|
|
338
|
+
addVersionLine(jsLines, 'Bun', versions.bun);
|
|
339
|
+
addVersionLine(jsLines, 'Deno', versions.deno);
|
|
340
|
+
addVersionLine(jsLines, 'NPM', versions.npm);
|
|
341
|
+
addVersionLine(jsLines, 'NVM', versions.nvm);
|
|
342
|
+
|
|
343
|
+
if (jsLines.length > 0) {
|
|
344
|
+
lines.push('');
|
|
345
|
+
lines.push('*📦 JavaScript/Node.js*');
|
|
346
|
+
lines.push(...jsLines);
|
|
406
347
|
}
|
|
407
|
-
|
|
408
|
-
|
|
348
|
+
|
|
349
|
+
// === Python ===
|
|
350
|
+
const pythonLines = [];
|
|
351
|
+
addVersionLine(pythonLines, 'Python', versions.python);
|
|
352
|
+
addVersionLine(pythonLines, 'Pyenv', versions.pyenv);
|
|
353
|
+
|
|
354
|
+
if (pythonLines.length > 0) {
|
|
355
|
+
lines.push('');
|
|
356
|
+
lines.push('*🐍 Python*');
|
|
357
|
+
lines.push(...pythonLines);
|
|
409
358
|
}
|
|
410
|
-
|
|
411
|
-
|
|
359
|
+
|
|
360
|
+
// === Rust ===
|
|
361
|
+
const rustLines = [];
|
|
362
|
+
addVersionLine(rustLines, 'Rustc', versions.rust);
|
|
363
|
+
addVersionLine(rustLines, 'Cargo', versions.cargo);
|
|
364
|
+
|
|
365
|
+
if (rustLines.length > 0) {
|
|
366
|
+
lines.push('');
|
|
367
|
+
lines.push('*🦀 Rust*');
|
|
368
|
+
lines.push(...rustLines);
|
|
412
369
|
}
|
|
413
|
-
|
|
414
|
-
|
|
370
|
+
|
|
371
|
+
// === Java ===
|
|
372
|
+
const javaLines = [];
|
|
373
|
+
addVersionLine(javaLines, 'Java', versions.java);
|
|
374
|
+
addVersionLine(javaLines, 'SDKMAN', versions.sdkman);
|
|
375
|
+
|
|
376
|
+
if (javaLines.length > 0) {
|
|
377
|
+
lines.push('');
|
|
378
|
+
lines.push('*☕ Java*');
|
|
379
|
+
lines.push(...javaLines);
|
|
415
380
|
}
|
|
381
|
+
|
|
382
|
+
// === Go ===
|
|
416
383
|
if (versions.go) {
|
|
417
|
-
|
|
384
|
+
lines.push('');
|
|
385
|
+
lines.push('*🔷 Go*');
|
|
386
|
+
addVersionLine(lines, 'Go', versions.go);
|
|
418
387
|
}
|
|
419
|
-
|
|
420
|
-
|
|
388
|
+
|
|
389
|
+
// === PHP ===
|
|
390
|
+
if (versions.php) {
|
|
391
|
+
lines.push('');
|
|
392
|
+
lines.push('*🐘 PHP*');
|
|
393
|
+
addVersionLine(lines, 'PHP', versions.php);
|
|
421
394
|
}
|
|
422
|
-
|
|
423
|
-
|
|
395
|
+
|
|
396
|
+
// === .NET ===
|
|
397
|
+
if (versions.dotnet) {
|
|
398
|
+
lines.push('');
|
|
399
|
+
lines.push('*📦 .NET*');
|
|
400
|
+
addVersionLine(lines, '.NET SDK', versions.dotnet);
|
|
424
401
|
}
|
|
425
|
-
|
|
426
|
-
|
|
402
|
+
|
|
403
|
+
// === Perl ===
|
|
404
|
+
const perlLines = [];
|
|
405
|
+
addVersionLine(perlLines, 'Perl', versions.perl);
|
|
406
|
+
addVersionLine(perlLines, 'Perlbrew', versions.perlbrew);
|
|
407
|
+
|
|
408
|
+
if (perlLines.length > 0) {
|
|
409
|
+
lines.push('');
|
|
410
|
+
lines.push('*💎 Perl*');
|
|
411
|
+
lines.push(...perlLines);
|
|
427
412
|
}
|
|
428
|
-
|
|
429
|
-
|
|
413
|
+
|
|
414
|
+
// === OCaml/Rocq ===
|
|
415
|
+
const ocamlLines = [];
|
|
416
|
+
addVersionLine(ocamlLines, 'OCaml', versions.ocaml);
|
|
417
|
+
addVersionLine(ocamlLines, 'Opam', versions.opam);
|
|
418
|
+
addVersionLine(ocamlLines, 'Rocq/Coq', versions.rocq);
|
|
419
|
+
|
|
420
|
+
if (ocamlLines.length > 0) {
|
|
421
|
+
lines.push('');
|
|
422
|
+
lines.push('*🐫 OCaml/Rocq*');
|
|
423
|
+
lines.push(...ocamlLines);
|
|
430
424
|
}
|
|
431
|
-
|
|
432
|
-
|
|
425
|
+
|
|
426
|
+
// === Lean ===
|
|
427
|
+
const leanLines = [];
|
|
428
|
+
addVersionLine(leanLines, 'Lean', versions.lean);
|
|
429
|
+
addVersionLine(leanLines, 'Elan', versions.elan);
|
|
430
|
+
addVersionLine(leanLines, 'Lake', versions.lake);
|
|
431
|
+
|
|
432
|
+
if (leanLines.length > 0) {
|
|
433
|
+
lines.push('');
|
|
434
|
+
lines.push('*📐 Lean*');
|
|
435
|
+
lines.push(...leanLines);
|
|
433
436
|
}
|
|
434
437
|
|
|
435
|
-
|
|
438
|
+
// === C/C++ ===
|
|
439
|
+
const cppLines = [];
|
|
440
|
+
addVersionLine(cppLines, 'GCC', versions.gcc);
|
|
441
|
+
addVersionLine(cppLines, 'G++', versions.gpp);
|
|
442
|
+
addVersionLine(cppLines, 'Clang', versions.clang);
|
|
443
|
+
addVersionLine(cppLines, 'LLVM', versions.llvm);
|
|
444
|
+
addVersionLine(cppLines, 'LLD', versions.lld);
|
|
445
|
+
addVersionLine(cppLines, 'Make', versions.make);
|
|
446
|
+
addVersionLine(cppLines, 'CMake', versions.cmake);
|
|
447
|
+
|
|
448
|
+
if (cppLines.length > 0) {
|
|
436
449
|
lines.push('');
|
|
437
|
-
lines.push('
|
|
438
|
-
lines.push(...
|
|
450
|
+
lines.push('*🔨 C/C++*');
|
|
451
|
+
lines.push(...cppLines);
|
|
439
452
|
}
|
|
440
453
|
|
|
441
454
|
// === Development Tools ===
|
|
442
455
|
const toolLines = [];
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
}
|
|
449
|
-
if (versions.npm) {
|
|
450
|
-
toolLines.push(`• NPM: \`${versions.npm}\``);
|
|
451
|
-
}
|
|
452
|
-
if (versions.nvm) {
|
|
453
|
-
toolLines.push(`• NVM: \`${versions.nvm}\``);
|
|
454
|
-
}
|
|
455
|
-
if (versions.pyenv) {
|
|
456
|
-
toolLines.push(`• Pyenv: \`${versions.pyenv}\``);
|
|
457
|
-
}
|
|
458
|
-
if (versions.cargo) {
|
|
459
|
-
toolLines.push(`• Cargo: \`${versions.cargo}\``);
|
|
460
|
-
}
|
|
461
|
-
if (versions.brew) {
|
|
462
|
-
toolLines.push(`• Homebrew: \`${versions.brew}\``);
|
|
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
|
-
}
|
|
456
|
+
addVersionLine(toolLines, 'Git', versions.git);
|
|
457
|
+
addVersionLine(toolLines, 'GitHub CLI', versions.gh);
|
|
458
|
+
addVersionLine(toolLines, 'Playwright', versions.playwright);
|
|
459
|
+
addVersionLine(toolLines, 'Playwright MCP', versions.playwrightMcp);
|
|
460
|
+
addVersionLine(toolLines, 'Homebrew', versions.brew);
|
|
479
461
|
|
|
480
462
|
if (toolLines.length > 0) {
|
|
481
463
|
lines.push('');
|
|
@@ -483,36 +465,6 @@ export function formatVersionMessage(versions) {
|
|
|
483
465
|
lines.push(...toolLines);
|
|
484
466
|
}
|
|
485
467
|
|
|
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
|
-
|
|
516
468
|
// === Platform ===
|
|
517
469
|
if (versions.platform) {
|
|
518
470
|
lines.push('');
|