ultra11y 5.40.2 → 5.41.0
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/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/.codex-plugin/plugin.json +1 -1
- package/.opencode/plugins/ultra11y.js +1 -1
- package/dist/playwright.mjs +8 -3
- package/package.json +1 -1
- package/scripts/ultra11y.mjs +800 -420
- package/skills/review-a11y/SKILL.md +1 -1
- package/skills/review-a11y/scripts/ultra11y.mjs +800 -420
- package/skills/ultra11y/SKILL.md +1 -1
- package/skills/ultra11y/scripts/ultra11y.mjs +800 -420
- package/skills/ultra11y/templates/gitlab-ci.yml +1 -1
- package/src/probes.ts +25 -3
- package/src/types.ts +1 -1
- package/src/vendor/codeindex-engine.d.mts +4 -3
- package/src/vendor/codeindex-engine.mjs +718 -346
- package/src/vendor/engine.meta.json +5 -5
package/scripts/ultra11y.mjs
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
// src/cli.ts
|
|
4
|
-
import { realpathSync as
|
|
5
|
-
import { join as join53, relative as relative6, resolve as resolve16, sep as sep7, dirname as
|
|
4
|
+
import { realpathSync as realpathSync7, writeFileSync as writeFileSync21, mkdirSync as mkdirSync18, existsSync as existsSync38, readFileSync as readFileSync34, appendFileSync, copyFileSync as copyFileSync4 } from "fs";
|
|
5
|
+
import { join as join53, relative as relative6, resolve as resolve16, sep as sep7, dirname as dirname17 } from "path";
|
|
6
6
|
import { fileURLToPath as fileURLToPath5, pathToFileURL as pathToFileURL3 } from "url";
|
|
7
7
|
|
|
8
8
|
// src/types.ts
|
|
9
|
-
var VERSION = "5.
|
|
9
|
+
var VERSION = "5.41.0";
|
|
10
10
|
var SCHEMA_VERSION = 2;
|
|
11
11
|
var INAPPLICABLE_STATUS = "C";
|
|
12
12
|
|
|
@@ -19922,7 +19922,7 @@ function opaqueLibrarySpecifiers(ast, elements) {
|
|
|
19922
19922
|
}
|
|
19923
19923
|
|
|
19924
19924
|
// src/glob.ts
|
|
19925
|
-
import { existsSync as existsSync11, statSync as
|
|
19925
|
+
import { existsSync as existsSync11, statSync as statSync10 } from "fs";
|
|
19926
19926
|
import { join as join24, sep as sep3 } from "path";
|
|
19927
19927
|
|
|
19928
19928
|
// src/util.ts
|
|
@@ -19958,13 +19958,18 @@ import { spawnSync } from "child_process";
|
|
|
19958
19958
|
import { readdirSync, statSync, lstatSync, readFileSync as readFileSync2, realpathSync } from "fs";
|
|
19959
19959
|
import { join, sep, extname as extname2 } from "path";
|
|
19960
19960
|
import { createHash } from "crypto";
|
|
19961
|
-
import { readFileSync as readFileSync22, existsSync } from "fs";
|
|
19961
|
+
import { readFileSync as readFileSync22, existsSync, statSync as statSync2 } from "fs";
|
|
19962
19962
|
import { homedir } from "os";
|
|
19963
19963
|
import { dirname, join as join2 } from "path";
|
|
19964
19964
|
import { fileURLToPath } from "url";
|
|
19965
19965
|
import { basename } from "path";
|
|
19966
19966
|
import { readFileSync as readFileSync3 } from "fs";
|
|
19967
19967
|
import { join as join3 } from "path";
|
|
19968
|
+
import { existsSync as existsSync2, statSync as statSync3 } from "fs";
|
|
19969
|
+
import * as os from "os";
|
|
19970
|
+
import { dirname as dirname2, join as join4 } from "path";
|
|
19971
|
+
import { fileURLToPath as fileURLToPath2, pathToFileURL } from "url";
|
|
19972
|
+
import { Worker } from "worker_threads";
|
|
19968
19973
|
import { posix } from "path";
|
|
19969
19974
|
import { join as join7 } from "path";
|
|
19970
19975
|
import { posix as posix2 } from "path";
|
|
@@ -19972,11 +19977,11 @@ import { join as join8 } from "path";
|
|
|
19972
19977
|
import { join as join9 } from "path";
|
|
19973
19978
|
import { join as join10 } from "path";
|
|
19974
19979
|
import { join as join11 } from "path";
|
|
19975
|
-
import { readFileSync as readFileSync6, writeFileSync as writeFileSync2 } from "fs";
|
|
19976
|
-
import { join as join12 } from "path";
|
|
19977
|
-
import { mkdirSync as mkdirSync2, readdirSync as readdirSync2, readFileSync as readFileSync7, rmSync as
|
|
19978
|
-
import { dirname as
|
|
19979
|
-
import { existsSync as existsSync5, readdirSync as readdirSync3, statSync as
|
|
19980
|
+
import { chmodSync, mkdtempSync as mkdtempSync2, readFileSync as readFileSync6, realpathSync as realpathSync2, renameSync as renameSync2, rmSync as rmSync2, statSync as statSync4, writeFileSync as writeFileSync2 } from "fs";
|
|
19981
|
+
import { basename as basename3, dirname as dirname4, join as join12 } from "path";
|
|
19982
|
+
import { mkdirSync as mkdirSync2, readdirSync as readdirSync2, readFileSync as readFileSync7, rmSync as rmSync3, statSync as statSync5, writeFileSync as writeFileSync3 } from "fs";
|
|
19983
|
+
import { dirname as dirname5, join as join13 } from "path";
|
|
19984
|
+
import { existsSync as existsSync5, readdirSync as readdirSync3, statSync as statSync6 } from "fs";
|
|
19980
19985
|
import { join as join14 } from "path";
|
|
19981
19986
|
import { createHash as createHash3 } from "crypto";
|
|
19982
19987
|
import { existsSync as existsSync6, readFileSync as readFileSync8 } from "fs";
|
|
@@ -19991,16 +19996,11 @@ import { spawn } from "child_process";
|
|
|
19991
19996
|
import { existsSync as existsSync9 } from "fs";
|
|
19992
19997
|
import { join as join20 } from "path";
|
|
19993
19998
|
import { pathToFileURL as pathToFileURL2 } from "url";
|
|
19994
|
-
import { statSync as
|
|
19999
|
+
import { statSync as statSync7 } from "fs";
|
|
19995
20000
|
import { join as join21 } from "path";
|
|
19996
|
-
import { readFileSync as readFileSync12 } from "fs";
|
|
20001
|
+
import { readFileSync as readFileSync12, statSync as statSync8, watch as watchFs } from "fs";
|
|
19997
20002
|
import { isAbsolute, join as join22 } from "path";
|
|
19998
20003
|
import { createInterface } from "readline";
|
|
19999
|
-
import { existsSync as existsSync2, statSync as statSync2 } from "fs";
|
|
20000
|
-
import { availableParallelism } from "os";
|
|
20001
|
-
import { dirname as dirname2, join as join4 } from "path";
|
|
20002
|
-
import { fileURLToPath as fileURLToPath2, pathToFileURL } from "url";
|
|
20003
|
-
import { Worker } from "worker_threads";
|
|
20004
20004
|
import { basename as basename2 } from "path";
|
|
20005
20005
|
import { existsSync as existsSync3, readFileSync as readFileSync4 } from "fs";
|
|
20006
20006
|
import { join as join5 } from "path";
|
|
@@ -20009,12 +20009,17 @@ import { existsSync as existsSync4, mkdirSync, mkdtempSync, readFileSync as read
|
|
|
20009
20009
|
import { dirname as dirname3, join as join6, resolve, sep as sep2 } from "path";
|
|
20010
20010
|
import { gunzipSync } from "zlib";
|
|
20011
20011
|
import { join as join15 } from "path";
|
|
20012
|
-
import { existsSync as existsSync10, mkdirSync as mkdirSync3, readFileSync as readFileSync13, writeFileSync as writeFileSync4 } from "fs";
|
|
20012
|
+
import { existsSync as existsSync10, mkdirSync as mkdirSync3, readFileSync as readFileSync13, statSync as statSync9, writeFileSync as writeFileSync4 } from "fs";
|
|
20013
20013
|
import { join as join23, resolve as resolve4 } from "path";
|
|
20014
20014
|
var __defProp = Object.defineProperty;
|
|
20015
20015
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
20016
|
-
var __esm = (fn, res) => function __init() {
|
|
20017
|
-
|
|
20016
|
+
var __esm = (fn, res, err2) => function __init() {
|
|
20017
|
+
if (err2) throw err2[0];
|
|
20018
|
+
try {
|
|
20019
|
+
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
20020
|
+
} catch (e) {
|
|
20021
|
+
throw err2 = [e], e;
|
|
20022
|
+
}
|
|
20018
20023
|
};
|
|
20019
20024
|
var __export = (target, all) => {
|
|
20020
20025
|
for (var name2 in all)
|
|
@@ -20026,9 +20031,9 @@ var EXTRACTOR_VERSION;
|
|
|
20026
20031
|
var init_types = __esm({
|
|
20027
20032
|
"src/types.ts"() {
|
|
20028
20033
|
"use strict";
|
|
20029
|
-
ENGINE_VERSION = "2.28.
|
|
20034
|
+
ENGINE_VERSION = "2.28.1";
|
|
20030
20035
|
SCHEMA_VERSION2 = 5;
|
|
20031
|
-
EXTRACTOR_VERSION =
|
|
20036
|
+
EXTRACTOR_VERSION = 14;
|
|
20032
20037
|
}
|
|
20033
20038
|
});
|
|
20034
20039
|
function sh(cmd, args2, opts = {}) {
|
|
@@ -20354,6 +20359,9 @@ var init_ignore = __esm({
|
|
|
20354
20359
|
init_util();
|
|
20355
20360
|
}
|
|
20356
20361
|
});
|
|
20362
|
+
function isIgnoredDirectory(name2, ignoreDirs) {
|
|
20363
|
+
return ignoreDirs.has(name2) || name2.startsWith(".codeindex-edit-");
|
|
20364
|
+
}
|
|
20357
20365
|
function walk(root, opts = {}) {
|
|
20358
20366
|
const maxFileBytes = opts.maxFileBytes ?? 1024 * 1024;
|
|
20359
20367
|
const maxFiles = opts.maxFiles ?? Infinity;
|
|
@@ -20402,7 +20410,7 @@ function walk(root, opts = {}) {
|
|
|
20402
20410
|
const abs = join(frame.dir, name2);
|
|
20403
20411
|
const rel2 = frame.rel ? `${frame.rel}/${name2}` : name2;
|
|
20404
20412
|
const isLink = entry.isSymbolicLink();
|
|
20405
|
-
if (entry.isDirectory() &&
|
|
20413
|
+
if (entry.isDirectory() && isIgnoredDirectory(name2, ignoreDirs)) continue;
|
|
20406
20414
|
let st;
|
|
20407
20415
|
try {
|
|
20408
20416
|
st = isLink ? statSync(abs) : lstatSync(abs);
|
|
@@ -20410,7 +20418,7 @@ function walk(root, opts = {}) {
|
|
|
20410
20418
|
continue;
|
|
20411
20419
|
}
|
|
20412
20420
|
if (st.isDirectory()) {
|
|
20413
|
-
if (
|
|
20421
|
+
if (isIgnoredDirectory(name2, ignoreDirs)) continue;
|
|
20414
20422
|
if (isLink) continue;
|
|
20415
20423
|
if (useGitignore && rules.length && isIgnored(rules, rel2, true)) continue;
|
|
20416
20424
|
stack.push({ dir: abs, rel: rel2, rules });
|
|
@@ -25823,16 +25831,26 @@ async function ensureGrammars(keys) {
|
|
|
25823
25831
|
parser = new Parser3();
|
|
25824
25832
|
}
|
|
25825
25833
|
for (const key2 of new Set(keys)) {
|
|
25826
|
-
if (loaded.has(key2)
|
|
25834
|
+
if (loaded.has(key2)) continue;
|
|
25827
25835
|
const wasm = firstIn(`${key2}.wasm`);
|
|
25836
|
+
const fingerprint = wasm ? (() => {
|
|
25837
|
+
try {
|
|
25838
|
+
const st = statSync2(wasm);
|
|
25839
|
+
return `${wasm}:${st.size}:${st.mtimeMs}`;
|
|
25840
|
+
} catch {
|
|
25841
|
+
return `${wasm}:unreadable`;
|
|
25842
|
+
}
|
|
25843
|
+
})() : `missing:${dirs.join("|")}`;
|
|
25844
|
+
if (failed.get(key2) === fingerprint) continue;
|
|
25828
25845
|
if (!wasm) {
|
|
25829
|
-
failed.
|
|
25846
|
+
failed.set(key2, fingerprint);
|
|
25830
25847
|
continue;
|
|
25831
25848
|
}
|
|
25832
25849
|
try {
|
|
25833
25850
|
loaded.set(key2, await Language.load(new Uint8Array(readFileSync22(wasm))));
|
|
25851
|
+
failed.delete(key2);
|
|
25834
25852
|
} catch {
|
|
25835
|
-
failed.
|
|
25853
|
+
failed.set(key2, fingerprint);
|
|
25836
25854
|
}
|
|
25837
25855
|
}
|
|
25838
25856
|
}
|
|
@@ -25935,7 +25953,7 @@ var init_loader = __esm({
|
|
|
25935
25953
|
runtimeReady = false;
|
|
25936
25954
|
parser = null;
|
|
25937
25955
|
loaded = /* @__PURE__ */ new Map();
|
|
25938
|
-
failed = /* @__PURE__ */ new
|
|
25956
|
+
failed = /* @__PURE__ */ new Map();
|
|
25939
25957
|
}
|
|
25940
25958
|
});
|
|
25941
25959
|
function findFirst(node, pred) {
|
|
@@ -28176,6 +28194,7 @@ function buildCodeRecord(rel2, ext2, size, content, hash, lang, opts = {}) {
|
|
|
28176
28194
|
record.truncated = code2.truncated;
|
|
28177
28195
|
record.relations = code2.relations;
|
|
28178
28196
|
record.terms = code2.terms;
|
|
28197
|
+
record.literals = code2.literals;
|
|
28179
28198
|
} else {
|
|
28180
28199
|
record.title = basename(rel2);
|
|
28181
28200
|
}
|
|
@@ -28254,7 +28273,7 @@ function scanRepo(root, opts = {}) {
|
|
|
28254
28273
|
files.push(preUsable.record);
|
|
28255
28274
|
continue;
|
|
28256
28275
|
}
|
|
28257
|
-
const record = {
|
|
28276
|
+
const record = kind === "code" ? buildCodeRecord(f.rel, f.ext, f.size, content, hash, lang, opts) : {
|
|
28258
28277
|
rel: f.rel,
|
|
28259
28278
|
ext: f.ext,
|
|
28260
28279
|
size: f.size,
|
|
@@ -28266,37 +28285,21 @@ function scanRepo(root, opts = {}) {
|
|
|
28266
28285
|
symbols: [],
|
|
28267
28286
|
refs: []
|
|
28268
28287
|
};
|
|
28269
|
-
if (
|
|
28270
|
-
if (kind === "doc" && MARKDOWN_EXT.has(f.ext)) {
|
|
28288
|
+
if (kind !== "code") {
|
|
28289
|
+
if (content && kind === "doc" && MARKDOWN_EXT.has(f.ext)) {
|
|
28271
28290
|
const md = extractMarkdown(content);
|
|
28272
28291
|
record.title = md.title ?? basename(f.rel);
|
|
28273
28292
|
record.summary = md.summary;
|
|
28274
28293
|
record.headings = md.headings;
|
|
28275
28294
|
record.refs = md.refs;
|
|
28276
|
-
} else if (kind === "doc") {
|
|
28277
|
-
record.title = basename(f.rel);
|
|
28278
|
-
} else if (kind === "code") {
|
|
28279
|
-
const code2 = extractCode(f.rel, f.ext, content, { maxCallsPerFile: opts.maxCallsPerFile });
|
|
28295
|
+
} else if (content && kind === "doc") {
|
|
28280
28296
|
record.title = basename(f.rel);
|
|
28281
|
-
|
|
28282
|
-
record.symbols = code2.symbols;
|
|
28283
|
-
record.refs = code2.refs;
|
|
28284
|
-
record.pkg = code2.pkg;
|
|
28285
|
-
record.idents = code2.idents;
|
|
28286
|
-
record.calls = code2.calls;
|
|
28287
|
-
record.importedNames = code2.importedNames;
|
|
28288
|
-
record.truncated = code2.truncated;
|
|
28289
|
-
record.relations = code2.relations;
|
|
28290
|
-
record.terms = code2.terms;
|
|
28291
|
-
record.literals = code2.literals;
|
|
28292
|
-
} else if (kind === "config") {
|
|
28297
|
+
} else if (content && kind === "config") {
|
|
28293
28298
|
record.title = basename(f.rel);
|
|
28294
28299
|
record.literals = extractConfigLiterals(content);
|
|
28295
28300
|
} else {
|
|
28296
28301
|
record.title = basename(f.rel);
|
|
28297
28302
|
}
|
|
28298
|
-
} else {
|
|
28299
|
-
record.title = basename(f.rel);
|
|
28300
28303
|
}
|
|
28301
28304
|
if (kind === "doc" && content) docText.set(f.rel, content);
|
|
28302
28305
|
files.push(record);
|
|
@@ -28339,6 +28342,13 @@ function toCacheMap(scan2) {
|
|
|
28339
28342
|
for (const f of scan2.files) m.set(f.rel, { hash: f.hash, record: f, size: f.size, mtimeMs: scan2.mtimes.get(f.rel) });
|
|
28340
28343
|
return m;
|
|
28341
28344
|
}
|
|
28345
|
+
function needsGrammarWarm(walked, cache, fullHash = false) {
|
|
28346
|
+
const codeFiles = walked.files.filter((file) => classify(file.rel, file.ext) === "code");
|
|
28347
|
+
return fullHash && codeFiles.length > 0 || codeFiles.some((file) => {
|
|
28348
|
+
const cached = cache.get(file.rel);
|
|
28349
|
+
return !cached || cached.size !== file.size || cached.mtimeMs !== file.mtimeMs;
|
|
28350
|
+
});
|
|
28351
|
+
}
|
|
28342
28352
|
function readPersistedIndex(repo, indexDir = INDEX_DIR) {
|
|
28343
28353
|
let parsed;
|
|
28344
28354
|
try {
|
|
@@ -28390,6 +28400,34 @@ function preloadSession(repo, opts, indexDir = INDEX_DIR) {
|
|
|
28390
28400
|
const scan2 = scanRepo(repo, { ...opts, cache: persisted.cacheMap });
|
|
28391
28401
|
return { scan: scan2, cacheMap: toCacheMap(scan2), arts: preloadArtifacts(repo, scan2, persisted.meta, indexDir) };
|
|
28392
28402
|
}
|
|
28403
|
+
async function preloadSessionLazy(repo, opts, warm, indexDir = INDEX_DIR) {
|
|
28404
|
+
const persisted = readPersistedIndex(repo, indexDir);
|
|
28405
|
+
if (!persisted) return void 0;
|
|
28406
|
+
const walked = opts.precomputedWalk ?? walk(repo, {
|
|
28407
|
+
maxFileBytes: opts.maxBytes,
|
|
28408
|
+
maxFiles: opts.maxFiles,
|
|
28409
|
+
gitignore: opts.gitignore,
|
|
28410
|
+
ignoreDirs: opts.ignoreDirs
|
|
28411
|
+
});
|
|
28412
|
+
const needsWarm = needsGrammarWarm(walked, persisted.cacheMap, opts.fullHash);
|
|
28413
|
+
if (needsWarm) {
|
|
28414
|
+
await warm();
|
|
28415
|
+
}
|
|
28416
|
+
const scan2 = scanRepo(repo, { ...opts, cache: persisted.cacheMap, precomputedWalk: walked });
|
|
28417
|
+
let artifactsTried = false;
|
|
28418
|
+
let artifacts;
|
|
28419
|
+
return {
|
|
28420
|
+
scan: scan2,
|
|
28421
|
+
cacheMap: toCacheMap(scan2),
|
|
28422
|
+
loadArtifacts: () => {
|
|
28423
|
+
if (!artifactsTried) {
|
|
28424
|
+
artifactsTried = true;
|
|
28425
|
+
artifacts = preloadArtifacts(repo, scan2, persisted.meta, indexDir);
|
|
28426
|
+
}
|
|
28427
|
+
return artifacts;
|
|
28428
|
+
}
|
|
28429
|
+
};
|
|
28430
|
+
}
|
|
28393
28431
|
var INDEX_DIR;
|
|
28394
28432
|
var init_preload = __esm({
|
|
28395
28433
|
"src/preload.ts"() {
|
|
@@ -28397,9 +28435,144 @@ var init_preload = __esm({
|
|
|
28397
28435
|
init_types();
|
|
28398
28436
|
init_scan();
|
|
28399
28437
|
init_hash();
|
|
28438
|
+
init_walk();
|
|
28439
|
+
init_classify();
|
|
28400
28440
|
INDEX_DIR = ".codeindex";
|
|
28401
28441
|
}
|
|
28402
28442
|
});
|
|
28443
|
+
function resolveEngineUrl() {
|
|
28444
|
+
try {
|
|
28445
|
+
const here = fileURLToPath2(import.meta.url);
|
|
28446
|
+
if (here.endsWith("engine.mjs")) return pathToFileURL(here).href;
|
|
28447
|
+
const adjacent = join4(dirname2(here), "engine.mjs");
|
|
28448
|
+
if (existsSync2(adjacent)) return pathToFileURL(adjacent).href;
|
|
28449
|
+
return void 0;
|
|
28450
|
+
} catch {
|
|
28451
|
+
return void 0;
|
|
28452
|
+
}
|
|
28453
|
+
}
|
|
28454
|
+
function workerCount(requested) {
|
|
28455
|
+
const env = process.env["CODEINDEX_WORKERS"];
|
|
28456
|
+
const raw = requested ?? (env !== void 0 && env !== "" ? Number(env) : void 0);
|
|
28457
|
+
if (raw !== void 0) return Number.isFinite(raw) && raw > 0 ? Math.floor(raw) : 0;
|
|
28458
|
+
let cores = 1;
|
|
28459
|
+
try {
|
|
28460
|
+
cores = typeof os.availableParallelism === "function" ? os.availableParallelism() : os.cpus().length;
|
|
28461
|
+
} catch {
|
|
28462
|
+
cores = 1;
|
|
28463
|
+
}
|
|
28464
|
+
return Math.max(0, Math.min(cores - 1, 8));
|
|
28465
|
+
}
|
|
28466
|
+
async function runExtractWorker(input, post) {
|
|
28467
|
+
await ensureGrammars(input.grammarKeys);
|
|
28468
|
+
const ready = input.grammarKeys.filter((k) => grammarReady(k));
|
|
28469
|
+
const records = [];
|
|
28470
|
+
for (const job of input.jobs) {
|
|
28471
|
+
let size;
|
|
28472
|
+
let mtimeMs;
|
|
28473
|
+
try {
|
|
28474
|
+
const st = statSync3(job.abs);
|
|
28475
|
+
size = st.size;
|
|
28476
|
+
mtimeMs = st.mtimeMs;
|
|
28477
|
+
} catch {
|
|
28478
|
+
continue;
|
|
28479
|
+
}
|
|
28480
|
+
const content = readText2(job.abs);
|
|
28481
|
+
const record = buildCodeRecord(job.rel, job.ext, size, content, sha1(content), extToLang(job.ext), {
|
|
28482
|
+
maxCallsPerFile: input.maxCallsPerFile
|
|
28483
|
+
});
|
|
28484
|
+
records.push({ rel: job.rel, size, mtimeMs, record });
|
|
28485
|
+
}
|
|
28486
|
+
post({ ready, records });
|
|
28487
|
+
}
|
|
28488
|
+
async function extractInParallel(jobs, grammarKeys, count, opts = {}) {
|
|
28489
|
+
if (count < 2 || jobs.length === 0) return void 0;
|
|
28490
|
+
const engineUrl = resolveEngineUrl();
|
|
28491
|
+
if (!engineUrl) return void 0;
|
|
28492
|
+
const wanted = grammarKeys.filter((k) => grammarReady(k)).sort();
|
|
28493
|
+
const shards = Array.from({ length: Math.min(count, jobs.length) }, () => []);
|
|
28494
|
+
jobs.forEach((j, i2) => shards[i2 % shards.length].push(j));
|
|
28495
|
+
const bootstrap = `import { runExtractWorker } from ${JSON.stringify(engineUrl)};
|
|
28496
|
+
import { parentPort, workerData } from "node:worker_threads";
|
|
28497
|
+
runExtractWorker(workerData.input, (o) => parentPort.postMessage(o)).catch((e) => parentPort.postMessage({ error: String(e) }));
|
|
28498
|
+
`;
|
|
28499
|
+
try {
|
|
28500
|
+
const outputs = await Promise.all(
|
|
28501
|
+
shards.map(
|
|
28502
|
+
(jobsForShard) => new Promise((resolve52, reject) => {
|
|
28503
|
+
const w = new Worker(bootstrap, {
|
|
28504
|
+
eval: true,
|
|
28505
|
+
workerData: { input: { jobs: jobsForShard, grammarKeys: wanted, maxCallsPerFile: opts.maxCallsPerFile } }
|
|
28506
|
+
});
|
|
28507
|
+
const timer = setTimeout(() => {
|
|
28508
|
+
reject(new Error("extraction worker timed out"));
|
|
28509
|
+
void w.terminate();
|
|
28510
|
+
}, WORKER_TIMEOUT_MS);
|
|
28511
|
+
const settle = (fn) => {
|
|
28512
|
+
clearTimeout(timer);
|
|
28513
|
+
fn();
|
|
28514
|
+
};
|
|
28515
|
+
w.once("message", (m) => {
|
|
28516
|
+
settle(() => resolve52(m));
|
|
28517
|
+
void w.terminate();
|
|
28518
|
+
});
|
|
28519
|
+
w.once("error", (e) => settle(() => reject(e)));
|
|
28520
|
+
w.once("exit", (code2) => {
|
|
28521
|
+
if (code2 !== 0) settle(() => reject(new Error(`extraction worker exited with ${code2}`)));
|
|
28522
|
+
});
|
|
28523
|
+
})
|
|
28524
|
+
)
|
|
28525
|
+
);
|
|
28526
|
+
const out2 = /* @__PURE__ */ new Map();
|
|
28527
|
+
for (const o of outputs) {
|
|
28528
|
+
if ("error" in o) return void 0;
|
|
28529
|
+
if (o.ready.slice().sort().join(",") !== wanted.join(",")) return void 0;
|
|
28530
|
+
for (const r of o.records) out2.set(r.rel, { size: r.size, mtimeMs: r.mtimeMs, record: r.record });
|
|
28531
|
+
}
|
|
28532
|
+
return out2;
|
|
28533
|
+
} catch {
|
|
28534
|
+
return void 0;
|
|
28535
|
+
}
|
|
28536
|
+
}
|
|
28537
|
+
async function scanRepoParallel(root, opts = {}) {
|
|
28538
|
+
const count = workerCount(opts.workers);
|
|
28539
|
+
if (count < 2) return scanRepo(root, opts);
|
|
28540
|
+
const walked = opts.precomputedWalk ?? walk(root, {
|
|
28541
|
+
maxFileBytes: opts.maxBytes,
|
|
28542
|
+
maxFiles: opts.maxFiles,
|
|
28543
|
+
gitignore: opts.gitignore,
|
|
28544
|
+
ignoreDirs: opts.ignoreDirs
|
|
28545
|
+
});
|
|
28546
|
+
const scanOpts = { ...opts, precomputedWalk: walked };
|
|
28547
|
+
const jobs = [];
|
|
28548
|
+
for (const { f } of keptCodeFiles(root, scanOpts)) {
|
|
28549
|
+
const cached = opts.cache?.get(f.rel);
|
|
28550
|
+
if (!opts.fullHash && cached && cached.size !== void 0 && cached.mtimeMs !== void 0 && cached.size === f.size && cached.mtimeMs === f.mtimeMs) {
|
|
28551
|
+
continue;
|
|
28552
|
+
}
|
|
28553
|
+
jobs.push({ abs: f.abs, rel: f.rel, ext: f.ext });
|
|
28554
|
+
}
|
|
28555
|
+
if (jobs.length === 0) return scanRepo(root, scanOpts);
|
|
28556
|
+
const workersForced = opts.workers !== void 0 || (process.env["CODEINDEX_WORKERS"] ?? "") !== "";
|
|
28557
|
+
if (!workersForced && jobs.length < DEFAULT_MIN_PARALLEL_JOBS) return scanRepo(root, scanOpts);
|
|
28558
|
+
const grammarKeys = grammarKeysForExts(walked.files.map((f) => f.ext));
|
|
28559
|
+
const extracted = await extractInParallel(jobs, grammarKeys, count, { maxCallsPerFile: opts.maxCallsPerFile });
|
|
28560
|
+
return scanRepo(root, extracted ? { ...scanOpts, extracted } : scanOpts);
|
|
28561
|
+
}
|
|
28562
|
+
var WORKER_TIMEOUT_MS;
|
|
28563
|
+
var DEFAULT_MIN_PARALLEL_JOBS;
|
|
28564
|
+
var init_pool = __esm({
|
|
28565
|
+
"src/pool.ts"() {
|
|
28566
|
+
"use strict";
|
|
28567
|
+
init_hash();
|
|
28568
|
+
init_walk();
|
|
28569
|
+
init_registry();
|
|
28570
|
+
init_loader();
|
|
28571
|
+
init_scan();
|
|
28572
|
+
WORKER_TIMEOUT_MS = 10 * 60 * 1e3;
|
|
28573
|
+
DEFAULT_MIN_PARALLEL_JOBS = 200;
|
|
28574
|
+
}
|
|
28575
|
+
});
|
|
28403
28576
|
function distToSrcCandidates(target) {
|
|
28404
28577
|
const segs = norm(target).split("/").filter((s) => s !== ".");
|
|
28405
28578
|
const out2 = [];
|
|
@@ -29512,6 +29685,17 @@ function buildCallerIndex(scan2, importPairs, opts = {}) {
|
|
|
29512
29685
|
arr.push(s);
|
|
29513
29686
|
}
|
|
29514
29687
|
}
|
|
29688
|
+
const defsByFamily = /* @__PURE__ */ new Map();
|
|
29689
|
+
for (const [name2, sites2] of defs) {
|
|
29690
|
+
const families = /* @__PURE__ */ new Map();
|
|
29691
|
+
for (const site of sites2) {
|
|
29692
|
+
const family = familyOf(site.lang);
|
|
29693
|
+
let grouped = families.get(family);
|
|
29694
|
+
if (!grouped) families.set(family, grouped = []);
|
|
29695
|
+
grouped.push(site);
|
|
29696
|
+
}
|
|
29697
|
+
defsByFamily.set(name2, families);
|
|
29698
|
+
}
|
|
29515
29699
|
const localDefs = /* @__PURE__ */ new Map();
|
|
29516
29700
|
for (const f of scan2.files) {
|
|
29517
29701
|
const byName = /* @__PURE__ */ new Map();
|
|
@@ -29537,7 +29721,7 @@ function buildCallerIndex(scan2, importPairs, opts = {}) {
|
|
|
29537
29721
|
record(local, recall ? { file: f.rel, line: c2.line, confidence: "corroborated" } : { file: f.rel, line: c2.line });
|
|
29538
29722
|
continue;
|
|
29539
29723
|
}
|
|
29540
|
-
const cands = (
|
|
29724
|
+
const cands = (defsByFamily.get(c2.name)?.get(family) ?? []).filter((d) => d.file !== f.rel);
|
|
29541
29725
|
if (!cands.length) continue;
|
|
29542
29726
|
const imported = cands.filter((d) => pairs.has(`${f.rel}|${d.file}`));
|
|
29543
29727
|
const chosen = family === "js" ? imported.length ? pickCandidate(f.rel, imported) : (
|
|
@@ -29546,7 +29730,7 @@ function buildCallerIndex(scan2, importPairs, opts = {}) {
|
|
|
29546
29730
|
recall && cands.length === 1 ? cands[0] : void 0
|
|
29547
29731
|
) : imported.length ? pickCandidate(f.rel, imported) : pickCandidate(f.rel, cands);
|
|
29548
29732
|
if (!chosen) continue;
|
|
29549
|
-
const def =
|
|
29733
|
+
const def = chosen;
|
|
29550
29734
|
record(
|
|
29551
29735
|
def,
|
|
29552
29736
|
recall ? { file: f.rel, line: c2.line, confidence: imported.length ? "corroborated" : "unique-name" } : { file: f.rel, line: c2.line }
|
|
@@ -30328,6 +30512,25 @@ function cacheFor(scan2) {
|
|
|
30328
30512
|
if (!c2) caches.set(scan2, c2 = {});
|
|
30329
30513
|
return c2;
|
|
30330
30514
|
}
|
|
30515
|
+
function fileByRelFor(scan2) {
|
|
30516
|
+
const c2 = cacheFor(scan2);
|
|
30517
|
+
return c2.fileByRel ??= new Map(scan2.files.map((file) => [file.rel, file]));
|
|
30518
|
+
}
|
|
30519
|
+
function symbolsByNameFor(scan2) {
|
|
30520
|
+
const c2 = cacheFor(scan2);
|
|
30521
|
+
if (!c2.symbolsByName) {
|
|
30522
|
+
const byName = /* @__PURE__ */ new Map();
|
|
30523
|
+
for (const file of scan2.files) {
|
|
30524
|
+
for (const symbol of file.symbols) {
|
|
30525
|
+
const group = byName.get(symbol.name);
|
|
30526
|
+
if (group) group.push(symbol);
|
|
30527
|
+
else byName.set(symbol.name, [symbol]);
|
|
30528
|
+
}
|
|
30529
|
+
}
|
|
30530
|
+
c2.symbolsByName = byName;
|
|
30531
|
+
}
|
|
30532
|
+
return c2.symbolsByName;
|
|
30533
|
+
}
|
|
30331
30534
|
function resolveContextFor(scan2) {
|
|
30332
30535
|
const c2 = cacheFor(scan2);
|
|
30333
30536
|
return c2.resolveCtx ??= buildResolveContext(scan2);
|
|
@@ -30630,8 +30833,11 @@ var init_graph = __esm({
|
|
|
30630
30833
|
keyOf = (from, to, kind) => `${from}${SEP3}${to}${SEP3}${kind}`;
|
|
30631
30834
|
}
|
|
30632
30835
|
});
|
|
30836
|
+
function* allSymbols(scan2) {
|
|
30837
|
+
for (const file of scan2.files) yield* file.symbols;
|
|
30838
|
+
}
|
|
30633
30839
|
function symbolsOverview(scan2, rel2) {
|
|
30634
|
-
const f = scan2.
|
|
30840
|
+
const f = fileByRelFor(scan2).get(rel2);
|
|
30635
30841
|
if (!f) return [];
|
|
30636
30842
|
return [...f.symbols].filter((s) => !REFERENCE_KINDS5.has(s.kind)).sort((a, b) => a.line - b.line || byStr(a.name, b.name));
|
|
30637
30843
|
}
|
|
@@ -30642,27 +30848,37 @@ function findSymbol(scan2, namePath, opts = {}) {
|
|
|
30642
30848
|
const parents = segments.slice(0, -1);
|
|
30643
30849
|
const matchName = (name2, wanted) => opts.substring ? name2.toLowerCase().includes(wanted.toLowerCase()) : name2 === wanted;
|
|
30644
30850
|
const out2 = [];
|
|
30645
|
-
|
|
30646
|
-
|
|
30647
|
-
|
|
30648
|
-
|
|
30649
|
-
|
|
30650
|
-
|
|
30651
|
-
|
|
30652
|
-
}
|
|
30653
|
-
out2.push({ ...s });
|
|
30851
|
+
const candidates2 = opts.substring ? allSymbols(scan2) : symbolsByNameFor(scan2).get(leaf) ?? [];
|
|
30852
|
+
for (const s of candidates2) {
|
|
30853
|
+
if (REFERENCE_KINDS5.has(s.kind)) continue;
|
|
30854
|
+
if (!matchName(s.name, leaf)) continue;
|
|
30855
|
+
if (parents.length) {
|
|
30856
|
+
const parent = parents[parents.length - 1];
|
|
30857
|
+
if (!s.parent || s.parent !== parent) continue;
|
|
30654
30858
|
}
|
|
30859
|
+
out2.push({ ...s });
|
|
30655
30860
|
}
|
|
30656
30861
|
out2.sort(
|
|
30657
30862
|
(a, b) => Number(b.name === leaf) - Number(a.name === leaf) || byStr(a.file, b.file) || a.line - b.line
|
|
30658
30863
|
);
|
|
30659
30864
|
const capped = out2.slice(0, opts.maxResults ?? 50);
|
|
30660
30865
|
if (opts.includeBody) {
|
|
30866
|
+
const linesByFile = /* @__PURE__ */ new Map();
|
|
30867
|
+
const unreadableFiles = /* @__PURE__ */ new Set();
|
|
30661
30868
|
for (const m of capped) {
|
|
30662
30869
|
const end = m.endLine ?? m.line;
|
|
30663
|
-
|
|
30664
|
-
|
|
30665
|
-
|
|
30870
|
+
if (unreadableFiles.has(m.file)) continue;
|
|
30871
|
+
let lines = linesByFile.get(m.file);
|
|
30872
|
+
if (!lines) {
|
|
30873
|
+
const content = readText2(join11(scan2.root, m.file));
|
|
30874
|
+
if (!content) {
|
|
30875
|
+
unreadableFiles.add(m.file);
|
|
30876
|
+
continue;
|
|
30877
|
+
}
|
|
30878
|
+
lines = content.split("\n");
|
|
30879
|
+
linesByFile.set(m.file, lines);
|
|
30880
|
+
}
|
|
30881
|
+
m.body = lines.slice(m.line - 1, end).join("\n");
|
|
30666
30882
|
}
|
|
30667
30883
|
}
|
|
30668
30884
|
if (opts.concise) {
|
|
@@ -30727,6 +30943,34 @@ function resolveUniqueSymbol(scan2, namePath, file) {
|
|
|
30727
30943
|
function readLines(abs) {
|
|
30728
30944
|
return readFileSync6(abs, "utf8").split("\n");
|
|
30729
30945
|
}
|
|
30946
|
+
function atomicWriteText(abs, content, cleanup = rmSync2) {
|
|
30947
|
+
const target = realpathSync2(abs);
|
|
30948
|
+
const mode = statSync4(target).mode;
|
|
30949
|
+
let tempDir;
|
|
30950
|
+
try {
|
|
30951
|
+
tempDir = mkdtempSync2(join12(dirname4(target), ".codeindex-edit-"));
|
|
30952
|
+
} catch {
|
|
30953
|
+
writeFileSync2(target, content);
|
|
30954
|
+
chmodSync(target, mode);
|
|
30955
|
+
return;
|
|
30956
|
+
}
|
|
30957
|
+
const tempFile = join12(tempDir, basename3(target));
|
|
30958
|
+
try {
|
|
30959
|
+
writeFileSync2(tempFile, content);
|
|
30960
|
+
chmodSync(tempFile, mode);
|
|
30961
|
+
try {
|
|
30962
|
+
renameSync2(tempFile, target);
|
|
30963
|
+
} catch {
|
|
30964
|
+
writeFileSync2(target, content);
|
|
30965
|
+
chmodSync(target, mode);
|
|
30966
|
+
}
|
|
30967
|
+
} finally {
|
|
30968
|
+
try {
|
|
30969
|
+
cleanup(tempDir, { recursive: true, force: true });
|
|
30970
|
+
} catch {
|
|
30971
|
+
}
|
|
30972
|
+
}
|
|
30973
|
+
}
|
|
30730
30974
|
function replaceSymbolBody(scan2, namePath, body22, file) {
|
|
30731
30975
|
const sym = resolveUniqueSymbol(scan2, namePath, file);
|
|
30732
30976
|
const end = sym.endLine ?? sym.line;
|
|
@@ -30734,7 +30978,7 @@ function replaceSymbolBody(scan2, namePath, body22, file) {
|
|
|
30734
30978
|
const lines = readLines(abs);
|
|
30735
30979
|
const newLines = body22.replace(/^\n+|\n+$/g, "").split("\n");
|
|
30736
30980
|
lines.splice(sym.line - 1, end - sym.line + 1, ...newLines);
|
|
30737
|
-
|
|
30981
|
+
atomicWriteText(abs, lines.join("\n"));
|
|
30738
30982
|
return { file: sym.file, startLine: sym.line, endLine: sym.line + newLines.length - 1, lines: newLines.length };
|
|
30739
30983
|
}
|
|
30740
30984
|
function insertAt(scan2, sym, body22, index, blankBefore, blankAfter) {
|
|
@@ -30747,7 +30991,7 @@ function insertAt(scan2, sym, body22, index, blankBefore, blankAfter) {
|
|
|
30747
30991
|
block.push(...newLines);
|
|
30748
30992
|
if (blankAfter && minGap && lines[index]?.trim() !== "") block.push("");
|
|
30749
30993
|
lines.splice(index, 0, ...block);
|
|
30750
|
-
|
|
30994
|
+
atomicWriteText(abs, lines.join("\n"));
|
|
30751
30995
|
return { file: sym.file, startLine: index + 1, endLine: index + block.length, lines: block.length };
|
|
30752
30996
|
}
|
|
30753
30997
|
function insertAfterSymbol(scan2, namePath, body22, file) {
|
|
@@ -30784,7 +31028,7 @@ function memoryPath(repo, name2) {
|
|
|
30784
31028
|
}
|
|
30785
31029
|
function writeMemory(repo, name2, content) {
|
|
30786
31030
|
const path = memoryPath(repo, name2);
|
|
30787
|
-
mkdirSync2(
|
|
31031
|
+
mkdirSync2(dirname5(path), { recursive: true });
|
|
30788
31032
|
writeFileSync3(path, content.endsWith("\n") ? content : content + "\n");
|
|
30789
31033
|
return sanitize(name2);
|
|
30790
31034
|
}
|
|
@@ -30798,11 +31042,11 @@ function readMemory(repo, name2) {
|
|
|
30798
31042
|
function deleteMemory(repo, name2) {
|
|
30799
31043
|
const path = memoryPath(repo, name2);
|
|
30800
31044
|
try {
|
|
30801
|
-
|
|
31045
|
+
statSync5(path);
|
|
30802
31046
|
} catch {
|
|
30803
31047
|
return false;
|
|
30804
31048
|
}
|
|
30805
|
-
|
|
31049
|
+
rmSync3(path);
|
|
30806
31050
|
return true;
|
|
30807
31051
|
}
|
|
30808
31052
|
function listMemories(repo) {
|
|
@@ -30997,7 +31241,7 @@ function addPackage(root, dir, found, kind, warnings) {
|
|
|
30997
31241
|
}
|
|
30998
31242
|
function isDirAt(root, rel2) {
|
|
30999
31243
|
try {
|
|
31000
|
-
return
|
|
31244
|
+
return statSync6(join14(root, rel2)).isDirectory();
|
|
31001
31245
|
} catch {
|
|
31002
31246
|
return false;
|
|
31003
31247
|
}
|
|
@@ -32155,31 +32399,31 @@ function serializeEmbeddings(index) {
|
|
|
32155
32399
|
count: index.records.length,
|
|
32156
32400
|
records: index.records.map((r) => ({ file: r.file, symbol: r.symbol ?? "", line: r.line ?? 0 }))
|
|
32157
32401
|
});
|
|
32158
|
-
const headerBuf =
|
|
32159
|
-
const
|
|
32160
|
-
|
|
32402
|
+
const headerBuf = new TextEncoder().encode(header4);
|
|
32403
|
+
const bodyLength = index.records.length * index.dim;
|
|
32404
|
+
const out2 = new Uint8Array(8 + headerBuf.length + bodyLength);
|
|
32405
|
+
out2.set([67, 73, 69, 49], 0);
|
|
32406
|
+
new DataView(out2.buffer, out2.byteOffset, out2.byteLength).setUint32(4, headerBuf.length, true);
|
|
32407
|
+
out2.set(headerBuf, 8);
|
|
32408
|
+
let off = 8 + headerBuf.length;
|
|
32161
32409
|
for (const r of index.records) {
|
|
32162
|
-
for (let d = 0; d < index.dim; d++)
|
|
32410
|
+
for (let d = 0; d < index.dim; d++) out2[off++] = r.vec[d] ?? 0;
|
|
32163
32411
|
}
|
|
32164
|
-
const out2 = Buffer.alloc(8 + headerBuf.length + body22.length);
|
|
32165
|
-
out2.write(MAGIC, 0, "ascii");
|
|
32166
|
-
out2.writeUInt32LE(headerBuf.length, 4);
|
|
32167
|
-
headerBuf.copy(out2, 8);
|
|
32168
|
-
body22.copy(out2, 8 + headerBuf.length);
|
|
32169
32412
|
return out2;
|
|
32170
32413
|
}
|
|
32171
32414
|
function deserializeEmbeddings(bytes) {
|
|
32172
|
-
|
|
32173
|
-
if (buf.length < 8 || buf.toString("ascii", 0, 4) !== MAGIC) {
|
|
32415
|
+
if (bytes.byteLength < 8 || String.fromCharCode(...bytes.subarray(0, 4)) !== MAGIC) {
|
|
32174
32416
|
throw new Error("embeddings.bin: bad magic (not a codeindex embeddings artifact)");
|
|
32175
32417
|
}
|
|
32176
|
-
const
|
|
32177
|
-
const
|
|
32418
|
+
const data2 = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
|
|
32419
|
+
const headerLen = data2.getUint32(4, true);
|
|
32420
|
+
if (8 + headerLen > bytes.byteLength) throw new Error("embeddings.bin: truncated header");
|
|
32421
|
+
const header4 = JSON.parse(new TextDecoder().decode(bytes.subarray(8, 8 + headerLen)));
|
|
32178
32422
|
const bodyOff = 8 + headerLen;
|
|
32179
32423
|
const { dim } = header4;
|
|
32424
|
+
if (bodyOff + header4.records.length * dim > bytes.byteLength) throw new Error("embeddings.bin: truncated body");
|
|
32180
32425
|
const records = header4.records.map((m, i2) => {
|
|
32181
|
-
const vec = new Int8Array(dim);
|
|
32182
|
-
for (let d = 0; d < dim; d++) vec[d] = buf.readInt8(bodyOff + i2 * dim + d);
|
|
32426
|
+
const vec = new Int8Array(bytes.buffer.slice(bytes.byteOffset + bodyOff + i2 * dim, bytes.byteOffset + bodyOff + (i2 + 1) * dim));
|
|
32183
32427
|
const rec = { file: m.file, vec };
|
|
32184
32428
|
if (m.symbol) rec.symbol = m.symbol;
|
|
32185
32429
|
if (m.line) rec.line = m.line;
|
|
@@ -32546,18 +32790,33 @@ function createFramer() {
|
|
|
32546
32790
|
};
|
|
32547
32791
|
}
|
|
32548
32792
|
function fileUri(root, rel2) {
|
|
32549
|
-
const
|
|
32793
|
+
const rootPath = root.replace(/\\/g, "/").replace(/\/+$/, "");
|
|
32794
|
+
const relPath = rel2.replace(/\\/g, "/").replace(/^\/+/, "");
|
|
32795
|
+
const abs = `${rootPath}/${relPath}`;
|
|
32796
|
+
if (abs.startsWith("//")) {
|
|
32797
|
+
const [host = "", ...segments] = abs.slice(2).split("/");
|
|
32798
|
+
return `file://${encodeURIComponent(host)}/${segments.map(encodeURIComponent).join("/")}`;
|
|
32799
|
+
}
|
|
32550
32800
|
const drive = /^([A-Za-z]):/.exec(abs);
|
|
32551
32801
|
const path = drive ? `/${abs}` : abs;
|
|
32552
|
-
return "file://" + path.split("/").map((segment, i2) => i2 === 0 ? segment : encodeURIComponent(segment)).join("/");
|
|
32802
|
+
return "file://" + path.split("/").map((segment, i2) => i2 === 0 || i2 === 1 && /^[A-Za-z]:$/.test(segment) ? segment : encodeURIComponent(segment)).join("/");
|
|
32553
32803
|
}
|
|
32554
32804
|
function relFromUri(root, uri) {
|
|
32555
32805
|
if (!uri.startsWith("file://")) return void 0;
|
|
32556
|
-
let path
|
|
32806
|
+
let path;
|
|
32807
|
+
try {
|
|
32808
|
+
const encoded = uri.slice("file://".length);
|
|
32809
|
+
path = decodeURIComponent(encoded.startsWith("/") ? encoded : `//${encoded}`).replace(/\\/g, "/");
|
|
32810
|
+
} catch {
|
|
32811
|
+
return void 0;
|
|
32812
|
+
}
|
|
32557
32813
|
if (/^\/[A-Za-z]:/.test(path)) path = path.slice(1);
|
|
32558
|
-
const base = root.replace(/\/+$/, "");
|
|
32559
|
-
|
|
32560
|
-
|
|
32814
|
+
const base = root.replace(/\\/g, "/").replace(/\/+$/, "");
|
|
32815
|
+
const windows = /^[A-Za-z]:/.test(base) || base.startsWith("//");
|
|
32816
|
+
const comparablePath = windows ? path.toLowerCase() : path;
|
|
32817
|
+
const comparableBase = windows ? base.toLowerCase() : base;
|
|
32818
|
+
if (comparablePath === comparableBase) return "";
|
|
32819
|
+
if (!comparablePath.startsWith(`${comparableBase}/`)) return void 0;
|
|
32561
32820
|
return path.slice(base.length + 1);
|
|
32562
32821
|
}
|
|
32563
32822
|
function locationsToRefs(root, raw) {
|
|
@@ -33350,9 +33609,13 @@ function validateArgs(schema, args2) {
|
|
|
33350
33609
|
if (!spec?.type) continue;
|
|
33351
33610
|
const actual = Array.isArray(value) ? "array" : typeof value;
|
|
33352
33611
|
if (spec.type === "number") {
|
|
33353
|
-
|
|
33354
|
-
if (
|
|
33355
|
-
|
|
33612
|
+
const numeric = actual === "number" ? value : actual === "string" && value.trim() !== "" ? Number(value) : NaN;
|
|
33613
|
+
if (!Number.isFinite(numeric)) {
|
|
33614
|
+
return `\`${key2}\` must be a number, got ${actual === "string" ? JSON.stringify(value) : actual}`;
|
|
33615
|
+
}
|
|
33616
|
+
if (spec.minimum !== void 0 && numeric < spec.minimum) return `\`${key2}\` must be at least ${spec.minimum}`;
|
|
33617
|
+
if (spec.maximum !== void 0 && numeric > spec.maximum) return `\`${key2}\` must be at most ${spec.maximum}`;
|
|
33618
|
+
continue;
|
|
33356
33619
|
}
|
|
33357
33620
|
if (spec.type === "array") {
|
|
33358
33621
|
if (actual !== "array") return `\`${key2}\` must be an array of strings, got ${actual}`;
|
|
@@ -33580,7 +33843,7 @@ var init_tools = __esm({
|
|
|
33580
33843
|
type: "boolean",
|
|
33581
33844
|
description: "Return only name/kind/file/line \u2014 drop the signature, line span, visibility and language. Roughly 2.5x smaller; use it when you are resolving a path and nothing more (default false)."
|
|
33582
33845
|
},
|
|
33583
|
-
maxResults: { type: "number", description: "Cap matches (default 50)" }
|
|
33846
|
+
maxResults: { type: "number", minimum: 1, description: "Cap matches (default 50)" }
|
|
33584
33847
|
},
|
|
33585
33848
|
required: ["repo", "namePath"]
|
|
33586
33849
|
}
|
|
@@ -33620,7 +33883,7 @@ var init_tools = __esm({
|
|
|
33620
33883
|
type: "object",
|
|
33621
33884
|
properties: {
|
|
33622
33885
|
...repoProp,
|
|
33623
|
-
budgetTokens: { type: "number", description: "Token budget for the key-files section (default 900)" },
|
|
33886
|
+
budgetTokens: { type: "number", minimum: 1, description: "Token budget for the key-files section (default 900)" },
|
|
33624
33887
|
remember: { type: "boolean", description: "Persist the brief as the `onboarding` memory (default true)" }
|
|
33625
33888
|
},
|
|
33626
33889
|
required: ["repo"]
|
|
@@ -33631,7 +33894,7 @@ var init_tools = __esm({
|
|
|
33631
33894
|
description: "Token-budgeted map of the repository: the highest-PageRank files with their key exported signatures, deterministically rendered to fit `budgetTokens` (default 1024). The densest single read to understand an unfamiliar codebase.",
|
|
33632
33895
|
inputSchema: {
|
|
33633
33896
|
type: "object",
|
|
33634
|
-
properties: { ...repoProp, budgetTokens: { type: "number", description: "Approximate token budget (default 1024)" } },
|
|
33897
|
+
properties: { ...repoProp, budgetTokens: { type: "number", minimum: 1, description: "Approximate token budget (default 1024)" } },
|
|
33635
33898
|
required: ["repo"]
|
|
33636
33899
|
}
|
|
33637
33900
|
},
|
|
@@ -33725,7 +33988,7 @@ var init_tools = __esm({
|
|
|
33725
33988
|
properties: {
|
|
33726
33989
|
...repoProp,
|
|
33727
33990
|
...scopeProps,
|
|
33728
|
-
limit: { type: "number", description: "Cap entries (default: all)" }
|
|
33991
|
+
limit: { type: "number", minimum: 0, description: "Cap entries (default: all)" }
|
|
33729
33992
|
},
|
|
33730
33993
|
required: ["repo"]
|
|
33731
33994
|
}
|
|
@@ -33738,10 +34001,10 @@ var init_tools = __esm({
|
|
|
33738
34001
|
properties: {
|
|
33739
34002
|
...repoProp,
|
|
33740
34003
|
...scopeProps,
|
|
33741
|
-
minFiles: { type: "number", description: "Distinct files a value must span (default 2)" },
|
|
33742
|
-
minCount: { type: "number", description: "Total occurrences required (default 3)" },
|
|
34004
|
+
minFiles: { type: "number", minimum: 1, description: "Distinct files a value must span (default 2)" },
|
|
34005
|
+
minCount: { type: "number", minimum: 1, description: "Total occurrences required (default 3)" },
|
|
33743
34006
|
includeTests: { type: "boolean", description: "Count test files too (default false)" },
|
|
33744
|
-
limit: { type: "number", description: "Cap duplications (default: all)" }
|
|
34007
|
+
limit: { type: "number", minimum: 0, description: "Cap duplications (default: all)" }
|
|
33745
34008
|
},
|
|
33746
34009
|
required: ["repo"]
|
|
33747
34010
|
}
|
|
@@ -33751,7 +34014,13 @@ var init_tools = __esm({
|
|
|
33751
34014
|
description: "Cyclomatic-complexity estimates (branch-token counting over AST line spans), most-complex first. Pass `file` for one file's symbols, omit for the repo-wide top. Combine with hotspots: the `risk` field of this tool's sibling ranks complexity \xD7 churn.",
|
|
33752
34015
|
inputSchema: {
|
|
33753
34016
|
type: "object",
|
|
33754
|
-
properties: {
|
|
34017
|
+
properties: {
|
|
34018
|
+
...repoProp,
|
|
34019
|
+
file: { type: "string" },
|
|
34020
|
+
risk: { type: "boolean", description: "Return complexity \xD7 git-churn risk ranking instead" },
|
|
34021
|
+
since: { type: "string", description: "Only count risk churn after this ref" },
|
|
34022
|
+
top: { type: "number", minimum: 1, description: "Cap ranked symbols" }
|
|
34023
|
+
},
|
|
33755
34024
|
required: ["repo"]
|
|
33756
34025
|
}
|
|
33757
34026
|
},
|
|
@@ -33760,7 +34029,11 @@ var init_tools = __esm({
|
|
|
33760
34029
|
description: "Mermaid diagram of the module graph (renders inline in Claude/GitHub \u2014 no graph database). Optionally scoped to one module's neighborhood.",
|
|
33761
34030
|
inputSchema: {
|
|
33762
34031
|
type: "object",
|
|
33763
|
-
properties: {
|
|
34032
|
+
properties: {
|
|
34033
|
+
...repoProp,
|
|
34034
|
+
module: { type: "string", description: "Module slug to focus on" },
|
|
34035
|
+
maxEdges: { type: "number", minimum: 1, description: "Cap rendered edges" }
|
|
34036
|
+
},
|
|
33764
34037
|
required: ["repo"]
|
|
33765
34038
|
}
|
|
33766
34039
|
},
|
|
@@ -33775,7 +34048,7 @@ var init_tools = __esm({
|
|
|
33775
34048
|
scope: { type: "string", description: "Restrict to one directory (repo-relative)" },
|
|
33776
34049
|
globs: { type: "array", items: { type: "string" }, description: "Restrict to matching paths" },
|
|
33777
34050
|
ignoreCase: { type: "boolean" },
|
|
33778
|
-
maxHits: { type: "number" }
|
|
34051
|
+
maxHits: { type: "number", minimum: 1 }
|
|
33779
34052
|
},
|
|
33780
34053
|
required: ["repo", "pattern"]
|
|
33781
34054
|
}
|
|
@@ -33789,7 +34062,7 @@ var init_tools = __esm({
|
|
|
33789
34062
|
...repoProp,
|
|
33790
34063
|
...scopeProps,
|
|
33791
34064
|
query: { type: "string", description: "Natural-language or identifier query" },
|
|
33792
|
-
limit: { type: "number", description: "Max results (default 20)" },
|
|
34065
|
+
limit: { type: "number", minimum: 0, description: "Max results (default 20)" },
|
|
33793
34066
|
fuzzy: {
|
|
33794
34067
|
type: "boolean",
|
|
33795
34068
|
description: 'Fallback for query terms with zero document frequency: a morphological stem match first ("caching" finds "cache"), then trigram similarity for typos (default true)'
|
|
@@ -33823,7 +34096,7 @@ var init_tools = __esm({
|
|
|
33823
34096
|
...repoProp,
|
|
33824
34097
|
...scopeProps,
|
|
33825
34098
|
query: { type: "string", description: "Natural-language or identifier query" },
|
|
33826
|
-
limit: { type: "number", description: "Max results (default 20)" },
|
|
34099
|
+
limit: { type: "number", minimum: 0, description: "Max results (default 20)" },
|
|
33827
34100
|
fuzzy: { type: "boolean", description: "Stem/trigram fallback for zero-document-frequency terms (default true)" },
|
|
33828
34101
|
exact: { type: "boolean", description: "Drop results carrying no verbatim term match (default false)" }
|
|
33829
34102
|
},
|
|
@@ -33861,7 +34134,7 @@ var init_tools = __esm({
|
|
|
33861
34134
|
properties: {
|
|
33862
34135
|
...repoProp,
|
|
33863
34136
|
symbol: { type: "string", description: "Symbol name to centre on" },
|
|
33864
|
-
depth: { type: "number", description: "Hops to follow (default 2, max 5)" },
|
|
34137
|
+
depth: { type: "number", minimum: 1, maximum: 5, description: "Hops to follow (default 2, max 5)" },
|
|
33865
34138
|
direction: { type: "string", description: "out | in | both (default both)" }
|
|
33866
34139
|
},
|
|
33867
34140
|
required: ["repo", "symbol"]
|
|
@@ -34125,7 +34398,7 @@ async function memoizedEmbeddingIndex(key2, build) {
|
|
|
34125
34398
|
function memoizedEmbedModel(modelDir) {
|
|
34126
34399
|
let stat;
|
|
34127
34400
|
try {
|
|
34128
|
-
stat =
|
|
34401
|
+
stat = statSync7(join21(modelDir, "model.json"));
|
|
34129
34402
|
} catch {
|
|
34130
34403
|
return void 0;
|
|
34131
34404
|
}
|
|
@@ -34152,6 +34425,14 @@ function sessionPut(entry) {
|
|
|
34152
34425
|
function sessionClear() {
|
|
34153
34426
|
sessionCaches.length = 0;
|
|
34154
34427
|
}
|
|
34428
|
+
function sessionInvalidate(repo, rel2) {
|
|
34429
|
+
const prefix2 = repo + "\0";
|
|
34430
|
+
for (const entry of sessionCaches) {
|
|
34431
|
+
if (!entry.key.startsWith(prefix2)) continue;
|
|
34432
|
+
if (rel2) entry.cacheMap.delete(rel2);
|
|
34433
|
+
else entry.cacheMap.clear();
|
|
34434
|
+
}
|
|
34435
|
+
}
|
|
34155
34436
|
function sessionKey(repo, opts) {
|
|
34156
34437
|
return repo + "\0" + JSON.stringify({
|
|
34157
34438
|
scope: opts.scope,
|
|
@@ -34173,7 +34454,11 @@ function getScan(repo, opts = {}, walked) {
|
|
|
34173
34454
|
const fresh = scanRepo(repo, { ...opts, cache: hit.cacheMap, precomputedWalk: walked });
|
|
34174
34455
|
if (fresh.contentUnchanged) {
|
|
34175
34456
|
if (fresh.cacheDirty) hit.cacheMap = toCacheMap(fresh);
|
|
34176
|
-
if (hit.scan.commit !== fresh.commit)
|
|
34457
|
+
if (hit.scan.commit !== fresh.commit) {
|
|
34458
|
+
hit.scan.commit = fresh.commit;
|
|
34459
|
+
hit.arts = void 0;
|
|
34460
|
+
hit.loadArtifacts = void 0;
|
|
34461
|
+
}
|
|
34177
34462
|
return hit.scan;
|
|
34178
34463
|
}
|
|
34179
34464
|
sessionPut({ key: key2, scan: fresh, cacheMap: toCacheMap(fresh) });
|
|
@@ -34181,31 +34466,77 @@ function getScan(repo, opts = {}, walked) {
|
|
|
34181
34466
|
}
|
|
34182
34467
|
const preloaded = preloadSession(repo, { ...opts, precomputedWalk: walked });
|
|
34183
34468
|
if (preloaded) {
|
|
34184
|
-
sessionPut({
|
|
34469
|
+
sessionPut({
|
|
34470
|
+
key: key2,
|
|
34471
|
+
scan: preloaded.scan,
|
|
34472
|
+
cacheMap: preloaded.cacheMap,
|
|
34473
|
+
arts: preloaded.arts
|
|
34474
|
+
});
|
|
34185
34475
|
return preloaded.scan;
|
|
34186
34476
|
}
|
|
34187
34477
|
const scan2 = scanRepo(repo, { ...opts, precomputedWalk: walked });
|
|
34188
34478
|
sessionPut({ key: key2, scan: scan2, cacheMap: toCacheMap(scan2) });
|
|
34189
34479
|
return scan2;
|
|
34190
34480
|
}
|
|
34191
|
-
function
|
|
34192
|
-
|
|
34193
|
-
|
|
34194
|
-
|
|
34195
|
-
|
|
34196
|
-
|
|
34197
|
-
|
|
34198
|
-
|
|
34199
|
-
|
|
34200
|
-
|
|
34481
|
+
async function getScanParallel(repo, opts = {}, walked, warm = async () => {
|
|
34482
|
+
}) {
|
|
34483
|
+
const key2 = sessionKey(repo, opts);
|
|
34484
|
+
const existing = sessionCaches.find((entry) => entry.key === key2);
|
|
34485
|
+
if (existing) {
|
|
34486
|
+
const originalCache = existing.cacheMap;
|
|
34487
|
+
const reuseUnchanged = (fresh) => {
|
|
34488
|
+
if (fresh.cacheDirty) existing.cacheMap = toCacheMap(fresh);
|
|
34489
|
+
if (existing.scan.commit !== fresh.commit) {
|
|
34490
|
+
existing.scan.commit = fresh.commit;
|
|
34491
|
+
existing.arts = void 0;
|
|
34492
|
+
existing.loadArtifacts = void 0;
|
|
34493
|
+
}
|
|
34494
|
+
sessionGet(key2);
|
|
34495
|
+
return existing.scan;
|
|
34201
34496
|
};
|
|
34497
|
+
if (walked && needsGrammarWarm(walked, originalCache, opts.fullHash)) {
|
|
34498
|
+
await warm();
|
|
34499
|
+
const fresh = await scanRepoParallel(repo, { ...opts, cache: originalCache, precomputedWalk: walked });
|
|
34500
|
+
if (fresh.contentUnchanged) return reuseUnchanged(fresh);
|
|
34501
|
+
sessionPut({ key: key2, scan: fresh, cacheMap: toCacheMap(fresh) });
|
|
34502
|
+
return fresh;
|
|
34503
|
+
}
|
|
34504
|
+
const provisional = scanRepo(repo, { ...opts, cache: originalCache, precomputedWalk: walked });
|
|
34505
|
+
if (provisional.contentUnchanged) {
|
|
34506
|
+
return reuseUnchanged(provisional);
|
|
34507
|
+
}
|
|
34508
|
+
if (walked) {
|
|
34509
|
+
sessionPut({ key: key2, scan: provisional, cacheMap: toCacheMap(provisional) });
|
|
34510
|
+
return provisional;
|
|
34511
|
+
}
|
|
34512
|
+
await warm();
|
|
34513
|
+
const scan3 = await scanRepoParallel(repo, { ...opts, cache: originalCache, precomputedWalk: walked });
|
|
34514
|
+
sessionPut({ key: key2, scan: scan3, cacheMap: toCacheMap(scan3) });
|
|
34515
|
+
return scan3;
|
|
34516
|
+
}
|
|
34517
|
+
const preloaded = await preloadSessionLazy(repo, { ...opts, precomputedWalk: walked }, warm);
|
|
34518
|
+
if (preloaded) {
|
|
34519
|
+
sessionPut({
|
|
34520
|
+
key: key2,
|
|
34521
|
+
scan: preloaded.scan,
|
|
34522
|
+
cacheMap: preloaded.cacheMap,
|
|
34523
|
+
arts: preloaded.arts,
|
|
34524
|
+
loadArtifacts: preloaded.loadArtifacts
|
|
34525
|
+
});
|
|
34526
|
+
return preloaded.scan;
|
|
34202
34527
|
}
|
|
34528
|
+
await warm();
|
|
34529
|
+
const scan2 = await scanRepoParallel(repo, { ...opts, precomputedWalk: walked });
|
|
34530
|
+
sessionPut({ key: key2, scan: scan2, cacheMap: toCacheMap(scan2) });
|
|
34531
|
+
return scan2;
|
|
34532
|
+
}
|
|
34533
|
+
function getScanSummary(repo, opts = {}, walked) {
|
|
34203
34534
|
return scanSummary(repo, { ...opts, precomputedWalk: walked });
|
|
34204
34535
|
}
|
|
34205
|
-
function getArtifacts(repo, opts = {}, walked) {
|
|
34206
|
-
const scan2 = getScan(repo, opts, walked);
|
|
34536
|
+
function getArtifacts(repo, opts = {}, walked, prepared) {
|
|
34537
|
+
const scan2 = prepared ?? getScan(repo, opts, walked);
|
|
34207
34538
|
const entry = sessionCaches.find((e) => e.scan === scan2);
|
|
34208
|
-
if (entry) return entry.arts ??= buildArtifactsFromScan(scan2, opts);
|
|
34539
|
+
if (entry) return entry.arts ??= entry.loadArtifacts?.() ?? buildArtifactsFromScan(scan2, opts);
|
|
34209
34540
|
return buildArtifactsFromScan(scan2, opts);
|
|
34210
34541
|
}
|
|
34211
34542
|
async function warmGrammarsForRepo(repo) {
|
|
@@ -34223,6 +34554,7 @@ var init_session = __esm({
|
|
|
34223
34554
|
"use strict";
|
|
34224
34555
|
init_pipeline();
|
|
34225
34556
|
init_scan();
|
|
34557
|
+
init_pool();
|
|
34226
34558
|
init_preload();
|
|
34227
34559
|
init_walk();
|
|
34228
34560
|
init_loader();
|
|
@@ -34245,6 +34577,7 @@ __export(mcp_exports, {
|
|
|
34245
34577
|
capResponse: () => capResponse,
|
|
34246
34578
|
getArtifacts: () => getArtifacts,
|
|
34247
34579
|
getScan: () => getScan,
|
|
34580
|
+
getScanParallel: () => getScanParallel,
|
|
34248
34581
|
getScanSummary: () => getScanSummary,
|
|
34249
34582
|
memoizedEmbedModel: () => memoizedEmbedModel,
|
|
34250
34583
|
memoizedEmbeddingIndex: () => memoizedEmbeddingIndex,
|
|
@@ -34261,6 +34594,17 @@ __export(mcp_exports, {
|
|
|
34261
34594
|
warmGrammarsForRepo: () => warmGrammarsForRepo,
|
|
34262
34595
|
warmGrammarsForWalk: () => warmGrammarsForWalk
|
|
34263
34596
|
});
|
|
34597
|
+
function isRpcRequest(value) {
|
|
34598
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return false;
|
|
34599
|
+
const req = value;
|
|
34600
|
+
if (req.jsonrpc !== "2.0" || typeof req.method !== "string") return false;
|
|
34601
|
+
return req.id === void 0 || req.id === null || typeof req.id === "number" || typeof req.id === "string";
|
|
34602
|
+
}
|
|
34603
|
+
function isRpcResponse(value) {
|
|
34604
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return false;
|
|
34605
|
+
const response = value;
|
|
34606
|
+
return response.jsonrpc === "2.0" && typeof response.method !== "string" && ("result" in response || "error" in response);
|
|
34607
|
+
}
|
|
34264
34608
|
function str(v) {
|
|
34265
34609
|
return typeof v === "string" && v ? v : void 0;
|
|
34266
34610
|
}
|
|
@@ -34269,7 +34613,11 @@ function strArray(v) {
|
|
|
34269
34613
|
}
|
|
34270
34614
|
function num(v) {
|
|
34271
34615
|
const n = typeof v === "number" ? v : typeof v === "string" && v.trim() !== "" ? Number(v) : NaN;
|
|
34272
|
-
return Number.isFinite(n) && n
|
|
34616
|
+
return Number.isFinite(n) && n >= 0 ? n : void 0;
|
|
34617
|
+
}
|
|
34618
|
+
function positiveNum(v) {
|
|
34619
|
+
const n = num(v);
|
|
34620
|
+
return n !== void 0 && n > 0 ? n : void 0;
|
|
34273
34621
|
}
|
|
34274
34622
|
function errMessage(e) {
|
|
34275
34623
|
return e instanceof Error ? e.message : String(e);
|
|
@@ -34277,14 +34625,27 @@ function errMessage(e) {
|
|
|
34277
34625
|
async function callTool(name2, args2, defaultRepo) {
|
|
34278
34626
|
const repo = str(args2.repo) ?? defaultRepo;
|
|
34279
34627
|
if (!repo) throw new Error("`repo` is required (absolute path to the repository root)");
|
|
34628
|
+
try {
|
|
34629
|
+
if (!statSync8(repo).isDirectory()) throw new Error("not a directory");
|
|
34630
|
+
} catch {
|
|
34631
|
+
throw new Error(`repository root is not a readable directory: ${repo}`);
|
|
34632
|
+
}
|
|
34280
34633
|
const scanOpts = { scope: str(args2.scope), include: strArray(args2.include), exclude: strArray(args2.exclude) };
|
|
34281
34634
|
const rankArg = str(args2.rank);
|
|
34282
34635
|
const rankOpt = rankArg === "graph" || rankArg === "lexical" ? { rank: rankArg } : {};
|
|
34283
34636
|
let walked;
|
|
34637
|
+
let preparedScan;
|
|
34284
34638
|
if (!SCANLESS_TOOLS.has(name2)) {
|
|
34285
34639
|
walked = walk(repo, {});
|
|
34286
|
-
await
|
|
34640
|
+
preparedScan = await getScanParallel(
|
|
34641
|
+
repo,
|
|
34642
|
+
scanOpts,
|
|
34643
|
+
walked,
|
|
34644
|
+
() => walked ? warmGrammarsForWalk(walked) : Promise.resolve()
|
|
34645
|
+
);
|
|
34287
34646
|
}
|
|
34647
|
+
const readScan = () => preparedScan ?? getScan(repo, scanOpts, walked);
|
|
34648
|
+
const readArtifacts = () => getArtifacts(repo, scanOpts, walked, preparedScan);
|
|
34288
34649
|
if (name2 === "scan_summary") {
|
|
34289
34650
|
const s = getScanSummary(repo, scanOpts, walked);
|
|
34290
34651
|
return JSON.stringify(
|
|
@@ -34294,10 +34655,10 @@ async function callTool(name2, args2, defaultRepo) {
|
|
|
34294
34655
|
);
|
|
34295
34656
|
}
|
|
34296
34657
|
if (name2 === "graph") {
|
|
34297
|
-
return renderGraphJson(
|
|
34658
|
+
return renderGraphJson(readArtifacts().graph);
|
|
34298
34659
|
}
|
|
34299
34660
|
if (name2 === "symbols") {
|
|
34300
|
-
const { symbols } =
|
|
34661
|
+
const { symbols } = readArtifacts();
|
|
34301
34662
|
const lookup2 = str(args2.name);
|
|
34302
34663
|
if (lookup2) {
|
|
34303
34664
|
return JSON.stringify({ name: lookup2, defs: symbols.defs[lookup2] ?? [], refs: symbols.refs[lookup2] ?? [] }, null, 2);
|
|
@@ -34305,7 +34666,7 @@ async function callTool(name2, args2, defaultRepo) {
|
|
|
34305
34666
|
return JSON.stringify(symbols, null, 2);
|
|
34306
34667
|
}
|
|
34307
34668
|
if (name2 === "callers") {
|
|
34308
|
-
const scan2 =
|
|
34669
|
+
const scan2 = readScan();
|
|
34309
34670
|
const index = args2.recall === true ? buildCallerIndex(scan2, void 0, { recall: true }) : callerIndexFor(scan2);
|
|
34310
34671
|
const lookup2 = str(args2.name);
|
|
34311
34672
|
if (lookup2) {
|
|
@@ -34329,35 +34690,35 @@ async function callTool(name2, args2, defaultRepo) {
|
|
|
34329
34690
|
if (name2 === "symbols_overview") {
|
|
34330
34691
|
const file = str(args2.file);
|
|
34331
34692
|
if (!file) throw new Error("`file` is required");
|
|
34332
|
-
return JSON.stringify(symbolsOverview(
|
|
34693
|
+
return JSON.stringify(symbolsOverview(readScan(), file), null, 2);
|
|
34333
34694
|
}
|
|
34334
34695
|
if (name2 === "find_symbol") {
|
|
34335
34696
|
const namePath = str(args2.namePath);
|
|
34336
34697
|
if (!namePath) throw new Error("`namePath` is required");
|
|
34337
|
-
const matches = findSymbol(
|
|
34698
|
+
const matches = findSymbol(readScan(), namePath, {
|
|
34338
34699
|
substring: args2.substring === true,
|
|
34339
34700
|
includeBody: args2.includeBody === true,
|
|
34340
34701
|
concise: args2.concise === true,
|
|
34341
|
-
maxResults:
|
|
34702
|
+
maxResults: positiveNum(args2.maxResults)
|
|
34342
34703
|
});
|
|
34343
34704
|
return JSON.stringify(matches, null, 2);
|
|
34344
34705
|
}
|
|
34345
34706
|
if (name2 === "find_references") {
|
|
34346
34707
|
const symName = str(args2.name);
|
|
34347
34708
|
if (!symName) throw new Error("`name` is required");
|
|
34348
|
-
const scan2 =
|
|
34709
|
+
const scan2 = readScan();
|
|
34349
34710
|
const statik = findReferences(scan2, symName);
|
|
34350
34711
|
if (args2.lsp === true) return JSON.stringify(await referencesWithLsp(scan2, repo, symName, statik), null, 2);
|
|
34351
34712
|
return JSON.stringify(statik, null, 2);
|
|
34352
34713
|
}
|
|
34353
34714
|
if (name2 === "lsp_status") {
|
|
34354
|
-
return JSON.stringify(await lspStatus(
|
|
34715
|
+
return JSON.stringify(await lspStatus(readScan(), repo, args2.probe === true), null, 2);
|
|
34355
34716
|
}
|
|
34356
34717
|
if (name2 === "replace_symbol_body" || name2 === "insert_after_symbol" || name2 === "insert_before_symbol") {
|
|
34357
34718
|
const namePath = str(args2.namePath);
|
|
34358
34719
|
const body22 = typeof args2.body === "string" ? args2.body : void 0;
|
|
34359
34720
|
if (!namePath || body22 === void 0) throw new Error("`namePath` and `body` are required");
|
|
34360
|
-
const scan2 =
|
|
34721
|
+
const scan2 = readScan();
|
|
34361
34722
|
const fn = name2 === "replace_symbol_body" ? replaceSymbolBody : name2 === "insert_after_symbol" ? insertAfterSymbol : insertBeforeSymbol;
|
|
34362
34723
|
const result = fn(scan2, namePath, body22, str(args2.file));
|
|
34363
34724
|
sessionClear();
|
|
@@ -34385,15 +34746,15 @@ async function callTool(name2, args2, defaultRepo) {
|
|
|
34385
34746
|
return JSON.stringify({ deleted: deleteMemory(repo, memName) }, null, 2);
|
|
34386
34747
|
}
|
|
34387
34748
|
if (name2 === "dead_code") {
|
|
34388
|
-
const all = findDeadCode(
|
|
34749
|
+
const all = findDeadCode(readScan());
|
|
34389
34750
|
const limit = num(args2.limit);
|
|
34390
34751
|
if (limit === void 0 || all.length <= limit) return JSON.stringify(all, null, 2);
|
|
34391
34752
|
return JSON.stringify({ total: all.length, shown: limit, truncated: true, candidates: all.slice(0, limit) }, null, 2);
|
|
34392
34753
|
}
|
|
34393
34754
|
if (name2 === "duplicated_literals") {
|
|
34394
|
-
const report = findLiteralDuplications(
|
|
34395
|
-
minFiles:
|
|
34396
|
-
minCount:
|
|
34755
|
+
const report = findLiteralDuplications(readScan(), {
|
|
34756
|
+
minFiles: positiveNum(args2.minFiles),
|
|
34757
|
+
minCount: positiveNum(args2.minCount),
|
|
34397
34758
|
includeTests: args2.includeTests === true
|
|
34398
34759
|
});
|
|
34399
34760
|
const limit = num(args2.limit);
|
|
@@ -34411,23 +34772,23 @@ async function callTool(name2, args2, defaultRepo) {
|
|
|
34411
34772
|
);
|
|
34412
34773
|
}
|
|
34413
34774
|
if (name2 === "complexity") {
|
|
34414
|
-
const scan2 =
|
|
34775
|
+
const scan2 = readScan();
|
|
34415
34776
|
if (args2.risk === true) {
|
|
34416
34777
|
const { churn, ok } = gitChurn(repo, { since: str(args2.since) });
|
|
34417
|
-
return JSON.stringify({ churnOk: ok, risks: riskHotspots(scan2, churn,
|
|
34778
|
+
return JSON.stringify({ churnOk: ok, risks: riskHotspots(scan2, churn, positiveNum(args2.top)) }, null, 2);
|
|
34418
34779
|
}
|
|
34419
|
-
return JSON.stringify(symbolComplexity(scan2, str(args2.file),
|
|
34780
|
+
return JSON.stringify(symbolComplexity(scan2, str(args2.file), positiveNum(args2.top)), null, 2);
|
|
34420
34781
|
}
|
|
34421
34782
|
if (name2 === "mermaid") {
|
|
34422
|
-
const { graph } =
|
|
34423
|
-
return renderMermaid(graph, { module: str(args2.module), maxEdges:
|
|
34783
|
+
const { graph } = readArtifacts();
|
|
34784
|
+
return renderMermaid(graph, { module: str(args2.module), maxEdges: positiveNum(args2.maxEdges) });
|
|
34424
34785
|
}
|
|
34425
34786
|
if (name2 === "onboard") {
|
|
34426
|
-
const scan2 =
|
|
34427
|
-
const { graph } =
|
|
34787
|
+
const scan2 = readScan();
|
|
34788
|
+
const { graph } = readArtifacts();
|
|
34428
34789
|
return JSON.stringify(
|
|
34429
34790
|
onboardBrief(scan2, graph, {
|
|
34430
|
-
...
|
|
34791
|
+
...positiveNum(args2.budgetTokens) !== void 0 ? { budgetTokens: positiveNum(args2.budgetTokens) } : {},
|
|
34431
34792
|
...args2.remember === false ? { remember: false } : {}
|
|
34432
34793
|
}),
|
|
34433
34794
|
null,
|
|
@@ -34435,11 +34796,11 @@ async function callTool(name2, args2, defaultRepo) {
|
|
|
34435
34796
|
);
|
|
34436
34797
|
}
|
|
34437
34798
|
if (name2 === "repo_map") {
|
|
34438
|
-
const { scan: scan2, graph } =
|
|
34439
|
-
return renderRepoMap(scan2, graph, { budgetTokens:
|
|
34799
|
+
const { scan: scan2, graph } = readArtifacts();
|
|
34800
|
+
return renderRepoMap(scan2, graph, { budgetTokens: positiveNum(args2.budgetTokens) });
|
|
34440
34801
|
}
|
|
34441
34802
|
if (name2 === "hotspots") {
|
|
34442
|
-
const scan2 =
|
|
34803
|
+
const scan2 = readScan();
|
|
34443
34804
|
const { churn, ok } = gitChurn(repo, { since: str(args2.since) });
|
|
34444
34805
|
return JSON.stringify({ churnOk: ok, hotspots: rankHotspots(scan2, churn) }, null, 2);
|
|
34445
34806
|
}
|
|
@@ -34455,15 +34816,15 @@ async function callTool(name2, args2, defaultRepo) {
|
|
|
34455
34816
|
const hits = grepRepo(repo, pattern, {
|
|
34456
34817
|
globs: scope ? [...globs ?? [], `${scope.replace(/\/+$/, "")}/**`] : globs,
|
|
34457
34818
|
ignoreCase: args2.ignoreCase === true,
|
|
34458
|
-
maxHits:
|
|
34819
|
+
maxHits: positiveNum(args2.maxHits)
|
|
34459
34820
|
});
|
|
34460
34821
|
return JSON.stringify(hits, null, 2);
|
|
34461
34822
|
}
|
|
34462
34823
|
if (name2 === "search") {
|
|
34463
34824
|
const query = str(args2.query);
|
|
34464
34825
|
if (!query) throw new Error("`query` is required");
|
|
34465
|
-
const scan2 =
|
|
34466
|
-
const limit =
|
|
34826
|
+
const scan2 = readScan();
|
|
34827
|
+
const limit = num(args2.limit);
|
|
34467
34828
|
const fuzzy = typeof args2.fuzzy === "boolean" ? args2.fuzzy : void 0;
|
|
34468
34829
|
const exactOpt = args2.exact === true ? { exact: true } : {};
|
|
34469
34830
|
if (args2.semantic === true) {
|
|
@@ -34506,8 +34867,8 @@ async function callTool(name2, args2, defaultRepo) {
|
|
|
34506
34867
|
if (name2 === "explain_search") {
|
|
34507
34868
|
const query = str(args2.query);
|
|
34508
34869
|
if (!query) throw new Error("`query` is required");
|
|
34509
|
-
const scan2 =
|
|
34510
|
-
const limit =
|
|
34870
|
+
const scan2 = readScan();
|
|
34871
|
+
const limit = num(args2.limit);
|
|
34511
34872
|
const fuzzy = typeof args2.fuzzy === "boolean" ? args2.fuzzy : void 0;
|
|
34512
34873
|
const { results, explain } = explainQuery(scan2, query, {
|
|
34513
34874
|
limit,
|
|
@@ -34532,7 +34893,7 @@ async function callTool(name2, args2, defaultRepo) {
|
|
|
34532
34893
|
return JSON.stringify(status, null, 2);
|
|
34533
34894
|
}
|
|
34534
34895
|
if (name2 === "type_hierarchy") {
|
|
34535
|
-
const hierarchy = hierarchyFor(
|
|
34896
|
+
const hierarchy = hierarchyFor(readScan());
|
|
34536
34897
|
const wanted = str(args2.name);
|
|
34537
34898
|
if (!wanted) {
|
|
34538
34899
|
const obj = {};
|
|
@@ -34546,7 +34907,7 @@ async function callTool(name2, args2, defaultRepo) {
|
|
|
34546
34907
|
if (name2 === "implementations") {
|
|
34547
34908
|
const wanted = str(args2.name);
|
|
34548
34909
|
if (!wanted) throw new Error("`name` is required");
|
|
34549
|
-
const hierarchy = hierarchyFor(
|
|
34910
|
+
const hierarchy = hierarchyFor(readScan());
|
|
34550
34911
|
if (!hierarchy.has(wanted)) return JSON.stringify({ error: `no type named ${wanted}` }, null, 2);
|
|
34551
34912
|
return JSON.stringify({ name: wanted, implementations: implementationsOf(hierarchy, wanted) }, null, 2);
|
|
34552
34913
|
}
|
|
@@ -34555,8 +34916,8 @@ async function callTool(name2, args2, defaultRepo) {
|
|
|
34555
34916
|
if (!symbol) throw new Error("`symbol` is required");
|
|
34556
34917
|
const direction = str(args2.direction);
|
|
34557
34918
|
const dir = direction === "out" || direction === "in" ? direction : "both";
|
|
34558
|
-
const result = neighborhood(symbolGraphFor(
|
|
34559
|
-
...
|
|
34919
|
+
const result = neighborhood(symbolGraphFor(readScan()), symbol, {
|
|
34920
|
+
...positiveNum(args2.depth) !== void 0 ? { depth: positiveNum(args2.depth) } : {},
|
|
34560
34921
|
direction: dir
|
|
34561
34922
|
});
|
|
34562
34923
|
if (!result.root.length) return JSON.stringify({ error: `no symbol named ${symbol}` }, null, 2);
|
|
@@ -34575,7 +34936,7 @@ async function callTool(name2, args2, defaultRepo) {
|
|
|
34575
34936
|
}
|
|
34576
34937
|
if (payload === void 0) throw new Error("`rules` (or `configPath`) is required");
|
|
34577
34938
|
const rules = parseRules(payload);
|
|
34578
|
-
const { graph } =
|
|
34939
|
+
const { graph } = readArtifacts();
|
|
34579
34940
|
return JSON.stringify(checkRules(graph, rules), null, 2);
|
|
34580
34941
|
}
|
|
34581
34942
|
throw new Error(`unknown tool: ${name2}`);
|
|
@@ -34587,31 +34948,81 @@ async function runMcpServer(opts = {}) {
|
|
|
34587
34948
|
};
|
|
34588
34949
|
let protocolVersion = PROTOCOL_VERSIONS[0];
|
|
34589
34950
|
let tools = toolsFor(opts.defaultRepo, protocolVersion, opts.profile);
|
|
34951
|
+
let watcher;
|
|
34952
|
+
if (opts.watch && opts.defaultRepo) {
|
|
34953
|
+
try {
|
|
34954
|
+
watcher = watchFs(opts.defaultRepo, { recursive: true }, (_event, filename) => {
|
|
34955
|
+
const rel2 = filename?.toString().replaceAll("\\", "/") ?? "";
|
|
34956
|
+
const ignored = rel2.split("/").some(
|
|
34957
|
+
(segment) => IGNORE_DIRS.has(segment) || segment.startsWith(".codeindex-edit-")
|
|
34958
|
+
);
|
|
34959
|
+
if (ignored) return;
|
|
34960
|
+
sessionInvalidate(opts.defaultRepo, rel2 || void 0);
|
|
34961
|
+
});
|
|
34962
|
+
watcher.on("error", (error) => {
|
|
34963
|
+
process.stderr.write(`codeindex: MCP watcher disabled (${error.message}); using freshness scans
|
|
34964
|
+
`);
|
|
34965
|
+
watcher?.close();
|
|
34966
|
+
watcher = void 0;
|
|
34967
|
+
sessionInvalidate(opts.defaultRepo);
|
|
34968
|
+
});
|
|
34969
|
+
} catch (error) {
|
|
34970
|
+
process.stderr.write(
|
|
34971
|
+
`codeindex: MCP watcher unavailable (${error instanceof Error ? error.message : String(error)}); using freshness scans
|
|
34972
|
+
`
|
|
34973
|
+
);
|
|
34974
|
+
}
|
|
34975
|
+
}
|
|
34590
34976
|
const send = (msg) => {
|
|
34591
|
-
|
|
34977
|
+
const wire = Array.isArray(msg) ? msg.map((entry) => ({ jsonrpc: "2.0", ...entry })) : { jsonrpc: "2.0", ...msg };
|
|
34978
|
+
process.stdout.write(JSON.stringify(wire) + "\n");
|
|
34592
34979
|
};
|
|
34593
34980
|
const rl = createInterface({ input: process.stdin, terminal: false });
|
|
34594
|
-
|
|
34595
|
-
const
|
|
34596
|
-
|
|
34597
|
-
|
|
34598
|
-
|
|
34599
|
-
|
|
34600
|
-
|
|
34601
|
-
|
|
34602
|
-
|
|
34981
|
+
try {
|
|
34982
|
+
for await (const line of rl) {
|
|
34983
|
+
const trimmed = line.trim();
|
|
34984
|
+
if (!trimmed) continue;
|
|
34985
|
+
let parsed;
|
|
34986
|
+
try {
|
|
34987
|
+
parsed = JSON.parse(trimmed);
|
|
34988
|
+
} catch {
|
|
34989
|
+
send({ id: null, error: { code: -32700, message: "parse error" } });
|
|
34990
|
+
continue;
|
|
34991
|
+
}
|
|
34992
|
+
if (Array.isArray(parsed) && parsed.length === 0) {
|
|
34993
|
+
send({ id: null, error: { code: -32600, message: "invalid request" } });
|
|
34994
|
+
continue;
|
|
34995
|
+
}
|
|
34996
|
+
const dispatch2 = async (req) => {
|
|
34997
|
+
if (isRpcResponse(req)) return void 0;
|
|
34998
|
+
if (!isRpcRequest(req)) {
|
|
34999
|
+
return { id: null, error: { code: -32600, message: "invalid request" } };
|
|
35000
|
+
}
|
|
35001
|
+
return handle2(req);
|
|
35002
|
+
};
|
|
35003
|
+
if (Array.isArray(parsed)) {
|
|
35004
|
+
const replies = [];
|
|
35005
|
+
for (const req of parsed) {
|
|
35006
|
+
const reply = await dispatch2(req);
|
|
35007
|
+
if (reply) replies.push(reply);
|
|
35008
|
+
}
|
|
35009
|
+
if (replies.length > 0) send(replies);
|
|
35010
|
+
} else {
|
|
35011
|
+
const reply = await dispatch2(parsed);
|
|
35012
|
+
if (reply) send(reply);
|
|
35013
|
+
}
|
|
34603
35014
|
}
|
|
34604
|
-
|
|
34605
|
-
|
|
35015
|
+
} finally {
|
|
35016
|
+
watcher?.close();
|
|
34606
35017
|
}
|
|
34607
35018
|
async function handle2(req) {
|
|
34608
|
-
|
|
35019
|
+
const notification = !("id" in req);
|
|
35020
|
+
const respond = (body22) => notification ? void 0 : { id: req.id ?? null, ...body22 };
|
|
34609
35021
|
try {
|
|
34610
35022
|
if (req.method === "initialize") {
|
|
34611
35023
|
protocolVersion = negotiateProtocol(req.params?.protocolVersion);
|
|
34612
35024
|
tools = toolsFor(opts.defaultRepo, protocolVersion, opts.profile);
|
|
34613
|
-
|
|
34614
|
-
id: req.id,
|
|
35025
|
+
return respond({
|
|
34615
35026
|
result: {
|
|
34616
35027
|
protocolVersion,
|
|
34617
35028
|
capabilities: { tools: {} },
|
|
@@ -34619,9 +35030,9 @@ async function runMcpServer(opts = {}) {
|
|
|
34619
35030
|
}
|
|
34620
35031
|
});
|
|
34621
35032
|
} else if (req.method === "ping") {
|
|
34622
|
-
|
|
35033
|
+
return respond({ result: {} });
|
|
34623
35034
|
} else if (req.method === "tools/list") {
|
|
34624
|
-
|
|
35035
|
+
return respond({ result: { tools } });
|
|
34625
35036
|
} else if (req.method === "tools/call") {
|
|
34626
35037
|
const params = req.params ?? {};
|
|
34627
35038
|
const name2 = str(params.name) ?? "";
|
|
@@ -34638,24 +35049,22 @@ async function runMcpServer(opts = {}) {
|
|
|
34638
35049
|
const capped = text !== raw;
|
|
34639
35050
|
const link = capped && protocolVersion >= RICH_TOOLS_SINCE ? resourceLinkFor(text, name2) : void 0;
|
|
34640
35051
|
const structured = protocolVersion >= RICH_TOOLS_SINCE ? structuredContentFor(text, capped, OUTPUT_SCHEMAS[name2] !== void 0) : void 0;
|
|
34641
|
-
|
|
34642
|
-
id: req.id,
|
|
35052
|
+
return respond({
|
|
34643
35053
|
result: {
|
|
34644
35054
|
content: link ? [{ type: "text", text }, link] : [{ type: "text", text }],
|
|
34645
35055
|
...structured ? { structuredContent: structured } : {}
|
|
34646
35056
|
}
|
|
34647
35057
|
});
|
|
34648
35058
|
} catch (e) {
|
|
34649
|
-
|
|
34650
|
-
id: req.id,
|
|
35059
|
+
return respond({
|
|
34651
35060
|
result: { content: [{ type: "text", text: e instanceof Error ? e.message : String(e) }], isError: true }
|
|
34652
35061
|
});
|
|
34653
35062
|
}
|
|
34654
35063
|
} else {
|
|
34655
|
-
|
|
35064
|
+
return respond({ error: { code: -32601, message: `method not found: ${req.method}` } });
|
|
34656
35065
|
}
|
|
34657
35066
|
} catch (e) {
|
|
34658
|
-
|
|
35067
|
+
return respond({ error: { code: -32603, message: e instanceof Error ? e.message : String(e) } });
|
|
34659
35068
|
}
|
|
34660
35069
|
}
|
|
34661
35070
|
}
|
|
@@ -34707,8 +35116,7 @@ var init_mcp = __esm({
|
|
|
34707
35116
|
"delete_memory",
|
|
34708
35117
|
"embed_status",
|
|
34709
35118
|
// scan_summary counts and classifies by path only — it never parses, so the
|
|
34710
|
-
// grammar warm (a whole extra walk) would be pure overhead.
|
|
34711
|
-
// already cached getScanSummary reuses it, warm grammars included.
|
|
35119
|
+
// grammar warm (a whole extra walk) would be pure overhead.
|
|
34712
35120
|
"scan_summary"
|
|
34713
35121
|
]);
|
|
34714
35122
|
}
|
|
@@ -34832,129 +35240,7 @@ init_walk();
|
|
|
34832
35240
|
init_scan();
|
|
34833
35241
|
init_scan();
|
|
34834
35242
|
init_preload();
|
|
34835
|
-
|
|
34836
|
-
init_walk();
|
|
34837
|
-
init_registry();
|
|
34838
|
-
init_loader();
|
|
34839
|
-
init_scan();
|
|
34840
|
-
function resolveEngineUrl() {
|
|
34841
|
-
try {
|
|
34842
|
-
const here = fileURLToPath2(import.meta.url);
|
|
34843
|
-
if (here.endsWith("engine.mjs")) return pathToFileURL(here).href;
|
|
34844
|
-
const adjacent = join4(dirname2(here), "engine.mjs");
|
|
34845
|
-
if (existsSync2(adjacent)) return pathToFileURL(adjacent).href;
|
|
34846
|
-
return void 0;
|
|
34847
|
-
} catch {
|
|
34848
|
-
return void 0;
|
|
34849
|
-
}
|
|
34850
|
-
}
|
|
34851
|
-
var WORKER_TIMEOUT_MS = 10 * 60 * 1e3;
|
|
34852
|
-
function workerCount(requested) {
|
|
34853
|
-
const env = process.env["CODEINDEX_WORKERS"];
|
|
34854
|
-
const raw = requested ?? (env !== void 0 && env !== "" ? Number(env) : void 0);
|
|
34855
|
-
if (raw !== void 0) return Number.isFinite(raw) && raw > 0 ? Math.floor(raw) : 0;
|
|
34856
|
-
let cores = 1;
|
|
34857
|
-
try {
|
|
34858
|
-
cores = availableParallelism();
|
|
34859
|
-
} catch {
|
|
34860
|
-
cores = 1;
|
|
34861
|
-
}
|
|
34862
|
-
return Math.max(0, Math.min(cores - 1, 8));
|
|
34863
|
-
}
|
|
34864
|
-
async function runExtractWorker(input, post) {
|
|
34865
|
-
await ensureGrammars(input.grammarKeys);
|
|
34866
|
-
const ready = input.grammarKeys.filter((k) => grammarReady(k));
|
|
34867
|
-
const records = [];
|
|
34868
|
-
for (const job of input.jobs) {
|
|
34869
|
-
let size;
|
|
34870
|
-
let mtimeMs;
|
|
34871
|
-
try {
|
|
34872
|
-
const st = statSync2(job.abs);
|
|
34873
|
-
size = st.size;
|
|
34874
|
-
mtimeMs = st.mtimeMs;
|
|
34875
|
-
} catch {
|
|
34876
|
-
continue;
|
|
34877
|
-
}
|
|
34878
|
-
const content = readText2(job.abs);
|
|
34879
|
-
const record = buildCodeRecord(job.rel, job.ext, size, content, sha1(content), extToLang(job.ext), {
|
|
34880
|
-
maxCallsPerFile: input.maxCallsPerFile
|
|
34881
|
-
});
|
|
34882
|
-
records.push({ rel: job.rel, size, mtimeMs, record });
|
|
34883
|
-
}
|
|
34884
|
-
post({ ready, records });
|
|
34885
|
-
}
|
|
34886
|
-
async function extractInParallel(jobs, grammarKeys, count, opts = {}) {
|
|
34887
|
-
if (count < 2 || jobs.length === 0) return void 0;
|
|
34888
|
-
const engineUrl = resolveEngineUrl();
|
|
34889
|
-
if (!engineUrl) return void 0;
|
|
34890
|
-
const wanted = grammarKeys.filter((k) => grammarReady(k)).sort();
|
|
34891
|
-
const shards = Array.from({ length: Math.min(count, jobs.length) }, () => []);
|
|
34892
|
-
jobs.forEach((j, i2) => shards[i2 % shards.length].push(j));
|
|
34893
|
-
const bootstrap = `import { runExtractWorker } from ${JSON.stringify(engineUrl)};
|
|
34894
|
-
import { parentPort, workerData } from "node:worker_threads";
|
|
34895
|
-
runExtractWorker(workerData.input, (o) => parentPort.postMessage(o)).catch((e) => parentPort.postMessage({ error: String(e) }));
|
|
34896
|
-
`;
|
|
34897
|
-
try {
|
|
34898
|
-
const outputs = await Promise.all(
|
|
34899
|
-
shards.map(
|
|
34900
|
-
(jobsForShard) => new Promise((resolve52, reject) => {
|
|
34901
|
-
const w = new Worker(bootstrap, {
|
|
34902
|
-
eval: true,
|
|
34903
|
-
workerData: { input: { jobs: jobsForShard, grammarKeys: wanted, maxCallsPerFile: opts.maxCallsPerFile } }
|
|
34904
|
-
});
|
|
34905
|
-
const timer = setTimeout(() => {
|
|
34906
|
-
reject(new Error("extraction worker timed out"));
|
|
34907
|
-
void w.terminate();
|
|
34908
|
-
}, WORKER_TIMEOUT_MS);
|
|
34909
|
-
const settle = (fn) => {
|
|
34910
|
-
clearTimeout(timer);
|
|
34911
|
-
fn();
|
|
34912
|
-
};
|
|
34913
|
-
w.once("message", (m) => {
|
|
34914
|
-
settle(() => resolve52(m));
|
|
34915
|
-
void w.terminate();
|
|
34916
|
-
});
|
|
34917
|
-
w.once("error", (e) => settle(() => reject(e)));
|
|
34918
|
-
w.once("exit", (code2) => {
|
|
34919
|
-
if (code2 !== 0) settle(() => reject(new Error(`extraction worker exited with ${code2}`)));
|
|
34920
|
-
});
|
|
34921
|
-
})
|
|
34922
|
-
)
|
|
34923
|
-
);
|
|
34924
|
-
const out2 = /* @__PURE__ */ new Map();
|
|
34925
|
-
for (const o of outputs) {
|
|
34926
|
-
if ("error" in o) return void 0;
|
|
34927
|
-
if (o.ready.slice().sort().join(",") !== wanted.join(",")) return void 0;
|
|
34928
|
-
for (const r of o.records) out2.set(r.rel, { size: r.size, mtimeMs: r.mtimeMs, record: r.record });
|
|
34929
|
-
}
|
|
34930
|
-
return out2;
|
|
34931
|
-
} catch {
|
|
34932
|
-
return void 0;
|
|
34933
|
-
}
|
|
34934
|
-
}
|
|
34935
|
-
async function scanRepoParallel(root, opts = {}) {
|
|
34936
|
-
const count = workerCount(opts.workers);
|
|
34937
|
-
if (count < 2) return scanRepo(root, opts);
|
|
34938
|
-
const walked = opts.precomputedWalk ?? walk(root, {
|
|
34939
|
-
maxFileBytes: opts.maxBytes,
|
|
34940
|
-
maxFiles: opts.maxFiles,
|
|
34941
|
-
gitignore: opts.gitignore,
|
|
34942
|
-
ignoreDirs: opts.ignoreDirs
|
|
34943
|
-
});
|
|
34944
|
-
const scanOpts = { ...opts, precomputedWalk: walked };
|
|
34945
|
-
const jobs = [];
|
|
34946
|
-
for (const { f } of keptCodeFiles(root, scanOpts)) {
|
|
34947
|
-
const cached = opts.cache?.get(f.rel);
|
|
34948
|
-
if (!opts.fullHash && cached && cached.size !== void 0 && cached.mtimeMs !== void 0 && cached.size === f.size && cached.mtimeMs === f.mtimeMs) {
|
|
34949
|
-
continue;
|
|
34950
|
-
}
|
|
34951
|
-
jobs.push({ abs: f.abs, rel: f.rel, ext: f.ext });
|
|
34952
|
-
}
|
|
34953
|
-
if (jobs.length === 0) return scanRepo(root, scanOpts);
|
|
34954
|
-
const grammarKeys = grammarKeysForExts(walked.files.map((f) => f.ext));
|
|
34955
|
-
const extracted = await extractInParallel(jobs, grammarKeys, count, { maxCallsPerFile: opts.maxCallsPerFile });
|
|
34956
|
-
return scanRepo(root, extracted ? { ...scanOpts, extracted } : scanOpts);
|
|
34957
|
-
}
|
|
35243
|
+
init_pool();
|
|
34958
35244
|
init_glob();
|
|
34959
35245
|
init_ignore();
|
|
34960
35246
|
init_classify();
|
|
@@ -35251,6 +35537,64 @@ function extractGrammarsTarball(bytes, destDir) {
|
|
|
35251
35537
|
const raw = b.length >= 2 && b[0] === 31 && b[1] === 139 ? gunzipSync(b) : b;
|
|
35252
35538
|
return extractTarInto(raw, destDir);
|
|
35253
35539
|
}
|
|
35540
|
+
function installGrammarCacheAtomically(tempDir, cacheDir, markerPath, expectedSha256, rename = renameSync, cleanup = rmSync) {
|
|
35541
|
+
const parent = dirname3(cacheDir);
|
|
35542
|
+
const swapDir = mkdtempSync(join6(parent, ".grammars-swap-"));
|
|
35543
|
+
const previousCache = join6(swapDir, "previous-cache");
|
|
35544
|
+
const previousMarker = join6(swapDir, "previous-marker");
|
|
35545
|
+
const nextMarker = join6(swapDir, "next-marker");
|
|
35546
|
+
let cacheBackedUp = false;
|
|
35547
|
+
let markerBackedUp = false;
|
|
35548
|
+
let cacheInstalled = false;
|
|
35549
|
+
let markerInstalled = false;
|
|
35550
|
+
try {
|
|
35551
|
+
if (expectedSha256) writeFileSync(nextMarker, expectedSha256 + "\n");
|
|
35552
|
+
if (existsSync4(cacheDir)) {
|
|
35553
|
+
rename(cacheDir, previousCache);
|
|
35554
|
+
cacheBackedUp = true;
|
|
35555
|
+
}
|
|
35556
|
+
if (existsSync4(markerPath)) {
|
|
35557
|
+
rename(markerPath, previousMarker);
|
|
35558
|
+
markerBackedUp = true;
|
|
35559
|
+
}
|
|
35560
|
+
rename(tempDir, cacheDir);
|
|
35561
|
+
cacheInstalled = true;
|
|
35562
|
+
if (expectedSha256) {
|
|
35563
|
+
rename(nextMarker, markerPath);
|
|
35564
|
+
markerInstalled = true;
|
|
35565
|
+
}
|
|
35566
|
+
} catch (error) {
|
|
35567
|
+
const rollbackErrors = [];
|
|
35568
|
+
const attempt = (operation) => {
|
|
35569
|
+
try {
|
|
35570
|
+
operation();
|
|
35571
|
+
} catch (rollback) {
|
|
35572
|
+
rollbackErrors.push(rollback);
|
|
35573
|
+
}
|
|
35574
|
+
};
|
|
35575
|
+
if (markerInstalled && existsSync4(markerPath)) attempt(() => rmSync(markerPath, { force: true }));
|
|
35576
|
+
if (cacheInstalled && existsSync4(cacheDir)) attempt(() => rmSync(cacheDir, { recursive: true, force: true }));
|
|
35577
|
+
if (markerBackedUp && existsSync4(previousMarker)) attempt(() => rename(previousMarker, markerPath));
|
|
35578
|
+
if (cacheBackedUp && existsSync4(previousCache)) attempt(() => rename(previousCache, cacheDir));
|
|
35579
|
+
if (rollbackErrors.length === 0) {
|
|
35580
|
+
try {
|
|
35581
|
+
rmSync(swapDir, { recursive: true, force: true });
|
|
35582
|
+
} catch {
|
|
35583
|
+
}
|
|
35584
|
+
}
|
|
35585
|
+
if (rollbackErrors.length > 0) {
|
|
35586
|
+
const rollbackError = rollbackErrors[0];
|
|
35587
|
+
throw new Error(
|
|
35588
|
+
`${error instanceof Error ? error.message : String(error)}; rollback failed: ${rollbackError instanceof Error ? rollbackError.message : String(rollbackError)} (backup preserved at ${swapDir})`
|
|
35589
|
+
);
|
|
35590
|
+
}
|
|
35591
|
+
throw error;
|
|
35592
|
+
}
|
|
35593
|
+
try {
|
|
35594
|
+
cleanup(swapDir, { recursive: true, force: true });
|
|
35595
|
+
} catch {
|
|
35596
|
+
}
|
|
35597
|
+
}
|
|
35254
35598
|
async function pullGrammars(cacheDir, opts = {}) {
|
|
35255
35599
|
const note = opts.onNote ?? (() => {
|
|
35256
35600
|
});
|
|
@@ -35299,10 +35643,8 @@ async function pullGrammars(cacheDir, opts = {}) {
|
|
|
35299
35643
|
if (!existsSync4(join6(tmp, "web-tree-sitter.wasm"))) {
|
|
35300
35644
|
throw new Error("archive is missing web-tree-sitter.wasm");
|
|
35301
35645
|
}
|
|
35302
|
-
|
|
35303
|
-
renameSync(tmp, cacheDir);
|
|
35646
|
+
installGrammarCacheAtomically(tmp, cacheDir, markerPath, expected);
|
|
35304
35647
|
tmp = void 0;
|
|
35305
|
-
if (expected) writeFileSync(markerPath, expected + "\n");
|
|
35306
35648
|
} catch (e) {
|
|
35307
35649
|
if (tmp) {
|
|
35308
35650
|
try {
|
|
@@ -36066,6 +36408,7 @@ init_hash();
|
|
|
36066
36408
|
init_graph_json();
|
|
36067
36409
|
init_symbols_json();
|
|
36068
36410
|
init_scan();
|
|
36411
|
+
init_pool();
|
|
36069
36412
|
init_preload();
|
|
36070
36413
|
init_walk();
|
|
36071
36414
|
init_relations();
|
|
@@ -36192,7 +36535,8 @@ Commands:
|
|
|
36192
36535
|
advertises a named subset (all | orient | find | impact | edit |
|
|
36193
36536
|
risk, default all) \u2014 every advertised tool's schema costs an agent
|
|
36194
36537
|
context on EVERY turn, and a tool left out is still answerable
|
|
36195
|
-
when called by name
|
|
36538
|
+
when called by name; --watch enables proactive invalidation for a
|
|
36539
|
+
pinned repo while retaining per-request freshness verification
|
|
36196
36540
|
version Print the engine version
|
|
36197
36541
|
|
|
36198
36542
|
Flags (accepted before OR after the subcommand: '--repo X scan' and
|
|
@@ -36343,6 +36687,7 @@ function parseMcpFlags(argv) {
|
|
|
36343
36687
|
let name2;
|
|
36344
36688
|
let maxResponseBytes;
|
|
36345
36689
|
let profile;
|
|
36690
|
+
let watch = false;
|
|
36346
36691
|
for (let i2 = 0; i2 < argv.length; i2++) {
|
|
36347
36692
|
const a = argv[i2];
|
|
36348
36693
|
if (a === "--repo") {
|
|
@@ -36363,12 +36708,15 @@ function parseMcpFlags(argv) {
|
|
|
36363
36708
|
if (!v) throw new Error(`--tools requires a profile: ${profileNames().join(", ")}`);
|
|
36364
36709
|
toolsInProfiles(v);
|
|
36365
36710
|
profile = v === "all" ? void 0 : v;
|
|
36711
|
+
} else if (a === "--watch") {
|
|
36712
|
+
watch = true;
|
|
36366
36713
|
} else {
|
|
36367
36714
|
throw new Error(`unknown flag for \`mcp\`: ${a}`);
|
|
36368
36715
|
}
|
|
36369
36716
|
}
|
|
36370
36717
|
if (defaultRepo && !existsSync10(defaultRepo)) throw new Error(`--repo path does not exist: ${defaultRepo}`);
|
|
36371
|
-
|
|
36718
|
+
if (watch && !defaultRepo) throw new Error("--watch requires --repo <dir>");
|
|
36719
|
+
return { defaultRepo, serverInfo: name2 ? { name: name2 } : void 0, maxResponseBytes, profile, watch };
|
|
36372
36720
|
}
|
|
36373
36721
|
var VALUE_FLAGS = /* @__PURE__ */ new Set([
|
|
36374
36722
|
"--repo",
|
|
@@ -36392,7 +36740,12 @@ var VALUE_FLAGS = /* @__PURE__ */ new Set([
|
|
|
36392
36740
|
"--tools",
|
|
36393
36741
|
"--workers",
|
|
36394
36742
|
"--index",
|
|
36395
|
-
"--max-response-bytes"
|
|
36743
|
+
"--max-response-bytes",
|
|
36744
|
+
"--base",
|
|
36745
|
+
"--depth",
|
|
36746
|
+
"--kind",
|
|
36747
|
+
"--rank",
|
|
36748
|
+
"--direction"
|
|
36396
36749
|
]);
|
|
36397
36750
|
function hoistLeadingFlags(argv) {
|
|
36398
36751
|
const lead = [];
|
|
@@ -36438,6 +36791,7 @@ async function runCli(rawArgv) {
|
|
|
36438
36791
|
}
|
|
36439
36792
|
const flags2 = parseFlags(rest);
|
|
36440
36793
|
if (!existsSync10(flags2.repo)) throw new Error(`--repo path does not exist: ${flags2.repo}`);
|
|
36794
|
+
if (!statSync9(flags2.repo).isDirectory()) throw new Error(`--repo path is not a directory: ${flags2.repo}`);
|
|
36441
36795
|
const scans = !SCANLESS_COMMANDS.has(cmd) && !(cmd === "embed" && flags2.positional !== "build");
|
|
36442
36796
|
let precomputedWalk;
|
|
36443
36797
|
if (scans && !flags2.noAst) {
|
|
@@ -36447,25 +36801,45 @@ async function runCli(rawArgv) {
|
|
|
36447
36801
|
gitignore: flags2.gitignore,
|
|
36448
36802
|
ignoreDirs: flags2.ignoreDirs.length ? flags2.ignoreDirs : void 0
|
|
36449
36803
|
});
|
|
36450
|
-
await ensureGrammars(grammarKeysForExts(precomputedWalk.files.map((f) => f.ext)));
|
|
36451
36804
|
}
|
|
36805
|
+
let grammarsWarmed = false;
|
|
36806
|
+
const warmPresentGrammars = async () => {
|
|
36807
|
+
if (grammarsWarmed || flags2.noAst || !precomputedWalk) return;
|
|
36808
|
+
await ensureGrammars(grammarKeysForExts(precomputedWalk.files.map((f) => f.ext)));
|
|
36809
|
+
grammarsWarmed = true;
|
|
36810
|
+
};
|
|
36452
36811
|
const indexDir = flags2.indexDir ?? INDEX_DIR;
|
|
36453
36812
|
let preloadTried = false;
|
|
36813
|
+
let preloadPromise;
|
|
36454
36814
|
let preloaded;
|
|
36455
|
-
const tryPreload = () => {
|
|
36815
|
+
const tryPreload = async () => {
|
|
36816
|
+
if (preloadPromise) return preloadPromise;
|
|
36456
36817
|
if (preloadTried) return preloaded;
|
|
36457
36818
|
preloadTried = true;
|
|
36458
36819
|
if (flags2.noIndexCache) return void 0;
|
|
36459
|
-
|
|
36460
|
-
|
|
36461
|
-
|
|
36820
|
+
preloadPromise = preloadSessionLazy(flags2.repo, scanOptions(flags2, precomputedWalk), warmPresentGrammars, indexDir).then((p) => {
|
|
36821
|
+
if (p) preloaded = { scan: p.scan, arts: p.arts, loadArtifacts: p.loadArtifacts };
|
|
36822
|
+
return preloaded;
|
|
36823
|
+
});
|
|
36824
|
+
return preloadPromise;
|
|
36462
36825
|
};
|
|
36463
|
-
|
|
36464
|
-
const
|
|
36465
|
-
const
|
|
36826
|
+
let readScanPromise;
|
|
36827
|
+
const readScan = async () => {
|
|
36828
|
+
const preloadedScan = (await tryPreload())?.scan;
|
|
36829
|
+
if (preloadedScan) return preloadedScan;
|
|
36830
|
+
return readScanPromise ??= warmPresentGrammars().then(
|
|
36831
|
+
() => scanRepoParallel(flags2.repo, {
|
|
36832
|
+
...scanOptions(flags2, precomputedWalk),
|
|
36833
|
+
workers: flags2.workers
|
|
36834
|
+
})
|
|
36835
|
+
);
|
|
36836
|
+
};
|
|
36837
|
+
let readArtifactsPromise;
|
|
36838
|
+
const readArtifacts = async () => {
|
|
36839
|
+
const p = await tryPreload();
|
|
36466
36840
|
if (p?.arts) return p.arts;
|
|
36467
|
-
if (p) return buildArtifactsFromScan(p.scan, scanOptions(flags2, precomputedWalk));
|
|
36468
|
-
return
|
|
36841
|
+
if (p) return p.arts ??= p.loadArtifacts?.() ?? buildArtifactsFromScan(p.scan, scanOptions(flags2, precomputedWalk));
|
|
36842
|
+
return readArtifactsPromise ??= readScan().then((scan2) => buildArtifactsFromScan(scan2, scanOptions(flags2, precomputedWalk)));
|
|
36469
36843
|
};
|
|
36470
36844
|
if (cmd === "index") {
|
|
36471
36845
|
if (!flags2.out) throw new Error("index needs --out <dir>");
|
|
@@ -36488,6 +36862,7 @@ async function runCli(rawArgv) {
|
|
|
36488
36862
|
}
|
|
36489
36863
|
} catch {
|
|
36490
36864
|
}
|
|
36865
|
+
await warmPresentGrammars();
|
|
36491
36866
|
const scan2 = await scanRepoParallel(flags2.repo, {
|
|
36492
36867
|
...scanOptions(flags2, precomputedWalk),
|
|
36493
36868
|
cache,
|
|
@@ -36566,13 +36941,13 @@ async function runCli(rawArgv) {
|
|
|
36566
36941
|
};
|
|
36567
36942
|
emit(JSON.stringify(summary, null, 2) + "\n", flags2.out);
|
|
36568
36943
|
} else if (cmd === "graph") {
|
|
36569
|
-
const { graph } = readArtifacts();
|
|
36944
|
+
const { graph } = await readArtifacts();
|
|
36570
36945
|
emit(renderGraphJson(graph), flags2.out);
|
|
36571
36946
|
} else if (cmd === "symbols") {
|
|
36572
|
-
const { symbols } = readArtifacts();
|
|
36947
|
+
const { symbols } = await readArtifacts();
|
|
36573
36948
|
emit(renderSymbolsJson(symbols), flags2.out);
|
|
36574
36949
|
} else if (cmd === "scip") {
|
|
36575
|
-
const scan2 = readScan();
|
|
36950
|
+
const scan2 = await readScan();
|
|
36576
36951
|
const bytes = renderScip(scan2, { projectRoot: flags2.projectRoot });
|
|
36577
36952
|
const out2 = flags2.out ?? resolve4("index.scip");
|
|
36578
36953
|
if (out2 === "-") process.stdout.write(Buffer.from(bytes));
|
|
@@ -36582,13 +36957,13 @@ async function runCli(rawArgv) {
|
|
|
36582
36957
|
`);
|
|
36583
36958
|
}
|
|
36584
36959
|
} else if (cmd === "callers") {
|
|
36585
|
-
const scan2 = readScan();
|
|
36960
|
+
const scan2 = await readScan();
|
|
36586
36961
|
const index = buildCallerIndex(scan2, void 0, { recall: flags2.recall });
|
|
36587
36962
|
const obj = {};
|
|
36588
36963
|
for (const [name2, entry] of index) obj[name2] = entry;
|
|
36589
36964
|
emit(JSON.stringify(obj, null, 2) + "\n", flags2.out);
|
|
36590
36965
|
} else if (cmd === "hierarchy") {
|
|
36591
|
-
const scan2 = readScan();
|
|
36966
|
+
const scan2 = await readScan();
|
|
36592
36967
|
const hierarchy = buildTypeHierarchy(scan2, computeImportPairs(scan2));
|
|
36593
36968
|
if (flags2.positional) {
|
|
36594
36969
|
const entry = hierarchy.get(flags2.positional);
|
|
@@ -36601,7 +36976,7 @@ async function runCli(rawArgv) {
|
|
|
36601
36976
|
}
|
|
36602
36977
|
} else if (cmd === "implementations") {
|
|
36603
36978
|
if (!flags2.positional) throw new Error("implementations needs a type name: cli.mjs implementations <Name> --repo <dir>");
|
|
36604
|
-
const scan2 = readScan();
|
|
36979
|
+
const scan2 = await readScan();
|
|
36605
36980
|
const hierarchy = buildTypeHierarchy(scan2, computeImportPairs(scan2));
|
|
36606
36981
|
if (!hierarchy.has(flags2.positional)) throw new Error(`no type named ${flags2.positional}`);
|
|
36607
36982
|
emit(
|
|
@@ -36610,7 +36985,7 @@ async function runCli(rawArgv) {
|
|
|
36610
36985
|
);
|
|
36611
36986
|
} else if (cmd === "callgraph") {
|
|
36612
36987
|
if (!flags2.positional) throw new Error("callgraph needs a symbol: cli.mjs callgraph <Symbol> --repo <dir>");
|
|
36613
|
-
const scan2 = readScan();
|
|
36988
|
+
const scan2 = await readScan();
|
|
36614
36989
|
const graph = buildSymbolGraph(scan2, computeImportPairs(scan2));
|
|
36615
36990
|
const result = neighborhood(graph, flags2.positional, {
|
|
36616
36991
|
...flags2.depth !== void 0 ? { depth: flags2.depth } : {},
|
|
@@ -36620,7 +36995,7 @@ async function runCli(rawArgv) {
|
|
|
36620
36995
|
emit(JSON.stringify(result, null, 2) + "\n", flags2.out);
|
|
36621
36996
|
} else if (cmd === "search") {
|
|
36622
36997
|
if (!flags2.positional) throw new Error('search needs a query: cli.mjs search "<query>" --repo <dir>');
|
|
36623
|
-
const scan2 = readScan();
|
|
36998
|
+
const scan2 = await readScan();
|
|
36624
36999
|
const searchOpts = {
|
|
36625
37000
|
limit: flags2.limit,
|
|
36626
37001
|
fuzzy: flags2.fuzzy,
|
|
@@ -36725,7 +37100,7 @@ async function runCli(rawArgv) {
|
|
|
36725
37100
|
}
|
|
36726
37101
|
const model = loadEmbedModel(modelDir);
|
|
36727
37102
|
mkdirSync3(flags2.out, { recursive: true });
|
|
36728
|
-
const scan2 = readScan();
|
|
37103
|
+
const scan2 = await readScan();
|
|
36729
37104
|
const index = buildEmbeddingIndex(scan2, model);
|
|
36730
37105
|
writeFileSync4(join23(flags2.out, "embeddings.bin"), serializeEmbeddings(index));
|
|
36731
37106
|
process.stderr.write(`codeindex: ${index.records.length} embedding records \u2192 ${flags2.out}/embeddings.bin (model ${model.modelId})
|
|
@@ -36764,7 +37139,7 @@ async function runCli(rawArgv) {
|
|
|
36764
37139
|
} else if (cmd === "lsp") {
|
|
36765
37140
|
const sub = flags2.positional;
|
|
36766
37141
|
if (sub !== "status") throw new Error("lsp needs a subcommand: status");
|
|
36767
|
-
emit(JSON.stringify(await lspStatus(readScan(), flags2.repo, flags2.probe === true), null, 2) + "\n", flags2.out);
|
|
37142
|
+
emit(JSON.stringify(await lspStatus(await readScan(), flags2.repo, flags2.probe === true), null, 2) + "\n", flags2.out);
|
|
36768
37143
|
} else if (cmd === "grammars") {
|
|
36769
37144
|
const sub = flags2.positional;
|
|
36770
37145
|
const cacheDir = sharedGrammarsCacheDir();
|
|
@@ -36803,7 +37178,7 @@ async function runCli(rawArgv) {
|
|
|
36803
37178
|
} else if (cmd === "rules") {
|
|
36804
37179
|
if (!flags2.config) throw new Error("rules needs --config <codeindex.rules.json>");
|
|
36805
37180
|
const rules = parseRules(JSON.parse(readFileSync13(flags2.config, "utf8")));
|
|
36806
|
-
const { graph } = readArtifacts();
|
|
37181
|
+
const { graph } = await readArtifacts();
|
|
36807
37182
|
const violations = checkRules(graph, rules);
|
|
36808
37183
|
const errors = violations.filter((v) => v.severity === "error").length;
|
|
36809
37184
|
emit(JSON.stringify({ errors, warnings: violations.length - errors, violations }, null, 2) + "\n", flags2.out);
|
|
@@ -36824,33 +37199,33 @@ async function runCli(rawArgv) {
|
|
|
36824
37199
|
for (const k of [...churn.keys()].sort()) sorted[k] = churn.get(k);
|
|
36825
37200
|
emit(JSON.stringify({ ok, churn: sorted }, null, 2) + "\n", flags2.out);
|
|
36826
37201
|
} else if (cmd === "repomap") {
|
|
36827
|
-
const { scan: scan2, graph } = readArtifacts();
|
|
37202
|
+
const { scan: scan2, graph } = await readArtifacts();
|
|
36828
37203
|
emit(renderRepoMap(scan2, graph, { budgetTokens: flags2.budgetTokens }), flags2.out);
|
|
36829
37204
|
} else if (cmd === "hotspots") {
|
|
36830
|
-
const scan2 = readScan();
|
|
37205
|
+
const scan2 = await readScan();
|
|
36831
37206
|
const { churn, ok } = gitChurn(flags2.repo, { since: flags2.since });
|
|
36832
37207
|
emit(JSON.stringify({ churnOk: ok, hotspots: rankHotspots(scan2, churn) }, null, 2) + "\n", flags2.out);
|
|
36833
37208
|
} else if (cmd === "coupling") {
|
|
36834
37209
|
const { ok, couplings } = changeCoupling(flags2.repo, { since: flags2.since });
|
|
36835
37210
|
emit(JSON.stringify({ ok, couplings }, null, 2) + "\n", flags2.out);
|
|
36836
37211
|
} else if (cmd === "deadcode") {
|
|
36837
|
-
emit(JSON.stringify(findDeadCode(readScan()), null, 2) + "\n", flags2.out);
|
|
37212
|
+
emit(JSON.stringify(findDeadCode(await readScan()), null, 2) + "\n", flags2.out);
|
|
36838
37213
|
} else if (cmd === "literals") {
|
|
36839
|
-
const report = findLiteralDuplications(readScan(), {
|
|
37214
|
+
const report = findLiteralDuplications(await readScan(), {
|
|
36840
37215
|
minFiles: flags2.minFiles,
|
|
36841
37216
|
minCount: flags2.minCount,
|
|
36842
37217
|
includeTests: flags2.includeTests
|
|
36843
37218
|
});
|
|
36844
37219
|
emit(JSON.stringify(report, null, 2) + "\n", flags2.out);
|
|
36845
37220
|
} else if (cmd === "complexity") {
|
|
36846
|
-
const scan2 = readScan();
|
|
37221
|
+
const scan2 = await readScan();
|
|
36847
37222
|
emit(JSON.stringify(symbolComplexity(scan2, flags2.positional), null, 2) + "\n", flags2.out);
|
|
36848
37223
|
} else if (cmd === "risk") {
|
|
36849
|
-
const scan2 = readScan();
|
|
37224
|
+
const scan2 = await readScan();
|
|
36850
37225
|
const { churn, ok } = gitChurn(flags2.repo, { since: flags2.since });
|
|
36851
37226
|
emit(JSON.stringify({ churnOk: ok, risks: riskHotspots(scan2, churn) }, null, 2) + "\n", flags2.out);
|
|
36852
37227
|
} else if (cmd === "delta") {
|
|
36853
|
-
const { graph, symbols } = readArtifacts();
|
|
37228
|
+
const { graph, symbols } = await readArtifacts();
|
|
36854
37229
|
const res = deltaFor(flags2.repo, graph, symbols, {
|
|
36855
37230
|
base: flags2.base,
|
|
36856
37231
|
staged: flags2.staged,
|
|
@@ -36860,19 +37235,19 @@ async function runCli(rawArgv) {
|
|
|
36860
37235
|
emit(flags2.json ? JSON.stringify(res, null, 2) + "\n" : formatDeltaPanel(res), flags2.out);
|
|
36861
37236
|
} else if (cmd === "impact") {
|
|
36862
37237
|
if (!flags2.positional) throw new Error("impact needs a target: cli.mjs impact <file|module> --repo <dir>");
|
|
36863
|
-
const { graph } = readArtifacts();
|
|
37238
|
+
const { graph } = await readArtifacts();
|
|
36864
37239
|
const res = impactOf(graph, flags2.positional, flags2.depth ?? Infinity);
|
|
36865
37240
|
if (!res) throw new Error(`no such file or module in the index: ${flags2.positional}`);
|
|
36866
37241
|
emit(JSON.stringify(res, null, 2) + "\n", flags2.out);
|
|
36867
37242
|
} else if (cmd === "neighbors") {
|
|
36868
37243
|
if (!flags2.positional) throw new Error("neighbors needs a target: cli.mjs neighbors <file|module> --repo <dir>");
|
|
36869
|
-
const { graph } = readArtifacts();
|
|
37244
|
+
const { graph } = await readArtifacts();
|
|
36870
37245
|
const kinds = flags2.kind ? new Set(flags2.kind.split(",").map((k) => k.trim()).filter(Boolean)) : void 0;
|
|
36871
37246
|
const res = neighborsOf(graph, flags2.positional, flags2.depth ?? 1, kinds);
|
|
36872
37247
|
if (!res) throw new Error(`no such file or module in the index: ${flags2.positional}`);
|
|
36873
37248
|
emit(JSON.stringify(res, null, 2) + "\n", flags2.out);
|
|
36874
37249
|
} else if (cmd === "mermaid") {
|
|
36875
|
-
const { graph } = readArtifacts();
|
|
37250
|
+
const { graph } = await readArtifacts();
|
|
36876
37251
|
emit(renderMermaid(graph, { module: flags2.positional }), flags2.out);
|
|
36877
37252
|
} else if (cmd === "grep") {
|
|
36878
37253
|
if (!flags2.positional) throw new Error("grep needs a pattern: cli.mjs grep <pattern> --repo <dir>");
|
|
@@ -36976,7 +37351,7 @@ function expandInputs(inputs, opts = {}) {
|
|
|
36976
37351
|
const acc = walkCached(staticBase(input), opts);
|
|
36977
37352
|
for (const f of acc) if (match(toPosix(f)) && exts.has(ext(f))) files.add(f);
|
|
36978
37353
|
} else if (existsSync11(input)) {
|
|
36979
|
-
if (
|
|
37354
|
+
if (statSync10(input).isDirectory()) {
|
|
36980
37355
|
const acc = walkCached(input, opts);
|
|
36981
37356
|
for (const f of acc) if (exts.has(ext(f))) files.add(f);
|
|
36982
37357
|
} else if (exts.has(ext(input))) {
|
|
@@ -37151,7 +37526,7 @@ function parseSourceWithAst(source, file, opts = {}) {
|
|
|
37151
37526
|
|
|
37152
37527
|
// src/snapshot.ts
|
|
37153
37528
|
import { existsSync as existsSync12, mkdirSync as mkdirSync4, readFileSync as readFileSync14, readdirSync as readdirSync4, writeFileSync as writeFileSync5 } from "fs";
|
|
37154
|
-
import { dirname as
|
|
37529
|
+
import { dirname as dirname6, join as join25 } from "path";
|
|
37155
37530
|
|
|
37156
37531
|
// src/collector.ts
|
|
37157
37532
|
var COLLECTED_CSS = [
|
|
@@ -37476,7 +37851,7 @@ function align(doc, entries) {
|
|
|
37476
37851
|
}
|
|
37477
37852
|
function attachSignals(doc) {
|
|
37478
37853
|
if (!isSnapshotDom(doc.file)) return;
|
|
37479
|
-
const dir =
|
|
37854
|
+
const dir = dirname6(doc.file);
|
|
37480
37855
|
const styles = readJson2(join25(dir, "styles.json"));
|
|
37481
37856
|
const boxes = readJson2(join25(dir, "boxes.json"));
|
|
37482
37857
|
const axtree = readJson2(join25(dir, "axtree.json"));
|
|
@@ -50827,7 +51202,7 @@ function crossToFinding(doc, ruleId, def, cf) {
|
|
|
50827
51202
|
import { resolve as absPath } from "path";
|
|
50828
51203
|
|
|
50829
51204
|
// src/graph/resolve.ts
|
|
50830
|
-
import { dirname as
|
|
51205
|
+
import { dirname as dirname7, join as join26 } from "path";
|
|
50831
51206
|
var EXT_ORDER = [".tsx", ".jsx", ".ts", ".js"];
|
|
50832
51207
|
function candidates(base) {
|
|
50833
51208
|
const out2 = [base];
|
|
@@ -50849,7 +51224,7 @@ function matchKnown(base, known) {
|
|
|
50849
51224
|
}
|
|
50850
51225
|
function resolveSpecifier(fromFile, spec, known, aliases) {
|
|
50851
51226
|
if (spec.startsWith(".")) {
|
|
50852
|
-
return matchKnown(join26(
|
|
51227
|
+
return matchKnown(join26(dirname7(toPosix(fromFile)), spec), known);
|
|
50853
51228
|
}
|
|
50854
51229
|
if (aliases?.length) {
|
|
50855
51230
|
for (const rule of aliases) {
|
|
@@ -50873,7 +51248,7 @@ function resolveSpecifier(fromFile, spec, known, aliases) {
|
|
|
50873
51248
|
|
|
50874
51249
|
// src/graph/tsconfig.ts
|
|
50875
51250
|
import { existsSync as existsSync13, readFileSync as readFileSync16 } from "fs";
|
|
50876
|
-
import { dirname as
|
|
51251
|
+
import { dirname as dirname8, join as join27, resolve as resolve5, relative } from "path";
|
|
50877
51252
|
function readJsonish(path) {
|
|
50878
51253
|
try {
|
|
50879
51254
|
const raw = readFileSync16(path, "utf8").replace(/\/\*[\s\S]*?\*\//g, "").replace(/(^|[^:])\/\/[^\n]*/g, "$1").replace(/,(\s*[}\]])/g, "$1");
|
|
@@ -50887,7 +51262,7 @@ function findTsconfig(startDir) {
|
|
|
50887
51262
|
for (let i2 = 0; i2 < 30; i2++) {
|
|
50888
51263
|
const p = join27(dir, "tsconfig.json");
|
|
50889
51264
|
if (existsSync13(p)) return p;
|
|
50890
|
-
const parent =
|
|
51265
|
+
const parent = dirname8(dir);
|
|
50891
51266
|
if (parent === dir) break;
|
|
50892
51267
|
dir = parent;
|
|
50893
51268
|
}
|
|
@@ -50907,7 +51282,7 @@ function tsconfigChain(startDir) {
|
|
|
50907
51282
|
out2.push(p);
|
|
50908
51283
|
const cfg = readJsonish(p);
|
|
50909
51284
|
const exts = Array.isArray(cfg?.extends) ? cfg.extends : typeof cfg?.extends === "string" ? [cfg.extends] : [];
|
|
50910
|
-
const dir =
|
|
51285
|
+
const dir = dirname8(p);
|
|
50911
51286
|
for (const e of exts) {
|
|
50912
51287
|
if (typeof e !== "string") continue;
|
|
50913
51288
|
const cands = e.endsWith(".json") ? [resolve5(dir, e)] : [resolve5(dir, `${e}.json`), resolve5(dir, e, "tsconfig.json")];
|
|
@@ -50920,7 +51295,7 @@ function tsconfigChain(startDir) {
|
|
|
50920
51295
|
function readTsAliases(startDir, cwd = process.cwd()) {
|
|
50921
51296
|
const tsconfigPath = findTsconfig(startDir);
|
|
50922
51297
|
if (!tsconfigPath) return [];
|
|
50923
|
-
const root =
|
|
51298
|
+
const root = dirname8(tsconfigPath);
|
|
50924
51299
|
const cfg = readJsonish(tsconfigPath);
|
|
50925
51300
|
if (!cfg) return [];
|
|
50926
51301
|
let co = cfg.compilerOptions ?? {};
|
|
@@ -51378,7 +51753,7 @@ function runPackRules(doc, pack) {
|
|
|
51378
51753
|
}
|
|
51379
51754
|
|
|
51380
51755
|
// src/graph/build.ts
|
|
51381
|
-
import { dirname as
|
|
51756
|
+
import { dirname as dirname9 } from "path";
|
|
51382
51757
|
|
|
51383
51758
|
// src/graph/imports.ts
|
|
51384
51759
|
var NAME_PROPS2 = /* @__PURE__ */ new Set(["aria-label", "aria-labelledby", "title", "label", "alt"]);
|
|
@@ -51676,7 +52051,7 @@ function buildGraphAndDocs(files, opts = {}) {
|
|
|
51676
52051
|
}
|
|
51677
52052
|
nodes.push(extractGraphNode(ast, doc, file, { sfc }));
|
|
51678
52053
|
}
|
|
51679
|
-
const startDir = files[0] ?
|
|
52054
|
+
const startDir = files[0] ? dirname9(files[0]) : process.cwd();
|
|
51680
52055
|
return { graph: buildGraph2(nodes, readTsAliases(startDir), startDir), docs };
|
|
51681
52056
|
}
|
|
51682
52057
|
|
|
@@ -52498,7 +52873,7 @@ function baselineSummary(diff, lang = "fr") {
|
|
|
52498
52873
|
}
|
|
52499
52874
|
|
|
52500
52875
|
// src/config.ts
|
|
52501
|
-
import { existsSync as existsSync16, statSync as
|
|
52876
|
+
import { existsSync as existsSync16, statSync as statSync11 } from "fs";
|
|
52502
52877
|
import { join as join29, isAbsolute as isAbsolute2 } from "path";
|
|
52503
52878
|
|
|
52504
52879
|
// src/pack.ts
|
|
@@ -56645,7 +57020,7 @@ function loadConfig(cwd) {
|
|
|
56645
57020
|
}
|
|
56646
57021
|
function packPaths(path) {
|
|
56647
57022
|
if (!existsSync16(path)) return null;
|
|
56648
|
-
if (
|
|
57023
|
+
if (statSync11(path).isDirectory()) {
|
|
56649
57024
|
const pack = join29(path, "pack.json");
|
|
56650
57025
|
if (!existsSync16(pack)) return null;
|
|
56651
57026
|
const glossary = join29(path, "glossary.json");
|
|
@@ -60310,7 +60685,7 @@ function renderCriteriaReference() {
|
|
|
60310
60685
|
|
|
60311
60686
|
// src/check.ts
|
|
60312
60687
|
import { existsSync as existsSync21, readFileSync as readFileSync19, readdirSync as readdirSync5 } from "fs";
|
|
60313
|
-
import { dirname as
|
|
60688
|
+
import { dirname as dirname10, join as join34 } from "path";
|
|
60314
60689
|
|
|
60315
60690
|
// src/verify.ts
|
|
60316
60691
|
import { existsSync as existsSync19, mkdirSync as mkdirSync8, readFileSync as readFileSync17, writeFileSync as writeFileSync9 } from "fs";
|
|
@@ -60874,7 +61249,7 @@ function checkSemantic(md, opts) {
|
|
|
60874
61249
|
const standard = opts.standard ?? "wcag";
|
|
60875
61250
|
const s = M[lang];
|
|
60876
61251
|
const empty = { total: 0, grounded: 0, moved: 0, failed: 0 };
|
|
60877
|
-
const artifact = opts.verdictsPath ?? join34(
|
|
61252
|
+
const artifact = opts.verdictsPath ?? join34(dirname10(opts.reportPath), "VERIFY.todo.json");
|
|
60878
61253
|
if (!existsSync21(artifact)) return { ok: false, issues: [s.semanticMissing(artifact)], ...empty };
|
|
60879
61254
|
let items;
|
|
60880
61255
|
try {
|
|
@@ -61087,7 +61462,7 @@ function openPerPage(audit2, standard, lang) {
|
|
|
61087
61462
|
}
|
|
61088
61463
|
|
|
61089
61464
|
// src/adjudicate.ts
|
|
61090
|
-
import { mkdirSync as mkdirSync9, statSync as
|
|
61465
|
+
import { mkdirSync as mkdirSync9, statSync as statSync12, writeFileSync as writeFileSync10 } from "fs";
|
|
61091
61466
|
import { isAbsolute as isAbsolute3, join as join35, relative as relative4, resolve as resolve10 } from "path";
|
|
61092
61467
|
|
|
61093
61468
|
// src/data/adjudication.json
|
|
@@ -62124,7 +62499,7 @@ function withinAuditInput(file, audit2, cwd) {
|
|
|
62124
62499
|
if (input === "-" || input === "<stdin>") continue;
|
|
62125
62500
|
const root = resolve10(cwd ?? process.cwd(), input);
|
|
62126
62501
|
try {
|
|
62127
|
-
if (
|
|
62502
|
+
if (statSync12(root).isDirectory()) {
|
|
62128
62503
|
const rel2 = relative4(root, target);
|
|
62129
62504
|
if (rel2 === "" || rel2 !== ".." && !rel2.startsWith("../") && !isAbsolute3(rel2)) return true;
|
|
62130
62505
|
} else if (root === target) return true;
|
|
@@ -63082,7 +63457,7 @@ function pruneRefuted(audit2, standard, items, lang = "en") {
|
|
|
63082
63457
|
// src/ledger.ts
|
|
63083
63458
|
import { createHash as createHash6 } from "crypto";
|
|
63084
63459
|
import { existsSync as existsSync22, mkdirSync as mkdirSync10, readFileSync as readFileSync20, writeFileSync as writeFileSync11 } from "fs";
|
|
63085
|
-
import { dirname as
|
|
63460
|
+
import { dirname as dirname11, join as join36 } from "path";
|
|
63086
63461
|
var LEDGER_DIR = ".ultra11y/verdicts";
|
|
63087
63462
|
function ledgerPath(standard, root = ".") {
|
|
63088
63463
|
return join36(root, LEDGER_DIR, `${standard}.json`);
|
|
@@ -63144,7 +63519,7 @@ function unreadableCaptures(audit2, cwd = ".") {
|
|
|
63144
63519
|
return (audit2.scope.pagesAudited ?? []).filter((id) => !existsSync22(join36(cwd, PAGES_DIR, id, "dom.html")));
|
|
63145
63520
|
}
|
|
63146
63521
|
function writeLedger(path, ledger) {
|
|
63147
|
-
mkdirSync10(
|
|
63522
|
+
mkdirSync10(dirname11(path), { recursive: true });
|
|
63148
63523
|
const sorted = { ...ledger, entries: [...ledger.entries].sort((a, b) => a.criteriaId.localeCompare(b.criteriaId, "en", { numeric: true })) };
|
|
63149
63524
|
writeFileSync11(path, `${JSON.stringify(sorted, null, 2)}
|
|
63150
63525
|
`);
|
|
@@ -63740,9 +64115,9 @@ async function runCli2(argv, prompt, opts, extract) {
|
|
|
63740
64115
|
|
|
63741
64116
|
// src/agent-codex.ts
|
|
63742
64117
|
import { spawn as spawn3 } from "child_process";
|
|
63743
|
-
import { existsSync as existsSync24, mkdtempSync as
|
|
64118
|
+
import { existsSync as existsSync24, mkdtempSync as mkdtempSync3, rmSync as rmSync4, writeFileSync as writeFileSync12 } from "fs";
|
|
63744
64119
|
import { tmpdir as tmpdir2 } from "os";
|
|
63745
|
-
import { delimiter as delimiter2, dirname as
|
|
64120
|
+
import { delimiter as delimiter2, dirname as dirname12, join as join38 } from "path";
|
|
63746
64121
|
var MAX_ATTEMPTS3 = 4;
|
|
63747
64122
|
var CODEX_EFFORT_LEVELS = ["minimal", "low", "medium", "high", "xhigh"];
|
|
63748
64123
|
var DEFAULT_CODEX_TIMEOUT_MS = 10 * 6e4;
|
|
@@ -63806,7 +64181,7 @@ function codexArgv(opts, schemaPath) {
|
|
|
63806
64181
|
"multi_agent",
|
|
63807
64182
|
"--strict-config",
|
|
63808
64183
|
"--cd",
|
|
63809
|
-
|
|
64184
|
+
dirname12(schemaPath),
|
|
63810
64185
|
"--skip-git-repo-check",
|
|
63811
64186
|
"--sandbox",
|
|
63812
64187
|
"read-only",
|
|
@@ -63893,7 +64268,7 @@ function transient(message) {
|
|
|
63893
64268
|
}
|
|
63894
64269
|
async function runCodex(schema, prompt, opts, extract) {
|
|
63895
64270
|
const run2 = opts.spawnImpl ?? realSpawn2;
|
|
63896
|
-
const dir =
|
|
64271
|
+
const dir = mkdtempSync3(join38(tmpdir2(), "ultra11y-codex-"));
|
|
63897
64272
|
const schemaPath = join38(dir, "schema.json");
|
|
63898
64273
|
writeFileSync12(schemaPath, `${JSON.stringify(schema)}
|
|
63899
64274
|
`, { mode: 384 });
|
|
@@ -63927,7 +64302,7 @@ async function runCodex(schema, prompt, opts, extract) {
|
|
|
63927
64302
|
return extract(env.result);
|
|
63928
64303
|
}
|
|
63929
64304
|
} finally {
|
|
63930
|
-
|
|
64305
|
+
rmSync4(dir, { recursive: true, force: true });
|
|
63931
64306
|
}
|
|
63932
64307
|
throw new Error(`ultra11y judge: ${lastError || "Codex failed after every attempt."}`);
|
|
63933
64308
|
}
|
|
@@ -63948,7 +64323,7 @@ async function refuteBatchCodex(items, prompt, opts, lang = "en") {
|
|
|
63948
64323
|
|
|
63949
64324
|
// src/scan.ts
|
|
63950
64325
|
import { execFileSync as execFileSync6 } from "child_process";
|
|
63951
|
-
import { mkdtempSync as
|
|
64326
|
+
import { mkdtempSync as mkdtempSync4, writeFileSync as writeFileSync13, existsSync as existsSync26, statSync as statSync13, readdirSync as readdirSync6, rmSync as rmSync5, readFileSync as readFileSync21 } from "fs";
|
|
63952
64327
|
import { tmpdir as tmpdir3 } from "os";
|
|
63953
64328
|
import { join as join39, resolve as resolve11 } from "path";
|
|
63954
64329
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
@@ -64291,14 +64666,14 @@ function imageExists(tag) {
|
|
|
64291
64666
|
}
|
|
64292
64667
|
var CTX_PREFIX = "ultra11y-dyn-";
|
|
64293
64668
|
function buildImage(tag = IMAGE_TAG) {
|
|
64294
|
-
const ctx =
|
|
64669
|
+
const ctx = mkdtempSync4(join39(tmpdir3(), CTX_PREFIX));
|
|
64295
64670
|
try {
|
|
64296
64671
|
writeFileSync13(join39(ctx, "runner.mjs"), RUNNER);
|
|
64297
64672
|
writeFileSync13(join39(ctx, "package.json"), PKG);
|
|
64298
64673
|
writeFileSync13(join39(ctx, "Dockerfile"), DOCKERFILE);
|
|
64299
64674
|
execFileSync6("docker", ["build", "-t", tag, ctx], { stdio: "inherit", timeout: 9e5 });
|
|
64300
64675
|
} finally {
|
|
64301
|
-
|
|
64676
|
+
rmSync5(ctx, { recursive: true, force: true });
|
|
64302
64677
|
}
|
|
64303
64678
|
}
|
|
64304
64679
|
function cleanTempContexts() {
|
|
@@ -64306,7 +64681,7 @@ function cleanTempContexts() {
|
|
|
64306
64681
|
const dir = tmpdir3();
|
|
64307
64682
|
for (const name2 of readdirSync6(dir)) {
|
|
64308
64683
|
if (!name2.startsWith(CTX_PREFIX)) continue;
|
|
64309
|
-
|
|
64684
|
+
rmSync5(join39(dir, name2), { recursive: true, force: true });
|
|
64310
64685
|
removed++;
|
|
64311
64686
|
}
|
|
64312
64687
|
return removed;
|
|
@@ -64518,7 +64893,7 @@ function runScan(opts) {
|
|
|
64518
64893
|
}
|
|
64519
64894
|
const tag = opts.tag ?? IMAGE_TAG;
|
|
64520
64895
|
if (!imageExists(tag)) buildImage(tag);
|
|
64521
|
-
const isFile = !isUrl3 && existsSync26(opts.target) &&
|
|
64896
|
+
const isFile = !isUrl3 && existsSync26(opts.target) && statSync13(opts.target).isFile();
|
|
64522
64897
|
const out2 = runRunner(opts.target, isFile, tag, Boolean(opts.snapshotRoot));
|
|
64523
64898
|
const id = opts.snapshotRoot ? writeRunnerSnapshot(opts.snapshotRoot, out2, opts.target) : void 0;
|
|
64524
64899
|
return { ...toDynamicResult(out2, opts.target), testedScs: [...DOCKER_TESTED_SCS], ...id ? { snapshots: [id] } : {} };
|
|
@@ -64797,7 +65172,7 @@ function mergeSnapshotAudit(base, snap) {
|
|
|
64797
65172
|
}
|
|
64798
65173
|
|
|
64799
65174
|
// src/scan-local.ts
|
|
64800
|
-
import { existsSync as existsSync27, statSync as
|
|
65175
|
+
import { existsSync as existsSync27, statSync as statSync14 } from "fs";
|
|
64801
65176
|
import { createRequire } from "module";
|
|
64802
65177
|
import { resolve as resolve12 } from "path";
|
|
64803
65178
|
|
|
@@ -64901,7 +65276,8 @@ function focusSetupExpr(scope = "", maxFocusables = PROBE_DEFAULTS.maxFocusables
|
|
|
64901
65276
|
const rootExpr = scope ? `document.querySelectorAll(${JSON.stringify(scope)})` : `[document.documentElement]`;
|
|
64902
65277
|
return `(() => { ${PRELUDE}
|
|
64903
65278
|
const sel = 'a[href],button:not([disabled]),input:not([type=hidden]):not([disabled]),select:not([disabled]),textarea:not([disabled]),[tabindex]:not([tabindex="-1"]),[role=button]:not([disabled])';
|
|
64904
|
-
const
|
|
65279
|
+
const __style = (e, pseudo) => { const s = getComputedStyle(e, pseudo); return [s.outlineStyle, s.outlineWidth, s.outlineColor, s.boxShadow, s.borderColor, s.borderTopWidth, s.borderBottomWidth, s.backgroundColor, s.color, s.textDecorationLine].join('|'); };
|
|
65280
|
+
const snap = (e) => [__style(e, null), __style(e, '::before'), __style(e, '::after')].join('#');
|
|
64905
65281
|
// Visually-hidden radio/checkbox \u2192 measure its visible label/proxy, not the input.
|
|
64906
65282
|
const proxyFor = (e) => {
|
|
64907
65283
|
const type = (e.getAttribute('type') || '').toLowerCase();
|
|
@@ -64943,8 +65319,12 @@ var FOCUS_CHECK_PROBE = `(() => {
|
|
|
64943
65319
|
if (!key || !window.__u11yF || !window.__u11yF[key]) return null;
|
|
64944
65320
|
const rec = window.__u11yF[key];
|
|
64945
65321
|
const proxy = document.querySelector('[data-u11y-fp="' + key + '"]') || e;
|
|
64946
|
-
|
|
64947
|
-
|
|
65322
|
+
// THE SAME THREE BOXES pass 1 snapshotted, in the same order. A design system that paints
|
|
65323
|
+
// its control in label::before -- DSFR, GOV.UK, USWDS, Bootstrap -- puts the focus ring
|
|
65324
|
+
// there too, and reading only the element would report every one of them as unfocusable.
|
|
65325
|
+
// (No backticks in this comment: it lives inside a template literal.)
|
|
65326
|
+
const st = (pseudo) => { const s = getComputedStyle(proxy, pseudo); return [s.outlineStyle, s.outlineWidth, s.outlineColor, s.boxShadow, s.borderColor, s.borderTopWidth, s.borderBottomWidth, s.backgroundColor, s.color, s.textDecorationLine].join('|'); };
|
|
65327
|
+
const now = [st(null), st('::before'), st('::after')].join('#');
|
|
64948
65328
|
return { key: key, changed: now !== rec.rest, selector: rec.sel, html: rec.html };
|
|
64949
65329
|
})()`;
|
|
64950
65330
|
var FOCUS_OBSCURED_PROBE = `(() => { ${PRELUDE}
|
|
@@ -65605,7 +65985,7 @@ async function runScanLocal(opts) {
|
|
|
65605
65985
|
if (!isUrl3 && !existsSync27(opts.target)) {
|
|
65606
65986
|
throw new Error(`File not found: ${opts.target}. Pass an http(s):// URL or an existing HTML file.`);
|
|
65607
65987
|
}
|
|
65608
|
-
const isFile = !isUrl3 &&
|
|
65988
|
+
const isFile = !isUrl3 && statSync14(opts.target).isFile();
|
|
65609
65989
|
const lang = opts.lang ?? "en";
|
|
65610
65990
|
const interact = opts.interact !== false;
|
|
65611
65991
|
const { chromium, AxeBuilder } = resolveLocalDeps(opts.cwd);
|
|
@@ -66252,7 +66632,7 @@ function fixSummary(r, lang = "fr", write = false, standard = CORE2) {
|
|
|
66252
66632
|
}
|
|
66253
66633
|
|
|
66254
66634
|
// src/init.ts
|
|
66255
|
-
import { writeFileSync as writeFileSync15, mkdirSync as mkdirSync11, chmodSync, realpathSync as
|
|
66635
|
+
import { writeFileSync as writeFileSync15, mkdirSync as mkdirSync11, chmodSync as chmodSync2, realpathSync as realpathSync3 } from "fs";
|
|
66256
66636
|
import { execFileSync as execFileSync7 } from "child_process";
|
|
66257
66637
|
import { join as join40, relative as relative5, sep as sep4 } from "path";
|
|
66258
66638
|
var EN_SEV = { bloquant: "blocking", majeur: "major", mineur: "minor" };
|
|
@@ -66266,7 +66646,7 @@ function repoRoot() {
|
|
|
66266
66646
|
function resolveEnginePath(root) {
|
|
66267
66647
|
const argv1 = process.argv[1] ?? "scripts/ultra11y.mjs";
|
|
66268
66648
|
try {
|
|
66269
|
-
const abs =
|
|
66649
|
+
const abs = realpathSync3(argv1);
|
|
66270
66650
|
return abs.startsWith(root + sep4) ? relative5(root, abs) : abs;
|
|
66271
66651
|
} catch {
|
|
66272
66652
|
return argv1;
|
|
@@ -66376,7 +66756,7 @@ function writeHook(root, enginePath, failOn, mode = "staged") {
|
|
|
66376
66756
|
mkdirSync11(dir, { recursive: true });
|
|
66377
66757
|
const path = join40(dir, "pre-commit");
|
|
66378
66758
|
writeFileSync15(path, mode === "baseline" ? hookScript(enginePath, failOn) : stagedHookScript(enginePath, failOn));
|
|
66379
|
-
|
|
66759
|
+
chmodSync2(path, 493);
|
|
66380
66760
|
return path;
|
|
66381
66761
|
}
|
|
66382
66762
|
function writeCi(root, enginePath, failOn) {
|
|
@@ -66388,8 +66768,8 @@ function writeCi(root, enginePath, failOn) {
|
|
|
66388
66768
|
}
|
|
66389
66769
|
|
|
66390
66770
|
// src/install/json-edit.ts
|
|
66391
|
-
import { copyFileSync as copyFileSync2, existsSync as existsSync28, mkdirSync as mkdirSync12, readFileSync as readFileSync23, renameSync as
|
|
66392
|
-
import { dirname as
|
|
66771
|
+
import { copyFileSync as copyFileSync2, existsSync as existsSync28, mkdirSync as mkdirSync12, readFileSync as readFileSync23, renameSync as renameSync3, rmSync as rmSync6, writeFileSync as writeFileSync16 } from "fs";
|
|
66772
|
+
import { dirname as dirname13 } from "path";
|
|
66393
66773
|
var SettingsParseError = class extends Error {
|
|
66394
66774
|
constructor(path, cause) {
|
|
66395
66775
|
super(`${path} is not valid JSON (${cause}) \u2014 fix or move it, then run install again. It has NOT been modified.`);
|
|
@@ -66403,7 +66783,7 @@ function stamp() {
|
|
|
66403
66783
|
}
|
|
66404
66784
|
function writeTextWithBackup(path, content, marker = "ultra11y") {
|
|
66405
66785
|
if (existsSync28(path) && readFileSync23(path, "utf8") === content) return { path, changed: false };
|
|
66406
|
-
mkdirSync12(
|
|
66786
|
+
mkdirSync12(dirname13(path), { recursive: true });
|
|
66407
66787
|
let backup;
|
|
66408
66788
|
if (existsSync28(path)) {
|
|
66409
66789
|
backup = `${path}.${marker}-backup-${stamp()}`;
|
|
@@ -66412,9 +66792,9 @@ function writeTextWithBackup(path, content, marker = "ultra11y") {
|
|
|
66412
66792
|
const tmp = `${path}.${process.pid}.tmp`;
|
|
66413
66793
|
try {
|
|
66414
66794
|
writeFileSync16(tmp, content, { mode: 420 });
|
|
66415
|
-
|
|
66795
|
+
renameSync3(tmp, path);
|
|
66416
66796
|
} catch (e) {
|
|
66417
|
-
|
|
66797
|
+
rmSync6(tmp, { force: true });
|
|
66418
66798
|
throw e;
|
|
66419
66799
|
}
|
|
66420
66800
|
return { path, changed: true, backup };
|
|
@@ -66485,7 +66865,7 @@ function claudeCodeWired(settingsPath) {
|
|
|
66485
66865
|
}
|
|
66486
66866
|
|
|
66487
66867
|
// src/install/text-edit.ts
|
|
66488
|
-
import { existsSync as existsSync29, readFileSync as readFileSync24, rmSync as
|
|
66868
|
+
import { existsSync as existsSync29, readFileSync as readFileSync24, rmSync as rmSync7 } from "fs";
|
|
66489
66869
|
var BLOCK_BEGIN = "<!-- BEGIN ultra11y (managed by `ultra11y install --agents-md`; edit outside this block) -->";
|
|
66490
66870
|
var BLOCK_END = "<!-- END ultra11y -->";
|
|
66491
66871
|
var blockRe = () => new RegExp(`${escapeRe2(BLOCK_BEGIN)}[\\s\\S]*?${escapeRe2(BLOCK_END)}\\n?`);
|
|
@@ -66509,7 +66889,7 @@ function removeManagedBlock(path) {
|
|
|
66509
66889
|
if (!blockRe().test(current)) return { path, changed: false };
|
|
66510
66890
|
const rest = current.replace(blockRe(), "");
|
|
66511
66891
|
if (rest.trim() === "") {
|
|
66512
|
-
|
|
66892
|
+
rmSync7(path, { force: true });
|
|
66513
66893
|
return { path, changed: true };
|
|
66514
66894
|
}
|
|
66515
66895
|
return writeTextWithBackup(path, rest.replace(/\n+$/, "\n"));
|
|
@@ -66580,9 +66960,9 @@ import { existsSync as existsSync31, readFileSync as readFileSync26 } from "fs";
|
|
|
66580
66960
|
import { join as join43 } from "path";
|
|
66581
66961
|
|
|
66582
66962
|
// src/install/paths.ts
|
|
66583
|
-
import { copyFileSync as copyFileSync3, cpSync, existsSync as existsSync30, mkdirSync as mkdirSync13, readFileSync as readFileSync25, realpathSync as
|
|
66963
|
+
import { copyFileSync as copyFileSync3, cpSync, existsSync as existsSync30, mkdirSync as mkdirSync13, readFileSync as readFileSync25, realpathSync as realpathSync4, statSync as statSync15 } from "fs";
|
|
66584
66964
|
import { homedir as homedir2 } from "os";
|
|
66585
|
-
import { dirname as
|
|
66965
|
+
import { dirname as dirname14, join as join42 } from "path";
|
|
66586
66966
|
function codexHome() {
|
|
66587
66967
|
return process.env.CODEX_HOME || join42(homedir2(), ".codex");
|
|
66588
66968
|
}
|
|
@@ -66602,7 +66982,7 @@ function installedCliCommand() {
|
|
|
66602
66982
|
const argv1 = process.argv[1];
|
|
66603
66983
|
let source = null;
|
|
66604
66984
|
try {
|
|
66605
|
-
if (argv1) source =
|
|
66985
|
+
if (argv1) source = realpathSync4(argv1);
|
|
66606
66986
|
} catch {
|
|
66607
66987
|
}
|
|
66608
66988
|
const ephemeral = !source || /[/\\](?:_npx|\.npm[/\\]_npx|npm-cache|Temp|tmp)[/\\]/.test(source);
|
|
@@ -66617,13 +66997,13 @@ function installedCliCommand() {
|
|
|
66617
66997
|
function packageRoot() {
|
|
66618
66998
|
let dir;
|
|
66619
66999
|
try {
|
|
66620
|
-
dir =
|
|
67000
|
+
dir = dirname14(realpathSync4(process.argv[1] ?? ""));
|
|
66621
67001
|
} catch {
|
|
66622
67002
|
return null;
|
|
66623
67003
|
}
|
|
66624
67004
|
for (let i2 = 0; i2 < 6 && dir && dir !== "/"; i2++) {
|
|
66625
67005
|
if (existsSync30(join42(dir, "skills", "review-a11y", "SKILL.md"))) return dir;
|
|
66626
|
-
dir =
|
|
67006
|
+
dir = dirname14(dir);
|
|
66627
67007
|
}
|
|
66628
67008
|
return null;
|
|
66629
67009
|
}
|
|
@@ -66647,7 +67027,7 @@ function copySkillsInto(source, dest) {
|
|
|
66647
67027
|
const a = join42(from, f);
|
|
66648
67028
|
const b = join42(to, f);
|
|
66649
67029
|
try {
|
|
66650
|
-
return existsSync30(b) &&
|
|
67030
|
+
return existsSync30(b) && statSync15(a).size === statSync15(b).size && readFileSync25(a).equals(readFileSync25(b));
|
|
66651
67031
|
} catch {
|
|
66652
67032
|
return false;
|
|
66653
67033
|
}
|
|
@@ -66751,7 +67131,7 @@ function codexHooksEnabled(codexDir) {
|
|
|
66751
67131
|
}
|
|
66752
67132
|
|
|
66753
67133
|
// src/install/opencode.ts
|
|
66754
|
-
import { existsSync as existsSync32, readFileSync as readFileSync27, rmSync as
|
|
67134
|
+
import { existsSync as existsSync32, readFileSync as readFileSync27, rmSync as rmSync8 } from "fs";
|
|
66755
67135
|
import { join as join44 } from "path";
|
|
66756
67136
|
var OPENCODE_MARKER = "ULTRA11Y_OPENCODE_PLUGIN";
|
|
66757
67137
|
function pluginTarget(configDir) {
|
|
@@ -66780,8 +67160,8 @@ function uninstallOpencode({ configDir }) {
|
|
|
66780
67160
|
const reports = [];
|
|
66781
67161
|
const target = pluginTarget(configDir);
|
|
66782
67162
|
if (existsSync32(target) && readFileSync27(target, "utf8").includes(OPENCODE_MARKER)) {
|
|
66783
|
-
|
|
66784
|
-
|
|
67163
|
+
rmSync8(target, { force: true });
|
|
67164
|
+
rmSync8(join44(configDir, "plugin", "ultra11y.mjs"), { force: true });
|
|
66785
67165
|
reports.push({ path: target, changed: true });
|
|
66786
67166
|
}
|
|
66787
67167
|
const configPath = join44(configDir, "opencode.json");
|
|
@@ -68126,7 +68506,7 @@ function writeEvidence(result, opts) {
|
|
|
68126
68506
|
}
|
|
68127
68507
|
|
|
68128
68508
|
// src/html-emit.ts
|
|
68129
|
-
import { mkdirSync as mkdirSync15, readFileSync as readFileSync29, statSync as
|
|
68509
|
+
import { mkdirSync as mkdirSync15, readFileSync as readFileSync29, statSync as statSync16, writeFileSync as writeFileSync18 } from "fs";
|
|
68130
68510
|
import { join as join47 } from "path";
|
|
68131
68511
|
|
|
68132
68512
|
// src/html.ts
|
|
@@ -68767,7 +69147,7 @@ var T5 = {
|
|
|
68767
69147
|
var mb = (n) => (n / (1024 * 1024)).toFixed(1);
|
|
68768
69148
|
function inlineSize(path) {
|
|
68769
69149
|
try {
|
|
68770
|
-
return Math.ceil(
|
|
69150
|
+
return Math.ceil(statSync16(path).size / 3) * 4;
|
|
68771
69151
|
} catch {
|
|
68772
69152
|
return 0;
|
|
68773
69153
|
}
|
|
@@ -68928,7 +69308,7 @@ function noticeRuns(notices) {
|
|
|
68928
69308
|
// src/dev.ts
|
|
68929
69309
|
import { createServer } from "http";
|
|
68930
69310
|
import { mkdirSync as mkdirSync16, readFileSync as readFileSync30, writeFileSync as writeFileSync19 } from "fs";
|
|
68931
|
-
import { dirname as
|
|
69311
|
+
import { dirname as dirname15, join as join48 } from "path";
|
|
68932
69312
|
var DEV_DEFAULT_PORT = 4111;
|
|
68933
69313
|
function criterionLabel3(f, standard) {
|
|
68934
69314
|
if (isCore(standard)) return `WCAG ${f.criteriaId}`;
|
|
@@ -69286,7 +69666,7 @@ function startDevServer(opts) {
|
|
|
69286
69666
|
let auditPath;
|
|
69287
69667
|
if (applied.ok) {
|
|
69288
69668
|
auditPath = join48(opts.root, "audits", "audit-latest.json");
|
|
69289
|
-
mkdirSync16(
|
|
69669
|
+
mkdirSync16(dirname15(auditPath), { recursive: true });
|
|
69290
69670
|
writeFileSync19(auditPath, `${JSON.stringify(applied.audit, null, 2)}
|
|
69291
69671
|
`);
|
|
69292
69672
|
}
|
|
@@ -69605,7 +69985,7 @@ function e2eSetupPlan(runners, paths, lang = "en") {
|
|
|
69605
69985
|
}
|
|
69606
69986
|
|
|
69607
69987
|
// src/orchestrate.ts
|
|
69608
|
-
import { existsSync as existsSync35, mkdirSync as mkdirSync17, readFileSync as readFileSync31, rmSync as
|
|
69988
|
+
import { existsSync as existsSync35, mkdirSync as mkdirSync17, readFileSync as readFileSync31, rmSync as rmSync9, writeFileSync as writeFileSync20 } from "fs";
|
|
69609
69989
|
import { join as join50, resolve as resolve13 } from "path";
|
|
69610
69990
|
|
|
69611
69991
|
// src/orchestrate-templates.ts
|
|
@@ -69990,7 +70370,7 @@ function orchestrateRun(runDir, engineAbs, opts = {}) {
|
|
|
69990
70370
|
if (emitted.has(ph.name)) continue;
|
|
69991
70371
|
const stale = join50(orchDir, `${ph.name}.workflow.mjs`);
|
|
69992
70372
|
if (existsSync35(stale)) {
|
|
69993
|
-
|
|
70373
|
+
rmSync9(stale, { force: true });
|
|
69994
70374
|
notices.push(`phase "${ph.name}": stale workflow removed \u2014 its worklist ${ph.ready ? "is now empty" : "no longer exists"}.`);
|
|
69995
70375
|
}
|
|
69996
70376
|
}
|
|
@@ -70018,7 +70398,7 @@ function orchestrateRun(runDir, engineAbs, opts = {}) {
|
|
|
70018
70398
|
import { createInterface as createInterface2 } from "readline";
|
|
70019
70399
|
|
|
70020
70400
|
// src/mcp/handlers.ts
|
|
70021
|
-
import { existsSync as existsSync36, readFileSync as readFileSync32, realpathSync as
|
|
70401
|
+
import { existsSync as existsSync36, readFileSync as readFileSync32, realpathSync as realpathSync5, statSync as statSync17 } from "fs";
|
|
70022
70402
|
import { isAbsolute as isAbsolute4, join as join51, resolve as resolve14, sep as sep5 } from "path";
|
|
70023
70403
|
|
|
70024
70404
|
// src/criteria-view.ts
|
|
@@ -70504,7 +70884,7 @@ function requiredCwd(args2, defaults) {
|
|
|
70504
70884
|
if (!cwd) throw new ToolError("`cwd` is required: an absolute path to the project root.");
|
|
70505
70885
|
const abs = resolve14(cwd);
|
|
70506
70886
|
if (!existsSync36(abs)) throw new ToolError(`project root not found: ${abs}`);
|
|
70507
|
-
if (!
|
|
70887
|
+
if (!statSync17(abs).isDirectory()) throw new ToolError(`\`cwd\` is not a directory: ${abs}`);
|
|
70508
70888
|
return abs;
|
|
70509
70889
|
}
|
|
70510
70890
|
function optionalCwd(args2, defaults) {
|
|
@@ -70924,15 +71304,15 @@ function handleRead(args2, cwd) {
|
|
|
70924
71304
|
const target = isAbsolute4(raw) ? raw : join51(cwd, raw);
|
|
70925
71305
|
let real;
|
|
70926
71306
|
try {
|
|
70927
|
-
real =
|
|
71307
|
+
real = realpathSync5(target);
|
|
70928
71308
|
} catch {
|
|
70929
71309
|
throw new ToolError(`no such file: ${raw}`);
|
|
70930
71310
|
}
|
|
70931
|
-
const root =
|
|
71311
|
+
const root = realpathSync5(cwd);
|
|
70932
71312
|
if (real !== root && !real.startsWith(root + sep5)) {
|
|
70933
71313
|
throw new ToolError(`path is outside the project: ${raw}. Use your own file tool for anything else.`);
|
|
70934
71314
|
}
|
|
70935
|
-
const st =
|
|
71315
|
+
const st = statSync17(real);
|
|
70936
71316
|
if (!st.isFile()) throw new ToolError(`not a file: ${raw}`);
|
|
70937
71317
|
if (st.size > MAX_READ_BYTES) throw new ToolError(`file is too large to read (${st.size} bytes): ${raw}`);
|
|
70938
71318
|
const lines = readFileSync32(real, "utf8").split("\n");
|
|
@@ -71590,13 +71970,13 @@ function str3(v) {
|
|
|
71590
71970
|
var DECLARED = new Set([...TOOLS2, ...WRITE_TOOLS].map((t3) => t3.name));
|
|
71591
71971
|
|
|
71592
71972
|
// src/mcp/resources.ts
|
|
71593
|
-
import { existsSync as existsSync37, readdirSync as readdirSync7, readFileSync as readFileSync33, realpathSync as
|
|
71594
|
-
import { basename as
|
|
71973
|
+
import { existsSync as existsSync37, readdirSync as readdirSync7, readFileSync as readFileSync33, realpathSync as realpathSync6, statSync as statSync18 } from "fs";
|
|
71974
|
+
import { basename as basename4, dirname as dirname16, join as join52, resolve as resolve15, sep as sep6 } from "path";
|
|
71595
71975
|
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
71596
71976
|
var SKILL_NAME = "ultra11y";
|
|
71597
71977
|
var URI_SCHEME = "skill://";
|
|
71598
71978
|
function resolveSkillRoot(moduleDir) {
|
|
71599
|
-
const here = moduleDir ??
|
|
71979
|
+
const here = moduleDir ?? dirname16(fileURLToPath4(import.meta.url));
|
|
71600
71980
|
const candidates2 = [resolve15(here, ".."), resolve15(here, "..", "skills", SKILL_NAME), resolve15(here, "..", "..", "skills", SKILL_NAME)];
|
|
71601
71981
|
return candidates2.find((dir) => existsSync37(join52(dir, "SKILL.md")));
|
|
71602
71982
|
}
|
|
@@ -71608,7 +71988,7 @@ function listResources(moduleDir) {
|
|
|
71608
71988
|
if (!existsSync37(refDir)) return out2;
|
|
71609
71989
|
for (const file of readdirSync7(refDir).sort()) {
|
|
71610
71990
|
if (!file.endsWith(".md")) continue;
|
|
71611
|
-
out2.push(describe(root, join52("references", file), `${SKILL_NAME} reference: ${
|
|
71991
|
+
out2.push(describe(root, join52("references", file), `${SKILL_NAME} reference: ${basename4(file, ".md")}`));
|
|
71612
71992
|
}
|
|
71613
71993
|
return out2;
|
|
71614
71994
|
}
|
|
@@ -71621,17 +72001,17 @@ function readResource(uri, moduleDir) {
|
|
|
71621
72001
|
const rel2 = uri.slice(URI_SCHEME.length);
|
|
71622
72002
|
if (!rel2) throw new ResourceError("empty resource path");
|
|
71623
72003
|
const target = resolve15(root, rel2);
|
|
71624
|
-
const rootReal =
|
|
72004
|
+
const rootReal = realpathSync6(root);
|
|
71625
72005
|
let targetReal;
|
|
71626
72006
|
try {
|
|
71627
|
-
targetReal =
|
|
72007
|
+
targetReal = realpathSync6(target);
|
|
71628
72008
|
} catch {
|
|
71629
72009
|
throw new ResourceError(`no such resource: ${uri}`);
|
|
71630
72010
|
}
|
|
71631
72011
|
if (targetReal !== rootReal && !targetReal.startsWith(rootReal + sep6)) {
|
|
71632
72012
|
throw new ResourceError(`resource path escapes the skill root: ${uri}`);
|
|
71633
72013
|
}
|
|
71634
|
-
if (!
|
|
72014
|
+
if (!statSync18(targetReal).isFile()) throw new ResourceError(`not a file: ${uri}`);
|
|
71635
72015
|
return { uri, mimeType: "text/markdown", text: readFileSync33(targetReal, "utf8") };
|
|
71636
72016
|
}
|
|
71637
72017
|
var ResourceError = class extends Error {
|
|
@@ -73077,7 +73457,7 @@ async function cmdAudit(p) {
|
|
|
73077
73457
|
const asFile = out2.toLowerCase().endsWith(".json");
|
|
73078
73458
|
const target = asFile ? out2 : join53(out2, "audit-latest.json");
|
|
73079
73459
|
try {
|
|
73080
|
-
mkdirSync18(asFile ?
|
|
73460
|
+
mkdirSync18(asFile ? dirname17(out2) : out2, { recursive: true });
|
|
73081
73461
|
writeFileSync21(target, JSON.stringify(document, null, 2) + "\n");
|
|
73082
73462
|
console.error(lang === "fr" ? `\u2192 audit \xE9crit dans ${target}` : `\u2192 audit written to ${target}`);
|
|
73083
73463
|
} catch {
|
|
@@ -74001,7 +74381,7 @@ function depsAt(root) {
|
|
|
74001
74381
|
function engineRefFor(root) {
|
|
74002
74382
|
let ref = process.argv[1] ?? "scripts/ultra11y.mjs";
|
|
74003
74383
|
try {
|
|
74004
|
-
const abs =
|
|
74384
|
+
const abs = realpathSync7(ref);
|
|
74005
74385
|
ref = abs.startsWith(root + sep7) ? relative6(root, abs) : abs;
|
|
74006
74386
|
} catch {
|
|
74007
74387
|
}
|
|
@@ -74064,7 +74444,7 @@ Fill in COMPONENTS, run it (e.g. npx tsx ${out2}), then: node scripts/ultra11y.m
|
|
|
74064
74444
|
const rel2 = ".ultra11y/capture-setup.mjs";
|
|
74065
74445
|
const out2 = join53(root, rel2);
|
|
74066
74446
|
try {
|
|
74067
|
-
mkdirSync18(
|
|
74447
|
+
mkdirSync18(dirname17(out2), { recursive: true });
|
|
74068
74448
|
writeFileSync21(out2, captureSetup());
|
|
74069
74449
|
} catch (e) {
|
|
74070
74450
|
console.error(`ultra11y render: could not write ${out2}: ${e instanceof Error ? e.message : String(e)}`);
|
|
@@ -75627,7 +76007,7 @@ function cmdOrchestrate(p) {
|
|
|
75627
76007
|
);
|
|
75628
76008
|
return 2;
|
|
75629
76009
|
}
|
|
75630
|
-
const engineAbs =
|
|
76010
|
+
const engineAbs = realpathSync7(fileURLToPath5(import.meta.url));
|
|
75631
76011
|
if (p.flags.list === true) {
|
|
75632
76012
|
if (!existsSync38(runFlag)) {
|
|
75633
76013
|
console.error(`ultra11y orchestrate: run dir not found: ${runFlag}.`);
|
|
@@ -75778,7 +76158,7 @@ function isInvokedDirectly() {
|
|
|
75778
76158
|
if (argv1 === void 0) return false;
|
|
75779
76159
|
const modulePath = fileURLToPath5(import.meta.url);
|
|
75780
76160
|
try {
|
|
75781
|
-
if (
|
|
76161
|
+
if (realpathSync7(argv1) === realpathSync7(modulePath)) return true;
|
|
75782
76162
|
} catch {
|
|
75783
76163
|
}
|
|
75784
76164
|
return import.meta.url === pathToFileURL3(argv1).href;
|