pi-lens 3.6.5 → 3.6.7
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 +87 -0
- package/README.md +40 -10
- package/clients/dispatch/runners/similarity.ts +100 -1
- package/clients/installer/index.ts +26 -20
- package/clients/lsp/client.ts +249 -110
- package/clients/native-rust-client.ts +531 -0
- package/commands/booboo.ts +2 -2
- package/index.ts +0 -8
- package/package.json +14 -2
- package/rust/Cargo.toml +34 -0
- package/rust/src/cache.rs +127 -0
- package/rust/src/index.rs +407 -0
- package/rust/src/lib.rs +209 -0
- package/rust/src/main.rs +24 -0
- package/rust/src/scan.rs +116 -0
- package/rust/src/similarity.rs +387 -0
- package/skills/ast-grep/SKILL.md +16 -4
- package/clients/interviewer-templates.ts +0 -90
- package/clients/interviewer.ts +0 -287
- package/clients/safe-spawn-async.ts +0 -220
- package/commands/fix-from-booboo.ts +0 -485
- package/commands/fix-simplified.ts +0 -768
- package/commands/rate.ts +0 -341
- package/commands/refactor.ts +0 -203
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,93 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to pi-lens will be documented in this file.
|
|
4
4
|
|
|
5
|
+
## [3.6.7] - 2026-04-04
|
|
6
|
+
|
|
7
|
+
### Fixed
|
|
8
|
+
- **LSP `ERR_STREAM_DESTROYED` crash** — When an LSP process (e.g. rust-analyzer) exits, Node.js emits
|
|
9
|
+
`'error'` events on the destroyed stdio streams. Without listeners these became uncaught exceptions
|
|
10
|
+
that crashed the extension. Added persistent `error` listeners to `stdin`, `stdout`, and `stderr`
|
|
11
|
+
before handing them to `vscode-jsonrpc`, covering the post-`connection.dispose()` window.
|
|
12
|
+
Same guard added to `NativeRustCoreClient` stdin writes.
|
|
13
|
+
|
|
14
|
+
### Added
|
|
15
|
+
- **Rust performance core (`pi-lens-core`)** — Optional Rust binary for CPU-intensive operations.
|
|
16
|
+
All features fall back to TypeScript automatically if the binary is not available (it is **not**
|
|
17
|
+
built automatically on `npm install` — run `npm run rust:build` once if you have Rust installed).
|
|
18
|
+
- **File scanning** — ripgrep’s `ignore` crate for `.gitignore`-aware project scanning
|
|
19
|
+
- **Similarity detection** — parallel 57×72 state-matrix index, persisted to
|
|
20
|
+
`.pi-lens/rust-index.json` between invocations (fixes in-memory cache that reset on every
|
|
21
|
+
process spawn)
|
|
22
|
+
- **Tree-sitter queries** — TypeScript and Rust AST queries via the binary
|
|
23
|
+
- **`NativeRustCoreClient`** — TypeScript wrapper with `isBinaryStale()` freshness detection,
|
|
24
|
+
JSON-IPC over stdin/stdout
|
|
25
|
+
- **Integration tests** — `npm run rust:test:integration` (37 assertions across all commands)
|
|
26
|
+
|
|
27
|
+
- **Rust similarity fast-path in dispatch runner** — `similarity.ts` now tries the Rust binary
|
|
28
|
+
first (scan → build index → query), falls through to the TypeScript implementation on any
|
|
29
|
+
failure. Feature flag `USE_RUST = true` at top of file.
|
|
30
|
+
|
|
31
|
+
### Changed
|
|
32
|
+
- **Similarity threshold raised from 0.75 → 0.90** — Empirical evaluation showed that below 0.90
|
|
33
|
+
false positives (structurally similar but semantically unrelated functions) outnumber true
|
|
34
|
+
positives with the current 57×72 matrix resolution. Applies to both the dispatch runner and
|
|
35
|
+
`/lens-booboo`.
|
|
36
|
+
|
|
37
|
+
- **Rust `kind_id` mapping improved** — Replaced `kind % dim` modulo (caused up to 4 unrelated
|
|
38
|
+
node types to share one matrix slot) with even-distribution across named slots plus a dedicated
|
|
39
|
+
last slot for anonymous punctuation tokens. Max named-slot collisions reduced from 4 to 3;
|
|
40
|
+
unnamed tokens no longer pollute named slots.
|
|
41
|
+
|
|
42
|
+
### Fixed (Rust)
|
|
43
|
+
- `tree_sitter_rust::language_rust()` → `language()` (correct API for tree-sitter-rust 0.21)
|
|
44
|
+
- `FunctionInfo` missing `#[derive(Clone)]` — caused compile error in `find_similar_to`
|
|
45
|
+
- `export function foo()` was missed by the index builder — TypeScript wraps exported functions
|
|
46
|
+
in `export_statement`; replaced flat top-level walk with recursive `collect_functions()`
|
|
47
|
+
- `find_similar_to` returned only the first function in a file — changed `find` to `filter`
|
|
48
|
+
- `tempfile` moved from `[dependencies]` to `[dev-dependencies]`
|
|
49
|
+
- Deleted orphan `test_lsp.rs` (intentional type errors caused rust-analyzer to crash the LSP stream)
|
|
50
|
+
|
|
51
|
+
### Repository
|
|
52
|
+
- Rust source (`rust/src/`, `rust/Cargo.toml`) added to npm `files` whitelist so users can build
|
|
53
|
+
the binary from an npm-installed package
|
|
54
|
+
- Removed stale `src/main.rs` rule from root `.gitignore` (no such file at repo root)
|
|
55
|
+
- Untracked `docs/plans/2025-04-03-auto-install-logging.md` (committed before `*.md` exclusion rule)
|
|
56
|
+
|
|
57
|
+
---
|
|
58
|
+
|
|
59
|
+
## [3.6.3] - 2026-04-03
|
|
60
|
+
|
|
61
|
+
### Removed (Dead Code Cleanup)
|
|
62
|
+
- **Deleted unused interviewer tool** — Browser-based interview with diff confirmation was never used:
|
|
63
|
+
- Removed `clients/interviewer.ts` (290 lines)
|
|
64
|
+
- Removed `clients/interviewer-templates.ts` (240 lines)
|
|
65
|
+
- Removed initialization from `index.ts`
|
|
66
|
+
|
|
67
|
+
- **Deleted deprecated commands** — All were superseded by `/lens-booboo`:
|
|
68
|
+
- `/lens-booboo-fix` command (fix-from-booboo.ts, 430 lines) — showed warning to use `/lens-booboo`
|
|
69
|
+
- `/lens-fix-simplified` command (fix-simplified.ts, 770 lines) — never registered, unused
|
|
70
|
+
- `/lens-rate` command (rate.ts, 340 lines) — showed warning to use `/lens-booboo`
|
|
71
|
+
- `/lens-booboo-refactor` command (refactor.ts, 207 lines) — depended on removed interviewer tool
|
|
72
|
+
|
|
73
|
+
- **Deleted duplicate safe-spawn module**:
|
|
74
|
+
- Removed `clients/safe-spawn-async.ts` (220 lines) — 100% duplicate of functions in `safe-spawn.ts`
|
|
75
|
+
- All imports already used `safe-spawn.ts`, making `safe-spawn-async.ts` pure dead code
|
|
76
|
+
|
|
77
|
+
### Test Suite Overhaul
|
|
78
|
+
- **Removed ~85 wasteful/broken test files**:
|
|
79
|
+
- "Is tool available" tests (8 files) — just checked if external CLIs installed
|
|
80
|
+
- Heavy integration tests (2 files) — 5s timeouts, full codebase scans
|
|
81
|
+
- Broken LSP tests (7 files) — import path errors
|
|
82
|
+
- Broken runner tests (7 files) — thin CLI wrappers with wrong imports
|
|
83
|
+
- Trivial utility tests (5 files) — file extension parsing, string sanitization
|
|
84
|
+
|
|
85
|
+
- **Added meaningful integration tests**:
|
|
86
|
+
- `tests/clients/dispatch/dispatcher-flow.test.ts` — Runner registration, execution, delta mode, conditional runners
|
|
87
|
+
- `tests/extension-hooks.test.ts` — pi API: tool/command/flag registration, event handlers
|
|
88
|
+
- `tests/mocks/runner-factory.ts` — Mock runners for testing without real CLI tools
|
|
89
|
+
|
|
90
|
+
- **Results:** 22 tests passing in 1.2s (was 104 tests in ~18s with 48 failures)
|
|
91
|
+
|
|
5
92
|
## [3.6.2] - 2026-04-02
|
|
6
93
|
|
|
7
94
|
### Added
|
package/README.md
CHANGED
|
@@ -128,7 +128,7 @@ Enable full Language Server Protocol support with `--lens-lsp`:
|
|
|
128
128
|
| **Config** | YAML, JSON, Prisma |
|
|
129
129
|
| **Web** | Vue, Svelte, CSS/SCSS/Sass/Less |
|
|
130
130
|
|
|
131
|
-
**Auto-installation (8 tools):** TypeScript, Python, Biome, Ruff, and analysis tools (Madge, jscpd, ast-grep, Knip) auto-install on first use to `.pi-lens/tools/`. Other LSP servers are launched via `npx` when available
|
|
131
|
+
**Auto-installation (8 tools):** TypeScript, Python, Biome, Ruff, and analysis tools (Madge, jscpd, ast-grep, Knip) auto-install on first use to `.pi-lens/tools/`. Other LSP servers require manual installation or are launched via `npx` when available.
|
|
132
132
|
|
|
133
133
|
**Usage:**
|
|
134
134
|
```bash
|
|
@@ -196,7 +196,7 @@ pi-lens uses a **dispatcher-runner architecture** for extensible multi-language
|
|
|
196
196
|
| **shellcheck** | Shell | 20 | Warning | Bash/sh/zsh/fish linting |
|
|
197
197
|
| **python-slop** | Python | 25 | Warning | AI slop detection (~40 patterns) |
|
|
198
198
|
| **spellcheck** | Markdown | 30 | Warning | Typo detection in docs |
|
|
199
|
-
| **similarity** | TS | 35 | Warning | Semantic duplicate detection (structural similarity) |
|
|
199
|
+
| **similarity** | TS | 35 | Warning | Semantic duplicate detection (≥90% structural similarity, Rust-accelerated when available) |
|
|
200
200
|
| **architect** | All | 40 | Warning | Architectural rule violations |
|
|
201
201
|
| **go-vet** | Go | 50 | Warning | Go static analysis |
|
|
202
202
|
| **rust-clippy** | Rust | 50 | Warning | Rust linting |
|
|
@@ -327,7 +327,7 @@ Full codebase analysis with **10 tracked runners** producing a comprehensive rep
|
|
|
327
327
|
|---|--------|---------------|
|
|
328
328
|
| 1 | **ast-grep (design smells)** | Structural issues (empty catch, no-debugger, etc.) |
|
|
329
329
|
| 2 | **ast-grep (similar functions)** | Duplicate function patterns across files |
|
|
330
|
-
| 3 | **semantic similarity (Amain)** | 57×72 matrix semantic clones (
|
|
330
|
+
| 3 | **semantic similarity (Amain)** | 57×72 matrix semantic clones (≥90% similarity) |
|
|
331
331
|
| 4 | **complexity metrics** | Low MI, high cognitive complexity, AI slop indicators |
|
|
332
332
|
| 5 | **TODO scanner** | TODO/FIXME annotations and tech debt markers |
|
|
333
333
|
| 6 | **dead code (Knip)** | Unused exports, files, dependencies |
|
|
@@ -501,6 +501,9 @@ pi-lens/
|
|
|
501
501
|
├── commands/ # /lens-booboo, /lens-format commands
|
|
502
502
|
├── docs/ # Documentation
|
|
503
503
|
├── rules/ # AST-grep rules
|
|
504
|
+
├── rust/ # Optional Rust core for performance acceleration
|
|
505
|
+
│ ├── src/ # Rust source (pi-lens-core binary)
|
|
506
|
+
│ └── Cargo.toml
|
|
504
507
|
├── skills/ # Built-in pi skills
|
|
505
508
|
├── index.ts # Main extension entry point
|
|
506
509
|
└── package.json
|
|
@@ -510,6 +513,40 @@ See source for detailed structure.
|
|
|
510
513
|
|
|
511
514
|
---
|
|
512
515
|
|
|
516
|
+
## Rust Core (Optional)
|
|
517
|
+
|
|
518
|
+
pi-lens includes a **Rust performance core** (`pi-lens-core`) for CPU-intensive operations. It is entirely optional — all features fall back to the TypeScript implementation automatically if the binary is not available.
|
|
519
|
+
|
|
520
|
+
**What it accelerates:**
|
|
521
|
+
- **File scanning** — Uses ripgrep's `ignore` crate for fast, `.gitignore`-aware project scanning (~10× faster than glob)
|
|
522
|
+
- **Similarity detection** — Parallel 57×72 state-matrix computation and index querying
|
|
523
|
+
- **Tree-sitter queries** — Runs TypeScript and Rust AST queries directly from the binary
|
|
524
|
+
|
|
525
|
+
**Status:** Does not work out of the box after `npm install`. The source is included in the package so you can build it yourself if you have Rust installed.
|
|
526
|
+
|
|
527
|
+
**Build the binary (one-time):**
|
|
528
|
+
```bash
|
|
529
|
+
# Requires Rust toolchain — https://rustup.rs
|
|
530
|
+
npm run rust:build # release build (recommended)
|
|
531
|
+
npm run rust:build:debug # debug build
|
|
532
|
+
```
|
|
533
|
+
|
|
534
|
+
Once built, pi-lens will automatically use the Rust binary and fall back to TypeScript if it is absent, outdated, or fails.
|
|
535
|
+
|
|
536
|
+
**Verify the binary is being used:**
|
|
537
|
+
```bash
|
|
538
|
+
node -e "import('./clients/native-rust-client.js').then(m => console.log('available:', m.getNativeRustCoreClient(true).isAvailable()))"
|
|
539
|
+
```
|
|
540
|
+
|
|
541
|
+
**Run integration tests** (requires debug binary):
|
|
542
|
+
```bash
|
|
543
|
+
npm run rust:build:debug
|
|
544
|
+
npm run rust:test:integration # 37 assertions
|
|
545
|
+
npm run rust:test # Rust unit tests
|
|
546
|
+
```
|
|
547
|
+
|
|
548
|
+
---
|
|
549
|
+
|
|
513
550
|
## Skills
|
|
514
551
|
|
|
515
552
|
pi-lens includes two built-in skills that guide the LLM on when to use specific tools:
|
|
@@ -575,13 +612,6 @@ pattern: "TODO" // Use grep instead
|
|
|
575
612
|
|
|
576
613
|
See [CHANGELOG.md](CHANGELOG.md) for full history.
|
|
577
614
|
|
|
578
|
-
### Latest Highlights
|
|
579
|
-
|
|
580
|
-
- **Tree-sitter Query Cache:** Compiled query cache with mtime-based invalidation — 10× faster structural analysis startup
|
|
581
|
-
- **LSP Support:** 31 Language Server Protocol clients (4 core auto-installed, others via npx or manual)
|
|
582
|
-
- **NAPI Runner:** 100x faster TypeScript/JavaScript structural analysis (~9ms vs ~1200ms) — security rules fire inline
|
|
583
|
-
- **Slop Detection:** 33+ TypeScript and 40+ Python patterns for AI-generated code quality issues
|
|
584
|
-
|
|
585
615
|
---
|
|
586
616
|
|
|
587
617
|
## License
|
|
@@ -9,6 +9,7 @@ import * as fs from "node:fs/promises";
|
|
|
9
9
|
import * as path from "node:path";
|
|
10
10
|
import * as ts from "typescript";
|
|
11
11
|
import { EXCLUDED_DIRS } from "../../file-utils.js";
|
|
12
|
+
import { NativeRustCoreClient } from "../../native-rust-client.js";
|
|
12
13
|
import {
|
|
13
14
|
buildProjectIndex,
|
|
14
15
|
findSimilarFunctions,
|
|
@@ -23,12 +24,18 @@ import type {
|
|
|
23
24
|
RunnerResult,
|
|
24
25
|
} from "../types.js";
|
|
25
26
|
|
|
27
|
+
// Singleton Rust client — initialised once, reused across runner invocations.
|
|
28
|
+
const rustClient = new NativeRustCoreClient();
|
|
29
|
+
|
|
30
|
+
/** Feature flag: set to false to force the pure-TypeScript path. */
|
|
31
|
+
const USE_RUST = true;
|
|
32
|
+
|
|
26
33
|
// ============================================================================
|
|
27
34
|
// Configuration
|
|
28
35
|
// ============================================================================
|
|
29
36
|
|
|
30
37
|
const CONFIG = {
|
|
31
|
-
SIMILARITY_THRESHOLD: 0.
|
|
38
|
+
SIMILARITY_THRESHOLD: 0.9, // 90% minimum similarity — below this false positives dominate
|
|
32
39
|
MIN_TRANSITIONS: 20, // Skip functions with <20 AST transitions
|
|
33
40
|
MAX_SUGGESTIONS: 3, // Max 3 suggestions per file
|
|
34
41
|
USAGE_THRESHOLD: 2, // Only suggest utilities with 2+ uses (placeholder)
|
|
@@ -64,6 +71,24 @@ const similarityRunner: RunnerDefinition = {
|
|
|
64
71
|
return { status: "skipped", diagnostics: [], semantic: "none" };
|
|
65
72
|
}
|
|
66
73
|
|
|
74
|
+
// ── Rust fast-path ─────────────────────────────────────────────────────
|
|
75
|
+
// Try Rust for file scanning + similarity detection. If the Rust binary
|
|
76
|
+
// is available, use it. On any failure, fall through to the pure-TS path.
|
|
77
|
+
if (USE_RUST && rustClient.isAvailable()) {
|
|
78
|
+
try {
|
|
79
|
+
const rustResult = await runWithRust(
|
|
80
|
+
filePath,
|
|
81
|
+
projectRoot,
|
|
82
|
+
CONFIG.SIMILARITY_THRESHOLD,
|
|
83
|
+
CONFIG.MAX_SUGGESTIONS,
|
|
84
|
+
);
|
|
85
|
+
if (rustResult !== null) return rustResult;
|
|
86
|
+
} catch {
|
|
87
|
+
// Fall through to TypeScript implementation.
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
// ── TypeScript fallback ─────────────────────────────────────────────────
|
|
91
|
+
|
|
67
92
|
const index = await loadOrBuildIndex(projectRoot);
|
|
68
93
|
if (!index || index.entries.size === 0) {
|
|
69
94
|
return { status: "skipped", diagnostics: [], semantic: "none" };
|
|
@@ -261,6 +286,80 @@ function buildSuggestionMessage(
|
|
|
261
286
|
return `Function '${func.name}' has ${similarityPct}% similarity to existing utility '${name}()' in ${location}. Consider reusing the existing utility.`;
|
|
262
287
|
}
|
|
263
288
|
|
|
289
|
+
// ============================================================================
|
|
290
|
+
// Rust fast-path
|
|
291
|
+
// ============================================================================
|
|
292
|
+
|
|
293
|
+
/**
|
|
294
|
+
* Run similarity detection via the Rust binary.
|
|
295
|
+
*
|
|
296
|
+
* Flow:
|
|
297
|
+
* 1. Scan project files with Rust (respects .gitignore, much faster than glob).
|
|
298
|
+
* 2. Build the Rust index (persisted to .pi-lens/rust-index.json).
|
|
299
|
+
* 3. Query similarity for the current file.
|
|
300
|
+
* 4. Convert matches to Diagnostics.
|
|
301
|
+
*
|
|
302
|
+
* Returns `null` if the Rust path cannot produce results (no matches is still
|
|
303
|
+
* a valid result — returned as an empty-diagnostic RunnerResult).
|
|
304
|
+
*/
|
|
305
|
+
async function runWithRust(
|
|
306
|
+
filePath: string,
|
|
307
|
+
projectRoot: string,
|
|
308
|
+
threshold: number,
|
|
309
|
+
maxSuggestions: number,
|
|
310
|
+
): Promise<RunnerResult | null> {
|
|
311
|
+
// 1. Scan project files.
|
|
312
|
+
const scanned = await rustClient.scanProject(projectRoot, [".ts", ".tsx"]);
|
|
313
|
+
if (scanned.length === 0) return null;
|
|
314
|
+
|
|
315
|
+
const relativeFiles = scanned.map((e) =>
|
|
316
|
+
path.relative(projectRoot, e.path).replace(/\\/g, "/"),
|
|
317
|
+
);
|
|
318
|
+
|
|
319
|
+
// 2. Build index (saves to .pi-lens/rust-index.json).
|
|
320
|
+
await rustClient.buildIndex(projectRoot, relativeFiles);
|
|
321
|
+
|
|
322
|
+
// 3. Find similarities for the current file.
|
|
323
|
+
const matches = await rustClient.findSimilarities(
|
|
324
|
+
projectRoot,
|
|
325
|
+
filePath,
|
|
326
|
+
threshold,
|
|
327
|
+
);
|
|
328
|
+
|
|
329
|
+
if (matches.length === 0) {
|
|
330
|
+
return { status: "succeeded", diagnostics: [], semantic: "none" };
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
// 4. Convert to Diagnostics.
|
|
334
|
+
const diagnostics: Diagnostic[] = matches
|
|
335
|
+
.slice(0, maxSuggestions)
|
|
336
|
+
.map((m) => {
|
|
337
|
+
const similarityPct = Math.round(m.similarity * 100);
|
|
338
|
+
// source_id format: "path/to/file.ts::funcName@line"
|
|
339
|
+
const [srcFile, srcFunc] = m.source_id.split("::");
|
|
340
|
+
const [targetFile, targetFunc] = m.target_id.split("::");
|
|
341
|
+
const funcName = srcFunc?.split("@")[0] ?? "?";
|
|
342
|
+
const targetName = targetFunc?.split("@")[0] ?? "?";
|
|
343
|
+
void srcFile; // file is implicit (it's the current file)
|
|
344
|
+
return {
|
|
345
|
+
id: `similarity-rust-${m.source_id}-${m.target_id}`,
|
|
346
|
+
tool: "similarity",
|
|
347
|
+
filePath,
|
|
348
|
+
line: 1, // Rust gives us the function source_id; line resolution is TODO
|
|
349
|
+
column: 1,
|
|
350
|
+
message: `Function '${funcName}' has ${similarityPct}% similarity to '${targetName}()' in ${targetFile}. Consider reusing the existing utility.`,
|
|
351
|
+
severity: "warning" as const,
|
|
352
|
+
semantic: "warning" as const,
|
|
353
|
+
};
|
|
354
|
+
});
|
|
355
|
+
|
|
356
|
+
return {
|
|
357
|
+
status: "succeeded",
|
|
358
|
+
diagnostics,
|
|
359
|
+
semantic: diagnostics.length > 0 ? "warning" : "none",
|
|
360
|
+
};
|
|
361
|
+
}
|
|
362
|
+
|
|
264
363
|
// ============================================================================
|
|
265
364
|
// Index Management
|
|
266
365
|
// ============================================================================
|
|
@@ -39,6 +39,19 @@ import path from "node:path";
|
|
|
39
39
|
// Global installation directory for pi-lens tools
|
|
40
40
|
const TOOLS_DIR = path.join(process.cwd(), ".pi-lens", "tools");
|
|
41
41
|
|
|
42
|
+
// Debug flag - set via PI_LENS_DEBUG=1 or --debug
|
|
43
|
+
const DEBUG =
|
|
44
|
+
process.env.PI_LENS_DEBUG === "1" || process.argv.includes("--debug");
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Log debug messages only when DEBUG is enabled
|
|
48
|
+
*/
|
|
49
|
+
function debugLog(...args: unknown[]): void {
|
|
50
|
+
if (DEBUG) {
|
|
51
|
+
console.error("[auto-install:debug]", ...args);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
42
55
|
// --- Tool Definitions ---
|
|
43
56
|
|
|
44
57
|
interface ToolDefinition {
|
|
@@ -237,22 +250,18 @@ async function verifyToolBinary(binPath: string): Promise<boolean> {
|
|
|
237
250
|
|
|
238
251
|
proc.on("exit", (code) => {
|
|
239
252
|
if (code === 0) {
|
|
240
|
-
|
|
241
|
-
`[auto-install] Verified: ${binPath} (version: ${stdout.trim()})`,
|
|
242
|
-
);
|
|
253
|
+
debugLog(`Verified: ${binPath} (version: ${stdout.trim()})`);
|
|
243
254
|
resolve(true);
|
|
244
255
|
} else {
|
|
245
|
-
console.error(
|
|
246
|
-
|
|
247
|
-
);
|
|
256
|
+
console.error(`[auto-install] Verification failed for ${binPath}`);
|
|
257
|
+
debugLog("Exit code:", code, "stderr:", stderr);
|
|
248
258
|
resolve(false);
|
|
249
259
|
}
|
|
250
260
|
});
|
|
251
261
|
|
|
252
262
|
proc.on("error", (err) => {
|
|
253
|
-
console.error(
|
|
254
|
-
|
|
255
|
-
);
|
|
263
|
+
console.error(`[auto-install] Verification failed for ${binPath}`);
|
|
264
|
+
debugLog("Error:", err.message);
|
|
256
265
|
resolve(false);
|
|
257
266
|
});
|
|
258
267
|
});
|
|
@@ -322,11 +331,11 @@ async function installNpmTool(
|
|
|
322
331
|
}
|
|
323
332
|
|
|
324
333
|
// NEW: Verify the binary actually works before returning
|
|
325
|
-
|
|
334
|
+
debugLog(`Verifying ${binaryName}...`);
|
|
326
335
|
const isValid = await verifyToolBinary(binPath);
|
|
327
336
|
if (!isValid) {
|
|
328
337
|
console.error(
|
|
329
|
-
`[auto-install] ${packageName} installed but verification failed
|
|
338
|
+
`[auto-install] ${packageName} installed but verification failed (binary may be corrupted)`,
|
|
330
339
|
);
|
|
331
340
|
// Clean up the broken installation
|
|
332
341
|
try {
|
|
@@ -357,10 +366,8 @@ async function installNpmTool(
|
|
|
357
366
|
proc.on("error", (err) => reject(err));
|
|
358
367
|
});
|
|
359
368
|
} catch (err) {
|
|
360
|
-
console.error(
|
|
361
|
-
|
|
362
|
-
err,
|
|
363
|
-
);
|
|
369
|
+
console.error(`[auto-install] Failed to install ${packageName}: ${(err as Error).message}`);
|
|
370
|
+
debugLog("Full error:", err);
|
|
364
371
|
return undefined;
|
|
365
372
|
}
|
|
366
373
|
}
|
|
@@ -393,10 +400,8 @@ async function installPipTool(
|
|
|
393
400
|
proc.on("error", (err) => reject(err));
|
|
394
401
|
});
|
|
395
402
|
} catch (err) {
|
|
396
|
-
console.error(
|
|
397
|
-
|
|
398
|
-
err,
|
|
399
|
-
);
|
|
403
|
+
console.error(`[auto-install] Failed to install ${packageName}: ${(err as Error).message}`);
|
|
404
|
+
debugLog("Full error:", err);
|
|
400
405
|
return undefined;
|
|
401
406
|
}
|
|
402
407
|
}
|
|
@@ -434,7 +439,8 @@ export async function installTool(toolId: string): Promise<boolean> {
|
|
|
434
439
|
return false;
|
|
435
440
|
}
|
|
436
441
|
} catch (err) {
|
|
437
|
-
console.error(`[auto-install] Failed to install ${tool.name}
|
|
442
|
+
console.error(`[auto-install] Failed to install ${tool.name}: ${(err as Error).message}`);
|
|
443
|
+
debugLog("Full error:", err);
|
|
438
444
|
return false;
|
|
439
445
|
}
|
|
440
446
|
}
|