pi-lens 3.8.63 → 3.8.64
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 +22 -0
- package/README.md +12 -9
- package/dist/clients/deadline-utils.js +23 -0
- package/dist/clients/installer/index.js +18 -27
- package/dist/clients/log-cleanup.js +36 -13
- package/dist/clients/lsp/client.js +44 -0
- package/dist/clients/lsp/index.js +208 -33
- package/dist/clients/lsp/interactive-install.js +14 -4
- package/dist/clients/lsp/launch.js +29 -100
- package/dist/clients/mcp/review.js +7 -4
- package/dist/clients/package-manager.js +223 -0
- package/dist/clients/pipeline.js +55 -2
- package/dist/clients/project-metadata.js +3 -23
- package/dist/clients/safe-spawn.js +9 -0
- package/dist/clients/tree-sitter-client.js +72 -14
- package/dist/index.js +16 -0
- package/dist/mcp/server.js +4 -2
- package/dist/tools/ast-grep-search.js +10 -6
- package/dist/tools/lens-diagnostics.js +43 -10
- package/dist/tools/lsp-diagnostics.js +23 -4
- package/dist/tools/scan-progress.js +38 -0
- package/grammars/tree-sitter-bash.wasm +0 -0
- package/grammars/tree-sitter-bash.wasm.json +5 -0
- package/grammars/tree-sitter-css.wasm +0 -0
- package/grammars/tree-sitter-css.wasm.json +5 -0
- package/grammars/tree-sitter-go.wasm +0 -0
- package/grammars/tree-sitter-go.wasm.json +5 -0
- package/grammars/tree-sitter-html.wasm +0 -0
- package/grammars/tree-sitter-html.wasm.json +5 -0
- package/grammars/tree-sitter-java.wasm +0 -0
- package/grammars/tree-sitter-java.wasm.json +5 -0
- package/grammars/tree-sitter-javascript.wasm +0 -0
- package/grammars/tree-sitter-javascript.wasm.json +5 -0
- package/grammars/tree-sitter-json.wasm +0 -0
- package/grammars/tree-sitter-json.wasm.json +5 -0
- package/grammars/tree-sitter-python.wasm +0 -0
- package/grammars/tree-sitter-python.wasm.json +5 -0
- package/grammars/tree-sitter-rust.wasm +0 -0
- package/grammars/tree-sitter-rust.wasm.json +5 -0
- package/grammars/tree-sitter-tsx.wasm +0 -0
- package/grammars/tree-sitter-tsx.wasm.json +5 -0
- package/grammars/tree-sitter-typescript.wasm +0 -0
- package/grammars/tree-sitter-typescript.wasm.json +5 -0
- package/grammars/tree-sitter-yaml.wasm +0 -0
- package/grammars/tree-sitter-yaml.wasm.json +5 -0
- package/package.json +7 -5
- package/scripts/analyze-pi-lens-logs.mjs +101 -3
- package/scripts/download-grammars.js +171 -30
- package/scripts/grammars.lock.json +32 -0
|
@@ -1,16 +1,33 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
/**
|
|
3
|
-
* Downloads tree-sitter WASM
|
|
4
|
-
*
|
|
3
|
+
* Downloads tree-sitter WASM grammars, each verified against the committed
|
|
4
|
+
* provenance manifest (`scripts/grammars.lock.json`: package, version, per-grammar
|
|
5
|
+
* sha256) and stamped with a `<grammar>.wasm.json` sidecar. On a version bump or a
|
|
6
|
+
* hash mismatch the stale file is re-downloaded instead of skipped — closing the
|
|
7
|
+
* old skip-if-exists hole where an ABI-mismatched grammar could silently persist
|
|
8
|
+
* against the pinned `web-tree-sitter` (#177).
|
|
5
9
|
*
|
|
6
|
-
*
|
|
10
|
+
* Modes:
|
|
11
|
+
* node download-grammars.js # all grammars → web-tree-sitter/grammars
|
|
12
|
+
* node download-grammars.js --core --dest grammars # core set → ./grammars (used by `prepare`)
|
|
13
|
+
* node download-grammars.js --write-manifest # regenerate grammars.lock.json from the CDN
|
|
14
|
+
*
|
|
15
|
+
* Source: tree-sitter-wasms on unpkg (mirrors the npm registry artifacts).
|
|
16
|
+
*
|
|
17
|
+
* Progress goes to stderr — stdout must stay clean so `npm pack --silent` (which
|
|
18
|
+
* runs this via `prepare`) captures only the tarball name (#376/#380).
|
|
7
19
|
*/
|
|
8
|
-
import {
|
|
20
|
+
import { createHash } from "node:crypto";
|
|
21
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
9
22
|
import { dirname, join } from "node:path";
|
|
10
|
-
import { fileURLToPath } from "node:url";
|
|
23
|
+
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
24
|
+
// The pinned tree-sitter-wasms release. Bump this, run `--write-manifest`, and
|
|
25
|
+
// commit the regenerated grammars.lock.json to move to a new grammar set.
|
|
11
26
|
const TREE_SITTER_WASMS_VERSION = "0.1.13";
|
|
12
|
-
const
|
|
13
|
-
const
|
|
27
|
+
const PACKAGE = "tree-sitter-wasms";
|
|
28
|
+
const SCRIPT_DIR = dirname(fileURLToPath(import.meta.url));
|
|
29
|
+
const MANIFEST_PATH = join(SCRIPT_DIR, "grammars.lock.json");
|
|
30
|
+
export const GRAMMARS = [
|
|
14
31
|
// Core typed languages
|
|
15
32
|
"tree-sitter-typescript.wasm",
|
|
16
33
|
"tree-sitter-tsx.wasm",
|
|
@@ -40,33 +57,153 @@ const GRAMMARS = [
|
|
|
40
57
|
"tree-sitter-yaml.wasm",
|
|
41
58
|
"tree-sitter-zig.wasm",
|
|
42
59
|
];
|
|
60
|
+
// The core set bundled into the tarball (via `prepare` → `grammars/`, shipped in
|
|
61
|
+
// `files[]`) so the common languages parse offline on every package manager. The
|
|
62
|
+
// long tail stays lazy-fetched at runtime. ~8.6MB uncompressed; ts/tsx dominate.
|
|
63
|
+
export const CORE = [
|
|
64
|
+
"tree-sitter-typescript.wasm",
|
|
65
|
+
"tree-sitter-tsx.wasm",
|
|
66
|
+
"tree-sitter-javascript.wasm",
|
|
67
|
+
"tree-sitter-python.wasm",
|
|
68
|
+
"tree-sitter-go.wasm",
|
|
69
|
+
"tree-sitter-rust.wasm",
|
|
70
|
+
"tree-sitter-json.wasm",
|
|
71
|
+
"tree-sitter-yaml.wasm",
|
|
72
|
+
"tree-sitter-bash.wasm",
|
|
73
|
+
"tree-sitter-html.wasm",
|
|
74
|
+
"tree-sitter-css.wasm",
|
|
75
|
+
"tree-sitter-java.wasm",
|
|
76
|
+
];
|
|
77
|
+
/** `sha256:<hex>` digest of a buffer, matching the manifest/sidecar format. */
|
|
78
|
+
export function sha256(buf) {
|
|
79
|
+
return `sha256:${createHash("sha256").update(buf).digest("hex")}`;
|
|
80
|
+
}
|
|
81
|
+
/** Read the committed provenance manifest (`scripts/grammars.lock.json`). */
|
|
82
|
+
export function loadManifest() {
|
|
83
|
+
return JSON.parse(readFileSync(MANIFEST_PATH, "utf-8"));
|
|
84
|
+
}
|
|
85
|
+
/** Sidecar path for a grammar wasm file: `<grammar>.wasm.json`. */
|
|
86
|
+
export function sidecarPathFor(wasmPath) {
|
|
87
|
+
return `${wasmPath}.json`;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Whether `filename` must be (re)downloaded into `destDir`: true if the grammar
|
|
91
|
+
* or its sidecar is missing, the sidecar's version differs from the manifest, or
|
|
92
|
+
* the sidecar's recorded hash differs from the expected one. Pure and cheap (it
|
|
93
|
+
* trusts the sidecar's recorded hash — the CI provenance guard re-hashes the
|
|
94
|
+
* bytes for the full integrity check).
|
|
95
|
+
*/
|
|
96
|
+
export function needsDownload(destDir, filename, manifest) {
|
|
97
|
+
const wasm = join(destDir, filename);
|
|
98
|
+
const sidecar = sidecarPathFor(wasm);
|
|
99
|
+
if (!existsSync(wasm) || !existsSync(sidecar))
|
|
100
|
+
return true;
|
|
101
|
+
let meta;
|
|
102
|
+
try {
|
|
103
|
+
meta = JSON.parse(readFileSync(sidecar, "utf-8"));
|
|
104
|
+
}
|
|
105
|
+
catch {
|
|
106
|
+
return true;
|
|
107
|
+
}
|
|
108
|
+
if (meta.version !== manifest.version)
|
|
109
|
+
return true;
|
|
110
|
+
const expected = manifest.grammars[filename];
|
|
111
|
+
if (expected && meta.sha256 !== expected)
|
|
112
|
+
return true;
|
|
113
|
+
return false;
|
|
114
|
+
}
|
|
43
115
|
function findGrammarsDir() {
|
|
44
|
-
const
|
|
45
|
-
|
|
46
|
-
// Prefer local node_modules next to this package
|
|
116
|
+
const pkgRoot = dirname(SCRIPT_DIR);
|
|
117
|
+
// Prefer local node_modules next to this package.
|
|
47
118
|
return join(pkgRoot, "node_modules", "web-tree-sitter", "grammars");
|
|
48
119
|
}
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
120
|
+
function baseUrl(version) {
|
|
121
|
+
return `https://unpkg.com/${PACKAGE}@${version}/out`;
|
|
122
|
+
}
|
|
123
|
+
async function fetchGrammar(version, filename) {
|
|
124
|
+
const res = await fetch(`${baseUrl(version)}/${filename}`);
|
|
125
|
+
if (!res.ok)
|
|
126
|
+
throw new Error(`HTTP ${res.status} fetching ${filename}`);
|
|
127
|
+
return Buffer.from(await res.arrayBuffer());
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Download `filename` into `destDir` (if it isn't already verified), checking its
|
|
131
|
+
* bytes against the manifest and writing a provenance sidecar. Throws on an
|
|
132
|
+
* integrity mismatch — a grammar whose bytes don't match the pinned manifest is
|
|
133
|
+
* never written (guards CDN corruption / tampering / ABI drift).
|
|
134
|
+
*/
|
|
135
|
+
async function downloadGrammar(destDir, filename, manifest) {
|
|
136
|
+
if (!needsDownload(destDir, filename, manifest)) {
|
|
137
|
+
console.error(` skip ${filename} (verified)`);
|
|
53
138
|
return;
|
|
54
139
|
}
|
|
55
|
-
const
|
|
56
|
-
const
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
140
|
+
const buf = await fetchGrammar(manifest.version, filename);
|
|
141
|
+
const actual = sha256(buf);
|
|
142
|
+
const expected = manifest.grammars[filename];
|
|
143
|
+
if (expected && actual !== expected) {
|
|
144
|
+
throw new Error(`integrity mismatch for ${filename}: expected ${expected}, got ${actual}`);
|
|
145
|
+
}
|
|
146
|
+
const wasm = join(destDir, filename);
|
|
147
|
+
writeFileSync(wasm, buf);
|
|
148
|
+
const sidecar = {
|
|
149
|
+
npmPackage: manifest.package,
|
|
150
|
+
version: manifest.version,
|
|
151
|
+
sha256: actual,
|
|
152
|
+
};
|
|
153
|
+
writeFileSync(sidecarPathFor(wasm), `${JSON.stringify(sidecar, null, 2)}\n`);
|
|
154
|
+
console.error(` ok ${filename}`);
|
|
155
|
+
}
|
|
156
|
+
function parseArgs(argv) {
|
|
157
|
+
const out = {
|
|
158
|
+
core: false,
|
|
159
|
+
dest: undefined,
|
|
160
|
+
writeManifest: false,
|
|
161
|
+
};
|
|
162
|
+
for (let i = 0; i < argv.length; i++) {
|
|
163
|
+
if (argv[i] === "--core")
|
|
164
|
+
out.core = true;
|
|
165
|
+
else if (argv[i] === "--write-manifest")
|
|
166
|
+
out.writeManifest = true;
|
|
167
|
+
else if (argv[i] === "--dest")
|
|
168
|
+
out.dest = argv[++i];
|
|
169
|
+
}
|
|
170
|
+
return out;
|
|
171
|
+
}
|
|
172
|
+
/** Regenerate grammars.lock.json by fetching every grammar and hashing it. */
|
|
173
|
+
async function regenerateManifest() {
|
|
174
|
+
console.error(`Regenerating manifest from ${PACKAGE}@${TREE_SITTER_WASMS_VERSION} …`);
|
|
175
|
+
const grammars = {};
|
|
176
|
+
for (const g of GRAMMARS) {
|
|
177
|
+
grammars[g] = sha256(await fetchGrammar(TREE_SITTER_WASMS_VERSION, g));
|
|
178
|
+
console.error(` hashed ${g}`);
|
|
179
|
+
}
|
|
180
|
+
const sorted = Object.fromEntries(Object.keys(grammars)
|
|
181
|
+
.sort()
|
|
182
|
+
.map((k) => [k, grammars[k]]));
|
|
183
|
+
const manifest = {
|
|
184
|
+
package: PACKAGE,
|
|
185
|
+
version: TREE_SITTER_WASMS_VERSION,
|
|
186
|
+
grammars: sorted,
|
|
187
|
+
};
|
|
188
|
+
writeFileSync(MANIFEST_PATH, `${JSON.stringify(manifest, null, 2)}\n`);
|
|
189
|
+
console.error(`Wrote ${MANIFEST_PATH} (${GRAMMARS.length} grammars).`);
|
|
62
190
|
}
|
|
63
191
|
async function main() {
|
|
64
|
-
const
|
|
192
|
+
const args = parseArgs(process.argv.slice(2));
|
|
193
|
+
if (args.writeManifest)
|
|
194
|
+
return regenerateManifest();
|
|
195
|
+
const manifest = loadManifest();
|
|
196
|
+
// `--dest` is relative to cwd (used by `prepare` to bundle into `./grammars/`);
|
|
197
|
+
// default is the installed web-tree-sitter/grammars dir.
|
|
198
|
+
const grammarsDir = args.dest
|
|
199
|
+
? join(process.cwd(), args.dest)
|
|
200
|
+
: findGrammarsDir();
|
|
201
|
+
const list = args.core ? CORE : GRAMMARS;
|
|
65
202
|
if (!existsSync(grammarsDir)) {
|
|
66
203
|
mkdirSync(grammarsDir, { recursive: true });
|
|
67
204
|
}
|
|
68
|
-
console.
|
|
69
|
-
const results = await Promise.allSettled(
|
|
205
|
+
console.error(`Downloading ${args.core ? "core" : "all"} tree-sitter grammars (${list.length}) → ${grammarsDir}`);
|
|
206
|
+
const results = await Promise.allSettled(list.map((g) => downloadGrammar(grammarsDir, g, manifest)));
|
|
70
207
|
const failed = results.filter((r) => r.status === "rejected");
|
|
71
208
|
if (failed.length > 0) {
|
|
72
209
|
for (const f of failed) {
|
|
@@ -75,11 +212,15 @@ async function main() {
|
|
|
75
212
|
console.warn(`${failed.length} grammar(s) failed — tree-sitter analysis may be unavailable.`);
|
|
76
213
|
}
|
|
77
214
|
else {
|
|
78
|
-
console.
|
|
215
|
+
console.error("All grammars downloaded successfully.");
|
|
79
216
|
}
|
|
80
217
|
}
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
218
|
+
// Only run when invoked directly (not when imported by the provenance check or
|
|
219
|
+
// tests) — the import guard keeps the exported helpers side-effect-free.
|
|
220
|
+
if (import.meta.url === pathToFileURL(process.argv[1] ?? "").href) {
|
|
221
|
+
main().catch((err) => {
|
|
222
|
+
// Never fail the install — tree-sitter is optional.
|
|
223
|
+
console.warn("Warning: grammar download failed:", err.message);
|
|
224
|
+
process.exit(0);
|
|
225
|
+
});
|
|
226
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
{
|
|
2
|
+
"package": "tree-sitter-wasms",
|
|
3
|
+
"version": "0.1.13",
|
|
4
|
+
"grammars": {
|
|
5
|
+
"tree-sitter-bash.wasm": "sha256:807dcdb1380a59befb112ed8fbd3d3872c7fadaf5903a769282b50973b30696d",
|
|
6
|
+
"tree-sitter-c.wasm": "sha256:056b25072382f72deee2c64ec238ffc4bb8cf42844ef21502c0e70f03a8a0d66",
|
|
7
|
+
"tree-sitter-c_sharp.wasm": "sha256:6266a7e32d68a3459104d994dc848df15d5672b0ea8e86d327274b694f8e6991",
|
|
8
|
+
"tree-sitter-cpp.wasm": "sha256:f6afdf53bfd6de76557bb7edb624a3a3869e14d9a83b78433f93617ecee42527",
|
|
9
|
+
"tree-sitter-css.wasm": "sha256:5fc615467b1b98420ed7517e5bf9e1f88468132dd903d842dfb13714f6a1cb0c",
|
|
10
|
+
"tree-sitter-dart.wasm": "sha256:7f5364e4256cf7e55efd01dd52421ef2663caa8061b82659b7e4bf61064545ec",
|
|
11
|
+
"tree-sitter-elixir.wasm": "sha256:82e91b9759ddca30d8978ebbfa8e347b4451b64c931f9ae62112e6db9b8fac20",
|
|
12
|
+
"tree-sitter-go.wasm": "sha256:9963ca89b616eaf04b08a43bc1fb0f07b85395bec313330851f1f1ead2f755b6",
|
|
13
|
+
"tree-sitter-html.wasm": "sha256:11b3405c1543fb012f5ed7f8ee73125076dce8b168301e1e787e4c717da6b456",
|
|
14
|
+
"tree-sitter-java.wasm": "sha256:637aac4415fb39a211a4f4292d63c66b5ce9c32fa2cd35464af4f681d91b9a1f",
|
|
15
|
+
"tree-sitter-javascript.wasm": "sha256:63812b9e275d26851264734868d27a1656bd44a2ef6eb3e85e6b03728c595ab5",
|
|
16
|
+
"tree-sitter-json.wasm": "sha256:fdb5219abe058369e16897aaa11eecf47ef4f546752c3ddbac339cdd89e1e667",
|
|
17
|
+
"tree-sitter-kotlin.wasm": "sha256:b5cb00c8d06ed0f10f1dbe497205b437809d7e87db1f638721a8cfb30e044449",
|
|
18
|
+
"tree-sitter-lua.wasm": "sha256:75ef809136d610068c5b2135741d89f5df62690a3d55169203351cb7cc85727d",
|
|
19
|
+
"tree-sitter-ocaml.wasm": "sha256:60849b6320ee956233d77b017c65c45660e507d03ae70aa1bd5783458e2e9e18",
|
|
20
|
+
"tree-sitter-php.wasm": "sha256:55bb617b6f01e14bab997861f0b20a2420cf6ba3199ffeb295b9ec398966d8a3",
|
|
21
|
+
"tree-sitter-python.wasm": "sha256:9056d0fb0c337810d019fae350e8167786119da98f0f282aceae7ab89ee8253b",
|
|
22
|
+
"tree-sitter-ruby.wasm": "sha256:93a5022855314cdb45458c7bb026a24a0ebc3a5ff6439e542e881f14dfa13a39",
|
|
23
|
+
"tree-sitter-rust.wasm": "sha256:4409921a70d0aa5bec7d1d7ce809a557a8ee1cf6ace901e3ac6a76e62cfea903",
|
|
24
|
+
"tree-sitter-swift.wasm": "sha256:41c4fdb2249a3aa6d87eed0d383081ff09725c2248b4977043a43825980ffcc7",
|
|
25
|
+
"tree-sitter-toml.wasm": "sha256:7849ac8ce9d10a4684ca189ea8ad3654c20c38acb2d674a014a164398cbd37a2",
|
|
26
|
+
"tree-sitter-tsx.wasm": "sha256:6aa3b2c70e76f5d48eafef1093e9c4de383e13f2fdde2f4e9b98a378f6a8f1b6",
|
|
27
|
+
"tree-sitter-typescript.wasm": "sha256:8515404dceed38e1ed86aa34b09fcf3379fff1b4ff9dd3967bcd6d1eb5ac3d8f",
|
|
28
|
+
"tree-sitter-vue.wasm": "sha256:6244521bb3fb60f34ce5f677f2af81facb2c38691193985ca5fa85e1b6f29250",
|
|
29
|
+
"tree-sitter-yaml.wasm": "sha256:5dea7cfff83d41d8f87fb8e434e1a5b292c0d670bfcdc42cb2af420ef490dde5",
|
|
30
|
+
"tree-sitter-zig.wasm": "sha256:59cc4531aa661e2de4c5bc04e4045b6bdd5d2bfa75045cbda5f673102d140eef"
|
|
31
|
+
}
|
|
32
|
+
}
|