trace-mcp 1.22.0 → 1.23.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/dist/cli.js +1680 -892
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +5 -5
- package/dist/index.js +1166 -461
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -10,10 +10,10 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
|
|
|
10
10
|
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
11
11
|
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
12
12
|
});
|
|
13
|
-
var __glob = (map) => (
|
|
14
|
-
var fn2 = map[
|
|
13
|
+
var __glob = (map) => (path67) => {
|
|
14
|
+
var fn2 = map[path67];
|
|
15
15
|
if (fn2) return fn2();
|
|
16
|
-
throw new Error("Module not found in bundle: " +
|
|
16
|
+
throw new Error("Module not found in bundle: " + path67);
|
|
17
17
|
};
|
|
18
18
|
var __esm = (fn2, res) => function __init() {
|
|
19
19
|
return fn2 && (res = (0, fn2[__getOwnPropNames(fn2)[0]])(fn2 = 0)), res;
|
|
@@ -2637,27 +2637,27 @@ var require_process = __commonJS({
|
|
|
2637
2637
|
var require_filesystem = __commonJS({
|
|
2638
2638
|
"node_modules/detect-libc/lib/filesystem.js"(exports, module) {
|
|
2639
2639
|
"use strict";
|
|
2640
|
-
var
|
|
2640
|
+
var fs57 = __require("fs");
|
|
2641
2641
|
var LDD_PATH = "/usr/bin/ldd";
|
|
2642
2642
|
var SELF_PATH = "/proc/self/exe";
|
|
2643
2643
|
var MAX_LENGTH = 2048;
|
|
2644
|
-
var
|
|
2645
|
-
const fd =
|
|
2644
|
+
var readFileSync11 = (path67) => {
|
|
2645
|
+
const fd = fs57.openSync(path67, "r");
|
|
2646
2646
|
const buffer = Buffer.alloc(MAX_LENGTH);
|
|
2647
|
-
const bytesRead =
|
|
2648
|
-
|
|
2647
|
+
const bytesRead = fs57.readSync(fd, buffer, 0, MAX_LENGTH, 0);
|
|
2648
|
+
fs57.close(fd, () => {
|
|
2649
2649
|
});
|
|
2650
2650
|
return buffer.subarray(0, bytesRead);
|
|
2651
2651
|
};
|
|
2652
|
-
var readFile = (
|
|
2653
|
-
|
|
2652
|
+
var readFile = (path67) => new Promise((resolve3, reject) => {
|
|
2653
|
+
fs57.open(path67, "r", (err14, fd) => {
|
|
2654
2654
|
if (err14) {
|
|
2655
2655
|
reject(err14);
|
|
2656
2656
|
} else {
|
|
2657
2657
|
const buffer = Buffer.alloc(MAX_LENGTH);
|
|
2658
|
-
|
|
2658
|
+
fs57.read(fd, buffer, 0, MAX_LENGTH, 0, (_, bytesRead) => {
|
|
2659
2659
|
resolve3(buffer.subarray(0, bytesRead));
|
|
2660
|
-
|
|
2660
|
+
fs57.close(fd, () => {
|
|
2661
2661
|
});
|
|
2662
2662
|
});
|
|
2663
2663
|
}
|
|
@@ -2666,7 +2666,7 @@ var require_filesystem = __commonJS({
|
|
|
2666
2666
|
module.exports = {
|
|
2667
2667
|
LDD_PATH,
|
|
2668
2668
|
SELF_PATH,
|
|
2669
|
-
readFileSync:
|
|
2669
|
+
readFileSync: readFileSync11,
|
|
2670
2670
|
readFile
|
|
2671
2671
|
};
|
|
2672
2672
|
}
|
|
@@ -2715,7 +2715,7 @@ var require_detect_libc = __commonJS({
|
|
|
2715
2715
|
"use strict";
|
|
2716
2716
|
var childProcess = __require("child_process");
|
|
2717
2717
|
var { isLinux, getReport } = require_process();
|
|
2718
|
-
var { LDD_PATH, SELF_PATH, readFile, readFileSync:
|
|
2718
|
+
var { LDD_PATH, SELF_PATH, readFile, readFileSync: readFileSync11 } = require_filesystem();
|
|
2719
2719
|
var { interpreterPath } = require_elf();
|
|
2720
2720
|
var cachedFamilyInterpreter;
|
|
2721
2721
|
var cachedFamilyFilesystem;
|
|
@@ -2769,11 +2769,11 @@ var require_detect_libc = __commonJS({
|
|
|
2769
2769
|
}
|
|
2770
2770
|
return null;
|
|
2771
2771
|
};
|
|
2772
|
-
var familyFromInterpreterPath = (
|
|
2773
|
-
if (
|
|
2774
|
-
if (
|
|
2772
|
+
var familyFromInterpreterPath = (path67) => {
|
|
2773
|
+
if (path67) {
|
|
2774
|
+
if (path67.includes("/ld-musl-")) {
|
|
2775
2775
|
return MUSL;
|
|
2776
|
-
} else if (
|
|
2776
|
+
} else if (path67.includes("/ld-linux-")) {
|
|
2777
2777
|
return GLIBC;
|
|
2778
2778
|
}
|
|
2779
2779
|
}
|
|
@@ -2807,7 +2807,7 @@ var require_detect_libc = __commonJS({
|
|
|
2807
2807
|
}
|
|
2808
2808
|
cachedFamilyFilesystem = null;
|
|
2809
2809
|
try {
|
|
2810
|
-
const lddContent =
|
|
2810
|
+
const lddContent = readFileSync11(LDD_PATH);
|
|
2811
2811
|
cachedFamilyFilesystem = getFamilyFromLddContent(lddContent);
|
|
2812
2812
|
} catch (e) {
|
|
2813
2813
|
}
|
|
@@ -2820,8 +2820,8 @@ var require_detect_libc = __commonJS({
|
|
|
2820
2820
|
cachedFamilyInterpreter = null;
|
|
2821
2821
|
try {
|
|
2822
2822
|
const selfContent = await readFile(SELF_PATH);
|
|
2823
|
-
const
|
|
2824
|
-
cachedFamilyInterpreter = familyFromInterpreterPath(
|
|
2823
|
+
const path67 = interpreterPath(selfContent);
|
|
2824
|
+
cachedFamilyInterpreter = familyFromInterpreterPath(path67);
|
|
2825
2825
|
} catch (e) {
|
|
2826
2826
|
}
|
|
2827
2827
|
return cachedFamilyInterpreter;
|
|
@@ -2832,9 +2832,9 @@ var require_detect_libc = __commonJS({
|
|
|
2832
2832
|
}
|
|
2833
2833
|
cachedFamilyInterpreter = null;
|
|
2834
2834
|
try {
|
|
2835
|
-
const selfContent =
|
|
2836
|
-
const
|
|
2837
|
-
cachedFamilyInterpreter = familyFromInterpreterPath(
|
|
2835
|
+
const selfContent = readFileSync11(SELF_PATH);
|
|
2836
|
+
const path67 = interpreterPath(selfContent);
|
|
2837
|
+
cachedFamilyInterpreter = familyFromInterpreterPath(path67);
|
|
2838
2838
|
} catch (e) {
|
|
2839
2839
|
}
|
|
2840
2840
|
return cachedFamilyInterpreter;
|
|
@@ -2896,7 +2896,7 @@ var require_detect_libc = __commonJS({
|
|
|
2896
2896
|
}
|
|
2897
2897
|
cachedVersionFilesystem = null;
|
|
2898
2898
|
try {
|
|
2899
|
-
const lddContent =
|
|
2899
|
+
const lddContent = readFileSync11(LDD_PATH);
|
|
2900
2900
|
const versionMatch = lddContent.match(RE_GLIBC_VERSION);
|
|
2901
2901
|
if (versionMatch) {
|
|
2902
2902
|
cachedVersionFilesystem = versionMatch[1];
|
|
@@ -4553,18 +4553,18 @@ var require_sharp = __commonJS({
|
|
|
4553
4553
|
`@img/sharp-${runtimePlatform}/sharp.node`,
|
|
4554
4554
|
"@img/sharp-wasm32/sharp.node"
|
|
4555
4555
|
];
|
|
4556
|
-
var
|
|
4556
|
+
var path67;
|
|
4557
4557
|
var sharp2;
|
|
4558
4558
|
var errors = [];
|
|
4559
|
-
for (
|
|
4559
|
+
for (path67 of paths) {
|
|
4560
4560
|
try {
|
|
4561
|
-
sharp2 = __require(
|
|
4561
|
+
sharp2 = __require(path67);
|
|
4562
4562
|
break;
|
|
4563
4563
|
} catch (err14) {
|
|
4564
4564
|
errors.push(err14);
|
|
4565
4565
|
}
|
|
4566
4566
|
}
|
|
4567
|
-
if (sharp2 &&
|
|
4567
|
+
if (sharp2 && path67.startsWith("@img/sharp-linux-x64") && !sharp2._isUsingX64V2()) {
|
|
4568
4568
|
const err14 = new Error("Prebuilt binaries for linux-x64 require v2 microarchitecture");
|
|
4569
4569
|
err14.code = "Unsupported CPU";
|
|
4570
4570
|
errors.push(err14);
|
|
@@ -7475,15 +7475,15 @@ var require_color = __commonJS({
|
|
|
7475
7475
|
};
|
|
7476
7476
|
}
|
|
7477
7477
|
function wrapConversion(toModel, graph) {
|
|
7478
|
-
const
|
|
7478
|
+
const path67 = [graph[toModel].parent, toModel];
|
|
7479
7479
|
let fn2 = conversions_default[graph[toModel].parent][toModel];
|
|
7480
7480
|
let cur = graph[toModel].parent;
|
|
7481
7481
|
while (graph[cur].parent) {
|
|
7482
|
-
|
|
7482
|
+
path67.unshift(graph[cur].parent);
|
|
7483
7483
|
fn2 = link(conversions_default[graph[cur].parent][cur], fn2);
|
|
7484
7484
|
cur = graph[cur].parent;
|
|
7485
7485
|
}
|
|
7486
|
-
fn2.conversion =
|
|
7486
|
+
fn2.conversion = path67;
|
|
7487
7487
|
return fn2;
|
|
7488
7488
|
}
|
|
7489
7489
|
function route(fromModel) {
|
|
@@ -8100,7 +8100,7 @@ var require_channel = __commonJS({
|
|
|
8100
8100
|
var require_output = __commonJS({
|
|
8101
8101
|
"node_modules/sharp/lib/output.js"(exports, module) {
|
|
8102
8102
|
"use strict";
|
|
8103
|
-
var
|
|
8103
|
+
var path67 = __require("path");
|
|
8104
8104
|
var is2 = require_is();
|
|
8105
8105
|
var sharp2 = require_sharp();
|
|
8106
8106
|
var formats = /* @__PURE__ */ new Map([
|
|
@@ -8131,9 +8131,9 @@ var require_output = __commonJS({
|
|
|
8131
8131
|
let err14;
|
|
8132
8132
|
if (!is2.string(fileOut)) {
|
|
8133
8133
|
err14 = new Error("Missing output file path");
|
|
8134
|
-
} else if (is2.string(this.options.input.file) &&
|
|
8134
|
+
} else if (is2.string(this.options.input.file) && path67.resolve(this.options.input.file) === path67.resolve(fileOut)) {
|
|
8135
8135
|
err14 = new Error("Cannot use same file for input and output");
|
|
8136
|
-
} else if (jp2Regex.test(
|
|
8136
|
+
} else if (jp2Regex.test(path67.extname(fileOut)) && !this.constructor.format.jp2k.output.file) {
|
|
8137
8137
|
err14 = errJp2Save();
|
|
8138
8138
|
}
|
|
8139
8139
|
if (err14) {
|
|
@@ -42840,9 +42840,9 @@ ${this.boa_token}${this.audio_token.repeat(this._compute_audio_num_tokens(audio_
|
|
|
42840
42840
|
});
|
|
42841
42841
|
|
|
42842
42842
|
// src/lsp/config.ts
|
|
42843
|
-
import { existsSync } from "fs";
|
|
42843
|
+
import { existsSync as existsSync2 } from "fs";
|
|
42844
42844
|
import { execSync } from "child_process";
|
|
42845
|
-
import { join } from "path";
|
|
42845
|
+
import { join as join2 } from "path";
|
|
42846
42846
|
function fileLanguageToLspLanguage(fileLanguage) {
|
|
42847
42847
|
if (!fileLanguage) return null;
|
|
42848
42848
|
const map = {
|
|
@@ -42913,7 +42913,7 @@ var init_config = __esm({
|
|
|
42913
42913
|
language: "typescript",
|
|
42914
42914
|
command: "npx",
|
|
42915
42915
|
args: ["typescript-language-server", "--stdio"],
|
|
42916
|
-
detect: (root) =>
|
|
42916
|
+
detect: (root) => existsSync2(join2(root, "tsconfig.json")) || existsSync2(join2(root, "package.json")),
|
|
42917
42917
|
initializationOptions: {
|
|
42918
42918
|
preferences: { includeInlayParameterNameHints: "none" }
|
|
42919
42919
|
}
|
|
@@ -42922,19 +42922,19 @@ var init_config = __esm({
|
|
|
42922
42922
|
language: "python",
|
|
42923
42923
|
command: "pyright-langserver",
|
|
42924
42924
|
args: ["--stdio"],
|
|
42925
|
-
detect: (root) =>
|
|
42925
|
+
detect: (root) => existsSync2(join2(root, "pyproject.toml")) || existsSync2(join2(root, "requirements.txt")) || existsSync2(join2(root, "setup.py"))
|
|
42926
42926
|
},
|
|
42927
42927
|
{
|
|
42928
42928
|
language: "go",
|
|
42929
42929
|
command: "gopls",
|
|
42930
42930
|
args: ["serve"],
|
|
42931
|
-
detect: (root) =>
|
|
42931
|
+
detect: (root) => existsSync2(join2(root, "go.mod"))
|
|
42932
42932
|
},
|
|
42933
42933
|
{
|
|
42934
42934
|
language: "rust",
|
|
42935
42935
|
command: "rust-analyzer",
|
|
42936
42936
|
args: [],
|
|
42937
|
-
detect: (root) =>
|
|
42937
|
+
detect: (root) => existsSync2(join2(root, "Cargo.toml"))
|
|
42938
42938
|
}
|
|
42939
42939
|
];
|
|
42940
42940
|
EXTENSION_TO_LANGUAGE = {
|
|
@@ -43328,7 +43328,7 @@ var init_mappers = __esm({
|
|
|
43328
43328
|
});
|
|
43329
43329
|
|
|
43330
43330
|
// src/lsp/enrichment.ts
|
|
43331
|
-
import { readFileSync } from "fs";
|
|
43331
|
+
import { readFileSync as readFileSync2 } from "fs";
|
|
43332
43332
|
import { resolve as resolve2 } from "path";
|
|
43333
43333
|
import { pathToFileURL as pathToFileURL3 } from "url";
|
|
43334
43334
|
var CALL_EDGE_TYPES, LspEnrichmentPass;
|
|
@@ -43447,7 +43447,7 @@ var init_enrichment = __esm({
|
|
|
43447
43447
|
const uri = pathToFileURL3(absPath).href;
|
|
43448
43448
|
if (!openedFiles.has(uri)) {
|
|
43449
43449
|
try {
|
|
43450
|
-
const content =
|
|
43450
|
+
const content = readFileSync2(absPath, "utf-8");
|
|
43451
43451
|
const langId = getLanguageId(file.path) ?? language;
|
|
43452
43452
|
await client.openDocument(uri, langId, content);
|
|
43453
43453
|
openedFiles.add(uri);
|
|
@@ -43976,8 +43976,8 @@ var init_layer_violations = __esm({
|
|
|
43976
43976
|
});
|
|
43977
43977
|
|
|
43978
43978
|
// src/tools/refactoring/pack-context.ts
|
|
43979
|
-
import
|
|
43980
|
-
import
|
|
43979
|
+
import fs49 from "fs";
|
|
43980
|
+
import path57 from "path";
|
|
43981
43981
|
function estimateTokens2(text) {
|
|
43982
43982
|
return Math.ceil(text.length / 4);
|
|
43983
43983
|
}
|
|
@@ -44084,11 +44084,11 @@ ${outlineLines.join("\n")}
|
|
|
44084
44084
|
let sourceFilesIncluded = 0;
|
|
44085
44085
|
let sourceTruncated = false;
|
|
44086
44086
|
for (const f of files) {
|
|
44087
|
-
const absPath =
|
|
44088
|
-
if (!
|
|
44087
|
+
const absPath = path57.join(projectRoot, f.path);
|
|
44088
|
+
if (!fs49.existsSync(absPath)) continue;
|
|
44089
44089
|
let content;
|
|
44090
44090
|
try {
|
|
44091
|
-
content =
|
|
44091
|
+
content = fs49.readFileSync(absPath, "utf-8");
|
|
44092
44092
|
} catch {
|
|
44093
44093
|
continue;
|
|
44094
44094
|
}
|
|
@@ -44267,7 +44267,7 @@ function buildFileTree(paths) {
|
|
|
44267
44267
|
for (const p of sorted.slice(0, 200)) {
|
|
44268
44268
|
const depth = p.split("/").length - 1;
|
|
44269
44269
|
const indent = " ".repeat(Math.min(depth, 6));
|
|
44270
|
-
lines.push(`${indent}${
|
|
44270
|
+
lines.push(`${indent}${path57.basename(p)}`);
|
|
44271
44271
|
}
|
|
44272
44272
|
if (sorted.length > 200) {
|
|
44273
44273
|
lines.push(` ... and ${sorted.length - 200} more files`);
|
|
@@ -44497,6 +44497,35 @@ async function* parseOpenAIStream(body) {
|
|
|
44497
44497
|
reader.releaseLock();
|
|
44498
44498
|
}
|
|
44499
44499
|
}
|
|
44500
|
+
async function* parseAnthropicStream(body) {
|
|
44501
|
+
const reader = body.getReader();
|
|
44502
|
+
const decoder = new TextDecoder();
|
|
44503
|
+
let buffer = "";
|
|
44504
|
+
try {
|
|
44505
|
+
while (true) {
|
|
44506
|
+
const { done, value } = await reader.read();
|
|
44507
|
+
if (done) break;
|
|
44508
|
+
buffer += decoder.decode(value, { stream: true });
|
|
44509
|
+
const lines = buffer.split("\n");
|
|
44510
|
+
buffer = lines.pop();
|
|
44511
|
+
for (const line of lines) {
|
|
44512
|
+
const trimmed = line.trim();
|
|
44513
|
+
if (!trimmed || !trimmed.startsWith("data: ")) continue;
|
|
44514
|
+
const payload = trimmed.slice(6);
|
|
44515
|
+
try {
|
|
44516
|
+
const event = JSON.parse(payload);
|
|
44517
|
+
if (event.type === "content_block_delta" && event.delta?.text) {
|
|
44518
|
+
yield event.delta.text;
|
|
44519
|
+
}
|
|
44520
|
+
if (event.type === "message_stop") return;
|
|
44521
|
+
} catch {
|
|
44522
|
+
}
|
|
44523
|
+
}
|
|
44524
|
+
}
|
|
44525
|
+
} finally {
|
|
44526
|
+
reader.releaseLock();
|
|
44527
|
+
}
|
|
44528
|
+
}
|
|
44500
44529
|
async function* parseOllamaChatStream(body) {
|
|
44501
44530
|
const reader = body.getReader();
|
|
44502
44531
|
const decoder = new TextDecoder();
|
|
@@ -44911,6 +44940,278 @@ var OnnxProvider = class {
|
|
|
44911
44940
|
}
|
|
44912
44941
|
};
|
|
44913
44942
|
|
|
44943
|
+
// src/ai/gemini.ts
|
|
44944
|
+
init_logger();
|
|
44945
|
+
var BASE_URL = "https://generativelanguage.googleapis.com";
|
|
44946
|
+
var GeminiEmbeddingService = class {
|
|
44947
|
+
constructor(apiKey, model, dims) {
|
|
44948
|
+
this.apiKey = apiKey;
|
|
44949
|
+
this.model = model;
|
|
44950
|
+
this.dims = dims;
|
|
44951
|
+
}
|
|
44952
|
+
apiKey;
|
|
44953
|
+
model;
|
|
44954
|
+
dims;
|
|
44955
|
+
async embed(text) {
|
|
44956
|
+
const results = await this.embedBatch([text]);
|
|
44957
|
+
return results[0] ?? [];
|
|
44958
|
+
}
|
|
44959
|
+
async embedBatch(texts) {
|
|
44960
|
+
return withRetry(async () => {
|
|
44961
|
+
const requests = texts.map((text) => ({
|
|
44962
|
+
model: `models/${this.model}`,
|
|
44963
|
+
content: { parts: [{ text }] },
|
|
44964
|
+
outputDimensionality: this.dims
|
|
44965
|
+
}));
|
|
44966
|
+
const resp = await fetch(
|
|
44967
|
+
`${BASE_URL}/v1beta/models/${this.model}:batchEmbedContents?key=${this.apiKey}`,
|
|
44968
|
+
{
|
|
44969
|
+
method: "POST",
|
|
44970
|
+
headers: { "Content-Type": "application/json" },
|
|
44971
|
+
body: JSON.stringify({ requests }),
|
|
44972
|
+
signal: AbortSignal.timeout(3e4)
|
|
44973
|
+
}
|
|
44974
|
+
);
|
|
44975
|
+
if (!resp.ok) {
|
|
44976
|
+
const body = await resp.text().catch(() => "");
|
|
44977
|
+
const safeBody = body.length > 200 ? body.slice(0, 200) + "\u2026" : body;
|
|
44978
|
+
throw new Error(`Gemini embeddings failed: ${resp.status} ${resp.statusText} \u2014 ${safeBody}`);
|
|
44979
|
+
}
|
|
44980
|
+
const data = await resp.json();
|
|
44981
|
+
return data.embeddings.map((e) => e.values);
|
|
44982
|
+
}, { label: "Gemini embeddings" });
|
|
44983
|
+
}
|
|
44984
|
+
dimensions() {
|
|
44985
|
+
return this.dims;
|
|
44986
|
+
}
|
|
44987
|
+
};
|
|
44988
|
+
var GeminiInferenceService = class {
|
|
44989
|
+
constructor(apiKey, model) {
|
|
44990
|
+
this.apiKey = apiKey;
|
|
44991
|
+
this.model = model;
|
|
44992
|
+
}
|
|
44993
|
+
apiKey;
|
|
44994
|
+
model;
|
|
44995
|
+
async generate(prompt, options) {
|
|
44996
|
+
return withRetry(async () => {
|
|
44997
|
+
const resp = await fetch(
|
|
44998
|
+
`${BASE_URL}/v1beta/models/${this.model}:generateContent?key=${this.apiKey}`,
|
|
44999
|
+
{
|
|
45000
|
+
method: "POST",
|
|
45001
|
+
headers: { "Content-Type": "application/json" },
|
|
45002
|
+
body: JSON.stringify({
|
|
45003
|
+
contents: [{ parts: [{ text: prompt }] }],
|
|
45004
|
+
generationConfig: {
|
|
45005
|
+
...options?.maxTokens ? { maxOutputTokens: options.maxTokens } : {},
|
|
45006
|
+
...options?.temperature !== void 0 ? { temperature: options.temperature } : {}
|
|
45007
|
+
}
|
|
45008
|
+
}),
|
|
45009
|
+
signal: AbortSignal.timeout(6e4)
|
|
45010
|
+
}
|
|
45011
|
+
);
|
|
45012
|
+
if (!resp.ok) {
|
|
45013
|
+
const body = await resp.text().catch(() => "");
|
|
45014
|
+
const safeBody = body.length > 200 ? body.slice(0, 200) + "\u2026" : body;
|
|
45015
|
+
throw new Error(`Gemini generate failed: ${resp.status} ${resp.statusText} \u2014 ${safeBody}`);
|
|
45016
|
+
}
|
|
45017
|
+
const data = await resp.json();
|
|
45018
|
+
return data.candidates?.[0]?.content?.parts?.[0]?.text ?? "";
|
|
45019
|
+
}, { label: "Gemini generate" });
|
|
45020
|
+
}
|
|
45021
|
+
async *generateStream(messages, options) {
|
|
45022
|
+
const contents = messages.map((m) => ({
|
|
45023
|
+
role: m.role === "assistant" ? "model" : "user",
|
|
45024
|
+
parts: [{ text: m.content }]
|
|
45025
|
+
}));
|
|
45026
|
+
const resp = await fetch(
|
|
45027
|
+
`${BASE_URL}/v1beta/models/${this.model}:streamGenerateContent?alt=sse&key=${this.apiKey}`,
|
|
45028
|
+
{
|
|
45029
|
+
method: "POST",
|
|
45030
|
+
headers: { "Content-Type": "application/json" },
|
|
45031
|
+
body: JSON.stringify({
|
|
45032
|
+
contents,
|
|
45033
|
+
generationConfig: {
|
|
45034
|
+
...options?.maxTokens ? { maxOutputTokens: options.maxTokens } : {},
|
|
45035
|
+
...options?.temperature !== void 0 ? { temperature: options.temperature } : {}
|
|
45036
|
+
}
|
|
45037
|
+
}),
|
|
45038
|
+
signal: AbortSignal.timeout(12e4)
|
|
45039
|
+
}
|
|
45040
|
+
);
|
|
45041
|
+
if (!resp.ok) {
|
|
45042
|
+
const body = await resp.text().catch(() => "");
|
|
45043
|
+
const safeBody = body.length > 200 ? body.slice(0, 200) + "\u2026" : body;
|
|
45044
|
+
throw new Error(`Gemini stream failed: ${resp.status} ${resp.statusText} \u2014 ${safeBody}`);
|
|
45045
|
+
}
|
|
45046
|
+
const reader = resp.body.getReader();
|
|
45047
|
+
const decoder = new TextDecoder();
|
|
45048
|
+
let buf = "";
|
|
45049
|
+
while (true) {
|
|
45050
|
+
const { value, done } = await reader.read();
|
|
45051
|
+
if (done) break;
|
|
45052
|
+
buf += decoder.decode(value, { stream: true });
|
|
45053
|
+
const lines = buf.split("\n");
|
|
45054
|
+
buf = lines.pop();
|
|
45055
|
+
for (const line of lines) {
|
|
45056
|
+
if (!line.startsWith("data: ")) continue;
|
|
45057
|
+
const json = line.slice(6).trim();
|
|
45058
|
+
if (!json || json === "[DONE]") continue;
|
|
45059
|
+
try {
|
|
45060
|
+
const chunk2 = JSON.parse(json);
|
|
45061
|
+
const text = chunk2.candidates?.[0]?.content?.parts?.[0]?.text;
|
|
45062
|
+
if (text) yield text;
|
|
45063
|
+
} catch {
|
|
45064
|
+
}
|
|
45065
|
+
}
|
|
45066
|
+
}
|
|
45067
|
+
}
|
|
45068
|
+
};
|
|
45069
|
+
var GeminiProvider = class {
|
|
45070
|
+
config;
|
|
45071
|
+
constructor(config) {
|
|
45072
|
+
this.config = config;
|
|
45073
|
+
}
|
|
45074
|
+
async isAvailable() {
|
|
45075
|
+
try {
|
|
45076
|
+
const resp = await fetch(
|
|
45077
|
+
`${BASE_URL}/v1beta/models?key=${this.config.apiKey}`,
|
|
45078
|
+
{ signal: AbortSignal.timeout(3e3) }
|
|
45079
|
+
);
|
|
45080
|
+
return resp.ok;
|
|
45081
|
+
} catch {
|
|
45082
|
+
logger.debug("Gemini not available");
|
|
45083
|
+
return false;
|
|
45084
|
+
}
|
|
45085
|
+
}
|
|
45086
|
+
embedding() {
|
|
45087
|
+
return new GeminiEmbeddingService(
|
|
45088
|
+
this.config.apiKey,
|
|
45089
|
+
this.config.embeddingModel,
|
|
45090
|
+
this.config.embeddingDimensions
|
|
45091
|
+
);
|
|
45092
|
+
}
|
|
45093
|
+
inference() {
|
|
45094
|
+
return new GeminiInferenceService(this.config.apiKey, this.config.inferenceModel);
|
|
45095
|
+
}
|
|
45096
|
+
fastInference() {
|
|
45097
|
+
return new GeminiInferenceService(this.config.apiKey, this.config.fastModel);
|
|
45098
|
+
}
|
|
45099
|
+
};
|
|
45100
|
+
|
|
45101
|
+
// src/ai/anthropic.ts
|
|
45102
|
+
init_logger();
|
|
45103
|
+
var BASE_URL2 = "https://api.anthropic.com";
|
|
45104
|
+
var NoEmbeddingService = class {
|
|
45105
|
+
async embed(_text) {
|
|
45106
|
+
return [];
|
|
45107
|
+
}
|
|
45108
|
+
async embedBatch(_texts) {
|
|
45109
|
+
return [];
|
|
45110
|
+
}
|
|
45111
|
+
dimensions() {
|
|
45112
|
+
return 0;
|
|
45113
|
+
}
|
|
45114
|
+
};
|
|
45115
|
+
var AnthropicInferenceService = class {
|
|
45116
|
+
constructor(apiKey, model) {
|
|
45117
|
+
this.apiKey = apiKey;
|
|
45118
|
+
this.model = model;
|
|
45119
|
+
}
|
|
45120
|
+
apiKey;
|
|
45121
|
+
model;
|
|
45122
|
+
async generate(prompt, options) {
|
|
45123
|
+
return withRetry(async () => {
|
|
45124
|
+
const resp = await fetch(`${BASE_URL2}/v1/messages`, {
|
|
45125
|
+
method: "POST",
|
|
45126
|
+
headers: {
|
|
45127
|
+
"Content-Type": "application/json",
|
|
45128
|
+
"x-api-key": this.apiKey,
|
|
45129
|
+
"anthropic-version": "2023-06-01"
|
|
45130
|
+
},
|
|
45131
|
+
body: JSON.stringify({
|
|
45132
|
+
model: this.model,
|
|
45133
|
+
max_tokens: options?.maxTokens ?? 4096,
|
|
45134
|
+
messages: [{ role: "user", content: prompt }],
|
|
45135
|
+
...options?.temperature !== void 0 ? { temperature: options.temperature } : {}
|
|
45136
|
+
}),
|
|
45137
|
+
signal: AbortSignal.timeout(6e4)
|
|
45138
|
+
});
|
|
45139
|
+
if (!resp.ok) {
|
|
45140
|
+
const body = await resp.text().catch(() => "");
|
|
45141
|
+
const safeBody = body.length > 200 ? body.slice(0, 200) + "\u2026" : body;
|
|
45142
|
+
throw new Error(`Anthropic API error: ${resp.status} ${resp.statusText} \u2014 ${safeBody}`);
|
|
45143
|
+
}
|
|
45144
|
+
const data = await resp.json();
|
|
45145
|
+
return data.content?.find((c) => c.type === "text")?.text ?? "";
|
|
45146
|
+
}, { label: "Anthropic generate" });
|
|
45147
|
+
}
|
|
45148
|
+
async *generateStream(messages, options) {
|
|
45149
|
+
const systemMsg = messages.find((m) => m.role === "system");
|
|
45150
|
+
const nonSystemMsgs = messages.filter((m) => m.role !== "system");
|
|
45151
|
+
const resp = await fetch(`${BASE_URL2}/v1/messages`, {
|
|
45152
|
+
method: "POST",
|
|
45153
|
+
headers: {
|
|
45154
|
+
"Content-Type": "application/json",
|
|
45155
|
+
"x-api-key": this.apiKey,
|
|
45156
|
+
"anthropic-version": "2023-06-01"
|
|
45157
|
+
},
|
|
45158
|
+
body: JSON.stringify({
|
|
45159
|
+
model: this.model,
|
|
45160
|
+
max_tokens: options?.maxTokens ?? 4096,
|
|
45161
|
+
stream: true,
|
|
45162
|
+
...systemMsg ? { system: systemMsg.content } : {},
|
|
45163
|
+
...options?.temperature !== void 0 ? { temperature: options.temperature } : {},
|
|
45164
|
+
messages: nonSystemMsgs.map((m) => ({ role: m.role, content: m.content }))
|
|
45165
|
+
}),
|
|
45166
|
+
signal: AbortSignal.timeout(12e4)
|
|
45167
|
+
});
|
|
45168
|
+
if (!resp.ok) {
|
|
45169
|
+
const body = await resp.text().catch(() => "");
|
|
45170
|
+
const safeBody = body.length > 200 ? body.slice(0, 200) + "\u2026" : body;
|
|
45171
|
+
throw new Error(`Anthropic stream error: ${resp.status} ${resp.statusText} \u2014 ${safeBody}`);
|
|
45172
|
+
}
|
|
45173
|
+
yield* parseAnthropicStream(resp.body);
|
|
45174
|
+
}
|
|
45175
|
+
};
|
|
45176
|
+
var AnthropicProvider = class {
|
|
45177
|
+
config;
|
|
45178
|
+
constructor(config) {
|
|
45179
|
+
this.config = config;
|
|
45180
|
+
}
|
|
45181
|
+
async isAvailable() {
|
|
45182
|
+
try {
|
|
45183
|
+
const resp = await fetch(`${BASE_URL2}/v1/messages`, {
|
|
45184
|
+
method: "POST",
|
|
45185
|
+
headers: {
|
|
45186
|
+
"Content-Type": "application/json",
|
|
45187
|
+
"x-api-key": this.config.apiKey,
|
|
45188
|
+
"anthropic-version": "2023-06-01"
|
|
45189
|
+
},
|
|
45190
|
+
body: JSON.stringify({
|
|
45191
|
+
model: this.config.inferenceModel,
|
|
45192
|
+
max_tokens: 1,
|
|
45193
|
+
messages: [{ role: "user", content: "ping" }]
|
|
45194
|
+
}),
|
|
45195
|
+
signal: AbortSignal.timeout(5e3)
|
|
45196
|
+
});
|
|
45197
|
+
return resp.ok || resp.status === 400;
|
|
45198
|
+
} catch {
|
|
45199
|
+
logger.debug("Anthropic not available");
|
|
45200
|
+
return false;
|
|
45201
|
+
}
|
|
45202
|
+
}
|
|
45203
|
+
embedding() {
|
|
45204
|
+
logger.warn("Anthropic does not provide embeddings \u2014 use a separate embedding provider (ONNX, Ollama, or OpenAI)");
|
|
45205
|
+
return new NoEmbeddingService();
|
|
45206
|
+
}
|
|
45207
|
+
inference() {
|
|
45208
|
+
return new AnthropicInferenceService(this.config.apiKey, this.config.inferenceModel);
|
|
45209
|
+
}
|
|
45210
|
+
fastInference() {
|
|
45211
|
+
return new AnthropicInferenceService(this.config.apiKey, this.config.fastModel);
|
|
45212
|
+
}
|
|
45213
|
+
};
|
|
45214
|
+
|
|
44914
45215
|
// src/ai/index.ts
|
|
44915
45216
|
init_logger();
|
|
44916
45217
|
|
|
@@ -45400,32 +45701,76 @@ var LLMReranker = class {
|
|
|
45400
45701
|
};
|
|
45401
45702
|
|
|
45402
45703
|
// src/ai/index.ts
|
|
45704
|
+
var OPENAI_COMPAT_DEFAULTS = {
|
|
45705
|
+
openai: {
|
|
45706
|
+
baseUrl: "https://api.openai.com/v1",
|
|
45707
|
+
embeddingModel: "text-embedding-3-small",
|
|
45708
|
+
embeddingDimensions: 1536,
|
|
45709
|
+
inferenceModel: "gpt-4o-mini",
|
|
45710
|
+
fastModel: "gpt-4o-mini",
|
|
45711
|
+
envKey: "OPENAI_API_KEY"
|
|
45712
|
+
},
|
|
45713
|
+
lmstudio: {
|
|
45714
|
+
baseUrl: "http://localhost:1234/v1",
|
|
45715
|
+
embeddingModel: "nomic-embed-text-v1.5",
|
|
45716
|
+
embeddingDimensions: 768,
|
|
45717
|
+
inferenceModel: "qwen2.5-coder-7b-instruct",
|
|
45718
|
+
fastModel: "qwen2.5-coder-7b-instruct",
|
|
45719
|
+
envKey: "LMSTUDIO_API_KEY"
|
|
45720
|
+
},
|
|
45721
|
+
groq: {
|
|
45722
|
+
baseUrl: "https://api.groq.com/openai/v1",
|
|
45723
|
+
embeddingModel: "nomic-embed-text-v1.5",
|
|
45724
|
+
embeddingDimensions: 768,
|
|
45725
|
+
inferenceModel: "llama-3.3-70b-versatile",
|
|
45726
|
+
fastModel: "llama-3.1-8b-instant",
|
|
45727
|
+
envKey: "GROQ_API_KEY"
|
|
45728
|
+
},
|
|
45729
|
+
together: {
|
|
45730
|
+
baseUrl: "https://api.together.xyz/v1",
|
|
45731
|
+
embeddingModel: "togethercomputer/m2-bert-80M-8k-retrieval",
|
|
45732
|
+
embeddingDimensions: 768,
|
|
45733
|
+
inferenceModel: "meta-llama/Llama-3.3-70B-Instruct-Turbo",
|
|
45734
|
+
fastModel: "meta-llama/Llama-3.1-8B-Instruct-Turbo",
|
|
45735
|
+
envKey: "TOGETHER_API_KEY"
|
|
45736
|
+
},
|
|
45737
|
+
deepseek: {
|
|
45738
|
+
baseUrl: "https://api.deepseek.com/v1",
|
|
45739
|
+
embeddingModel: "deepseek-chat",
|
|
45740
|
+
embeddingDimensions: 1536,
|
|
45741
|
+
inferenceModel: "deepseek-chat",
|
|
45742
|
+
fastModel: "deepseek-chat",
|
|
45743
|
+
envKey: "DEEPSEEK_API_KEY"
|
|
45744
|
+
},
|
|
45745
|
+
mistral: {
|
|
45746
|
+
baseUrl: "https://api.mistral.ai/v1",
|
|
45747
|
+
embeddingModel: "mistral-embed",
|
|
45748
|
+
embeddingDimensions: 1024,
|
|
45749
|
+
inferenceModel: "mistral-small-latest",
|
|
45750
|
+
fastModel: "mistral-small-latest",
|
|
45751
|
+
envKey: "MISTRAL_API_KEY"
|
|
45752
|
+
},
|
|
45753
|
+
xai: {
|
|
45754
|
+
baseUrl: "https://api.x.ai/v1",
|
|
45755
|
+
embeddingModel: "grok-2",
|
|
45756
|
+
embeddingDimensions: 1536,
|
|
45757
|
+
inferenceModel: "grok-2",
|
|
45758
|
+
fastModel: "grok-2",
|
|
45759
|
+
envKey: "XAI_API_KEY"
|
|
45760
|
+
}
|
|
45761
|
+
};
|
|
45403
45762
|
function createAIProvider(config) {
|
|
45404
45763
|
if (!config.ai?.enabled) {
|
|
45405
45764
|
return new FallbackProvider();
|
|
45406
45765
|
}
|
|
45407
|
-
|
|
45766
|
+
const provider = config.ai.provider;
|
|
45767
|
+
if (provider === "onnx") {
|
|
45408
45768
|
return new OnnxProvider({
|
|
45409
45769
|
model: config.ai.embedding_model,
|
|
45410
45770
|
dimensions: config.ai.embedding_dimensions
|
|
45411
45771
|
});
|
|
45412
45772
|
}
|
|
45413
|
-
if (
|
|
45414
|
-
const apiKey = config.ai.api_key ?? process.env.OPENAI_API_KEY ?? "";
|
|
45415
|
-
if (!apiKey) {
|
|
45416
|
-
logger.warn("OpenAI provider selected but no api_key configured \u2014 falling back to FallbackProvider");
|
|
45417
|
-
return new FallbackProvider();
|
|
45418
|
-
}
|
|
45419
|
-
return new OpenAIProvider({
|
|
45420
|
-
apiKey,
|
|
45421
|
-
baseUrl: config.ai.base_url ?? "https://api.openai.com/v1",
|
|
45422
|
-
embeddingModel: config.ai.embedding_model ?? "text-embedding-3-small",
|
|
45423
|
-
embeddingDimensions: config.ai.embedding_dimensions ?? 1536,
|
|
45424
|
-
inferenceModel: config.ai.inference_model ?? "gpt-4o-mini",
|
|
45425
|
-
fastModel: config.ai.fast_model ?? "gpt-4o-mini"
|
|
45426
|
-
});
|
|
45427
|
-
}
|
|
45428
|
-
if (config.ai.provider === "ollama") {
|
|
45773
|
+
if (provider === "ollama") {
|
|
45429
45774
|
return new OllamaProvider({
|
|
45430
45775
|
baseUrl: config.ai.base_url ?? "http://localhost:11434",
|
|
45431
45776
|
embeddingModel: config.ai.embedding_model ?? "qwen3-embedding:0.6b",
|
|
@@ -45434,6 +45779,48 @@ function createAIProvider(config) {
|
|
|
45434
45779
|
embeddingDimensions: config.ai.embedding_dimensions
|
|
45435
45780
|
});
|
|
45436
45781
|
}
|
|
45782
|
+
if (provider === "gemini") {
|
|
45783
|
+
const apiKey = config.ai.api_key ?? process.env.GEMINI_API_KEY ?? "";
|
|
45784
|
+
if (!apiKey) {
|
|
45785
|
+
logger.warn("Gemini provider selected but no api_key configured \u2014 falling back");
|
|
45786
|
+
return new FallbackProvider();
|
|
45787
|
+
}
|
|
45788
|
+
return new GeminiProvider({
|
|
45789
|
+
apiKey,
|
|
45790
|
+
embeddingModel: config.ai.embedding_model ?? "text-embedding-004",
|
|
45791
|
+
embeddingDimensions: config.ai.embedding_dimensions ?? 768,
|
|
45792
|
+
inferenceModel: config.ai.inference_model ?? "gemini-2.0-flash",
|
|
45793
|
+
fastModel: config.ai.fast_model ?? "gemini-2.0-flash"
|
|
45794
|
+
});
|
|
45795
|
+
}
|
|
45796
|
+
if (provider === "anthropic") {
|
|
45797
|
+
const apiKey = config.ai.api_key ?? process.env.ANTHROPIC_API_KEY ?? "";
|
|
45798
|
+
if (!apiKey) {
|
|
45799
|
+
logger.warn("Anthropic provider selected but no api_key configured \u2014 falling back");
|
|
45800
|
+
return new FallbackProvider();
|
|
45801
|
+
}
|
|
45802
|
+
return new AnthropicProvider({
|
|
45803
|
+
apiKey,
|
|
45804
|
+
inferenceModel: config.ai.inference_model ?? "claude-sonnet-4-20250514",
|
|
45805
|
+
fastModel: config.ai.fast_model ?? "claude-haiku-4-5-20251001"
|
|
45806
|
+
});
|
|
45807
|
+
}
|
|
45808
|
+
const defaults = OPENAI_COMPAT_DEFAULTS[provider];
|
|
45809
|
+
if (defaults) {
|
|
45810
|
+
const apiKey = config.ai.api_key ?? process.env[defaults.envKey] ?? "";
|
|
45811
|
+
if (!apiKey && provider !== "lmstudio") {
|
|
45812
|
+
logger.warn(`${provider} provider selected but no api_key configured \u2014 falling back`);
|
|
45813
|
+
return new FallbackProvider();
|
|
45814
|
+
}
|
|
45815
|
+
return new OpenAIProvider({
|
|
45816
|
+
apiKey,
|
|
45817
|
+
baseUrl: config.ai.base_url ?? defaults.baseUrl,
|
|
45818
|
+
embeddingModel: config.ai.embedding_model ?? defaults.embeddingModel,
|
|
45819
|
+
embeddingDimensions: config.ai.embedding_dimensions ?? defaults.embeddingDimensions,
|
|
45820
|
+
inferenceModel: config.ai.inference_model ?? defaults.inferenceModel,
|
|
45821
|
+
fastModel: config.ai.fast_model ?? defaults.fastModel
|
|
45822
|
+
});
|
|
45823
|
+
}
|
|
45437
45824
|
return new FallbackProvider();
|
|
45438
45825
|
}
|
|
45439
45826
|
|
|
@@ -46337,8 +46724,8 @@ var SessionJournal = class _SessionJournal {
|
|
|
46337
46724
|
};
|
|
46338
46725
|
this.entries.push(entry);
|
|
46339
46726
|
if (tool === "get_symbol" || tool === "get_outline") {
|
|
46340
|
-
const
|
|
46341
|
-
if (
|
|
46727
|
+
const path67 = params.path ?? params.file_path ?? "";
|
|
46728
|
+
if (path67) this.filesRead.add(path67);
|
|
46342
46729
|
}
|
|
46343
46730
|
if (resultCount === 0 && this.isSearchTool(tool)) {
|
|
46344
46731
|
this.zeroResultQueries.set(hash, summary);
|
|
@@ -47781,8 +48168,8 @@ init_logger();
|
|
|
47781
48168
|
import { z as z2 } from "zod";
|
|
47782
48169
|
|
|
47783
48170
|
// src/indexer/pipeline.ts
|
|
47784
|
-
import
|
|
47785
|
-
import
|
|
48171
|
+
import fs23 from "fs";
|
|
48172
|
+
import path21 from "path";
|
|
47786
48173
|
import { cpus } from "os";
|
|
47787
48174
|
import fg3 from "fast-glob";
|
|
47788
48175
|
init_logger();
|
|
@@ -50262,7 +50649,7 @@ var FilePersister = class {
|
|
|
50262
50649
|
};
|
|
50263
50650
|
|
|
50264
50651
|
// src/indexer/edge-resolver.ts
|
|
50265
|
-
import
|
|
50652
|
+
import path18 from "path";
|
|
50266
50653
|
|
|
50267
50654
|
// src/plugin-api/executor.ts
|
|
50268
50655
|
init_logger();
|
|
@@ -51419,6 +51806,251 @@ function buildFromPendingImports(state) {
|
|
|
51419
51806
|
return result;
|
|
51420
51807
|
}
|
|
51421
51808
|
|
|
51809
|
+
// src/indexer/edge-resolvers/php-imports.ts
|
|
51810
|
+
import * as path17 from "path";
|
|
51811
|
+
import * as fs18 from "fs";
|
|
51812
|
+
|
|
51813
|
+
// src/indexer/resolvers/psr4.ts
|
|
51814
|
+
import { readFileSync } from "fs";
|
|
51815
|
+
var Psr4Resolver = class _Psr4Resolver {
|
|
51816
|
+
constructor(mappings, rootPath) {
|
|
51817
|
+
this.rootPath = rootPath;
|
|
51818
|
+
this.mappings = /* @__PURE__ */ new Map();
|
|
51819
|
+
for (const [prefix, dir] of mappings) {
|
|
51820
|
+
const normPrefix = prefix.endsWith("\\") ? prefix : prefix + "\\";
|
|
51821
|
+
const normDir = dir.endsWith("/") ? dir : dir + "/";
|
|
51822
|
+
this.mappings.set(normPrefix, normDir);
|
|
51823
|
+
}
|
|
51824
|
+
}
|
|
51825
|
+
rootPath;
|
|
51826
|
+
/** namespace prefix (with trailing backslash) → directory (with trailing slash) */
|
|
51827
|
+
mappings;
|
|
51828
|
+
/**
|
|
51829
|
+
* Create a Psr4Resolver from a composer.json file.
|
|
51830
|
+
* Reads both autoload.psr-4 and autoload-dev.psr-4 sections.
|
|
51831
|
+
*/
|
|
51832
|
+
static fromComposerJson(composerJsonPath, rootPath) {
|
|
51833
|
+
try {
|
|
51834
|
+
const raw = readFileSync(composerJsonPath, "utf-8");
|
|
51835
|
+
const json = JSON.parse(raw);
|
|
51836
|
+
const mappings = /* @__PURE__ */ new Map();
|
|
51837
|
+
const extractPsr4 = (section) => {
|
|
51838
|
+
if (section && typeof section === "object" && !Array.isArray(section)) {
|
|
51839
|
+
const psr4 = section["psr-4"];
|
|
51840
|
+
if (psr4 && typeof psr4 === "object" && !Array.isArray(psr4)) {
|
|
51841
|
+
for (const [prefix, dir] of Object.entries(psr4)) {
|
|
51842
|
+
if (typeof dir === "string") {
|
|
51843
|
+
mappings.set(prefix, dir);
|
|
51844
|
+
}
|
|
51845
|
+
if (Array.isArray(dir)) {
|
|
51846
|
+
for (const d of dir) {
|
|
51847
|
+
if (typeof d === "string") {
|
|
51848
|
+
mappings.set(prefix, d);
|
|
51849
|
+
}
|
|
51850
|
+
}
|
|
51851
|
+
}
|
|
51852
|
+
}
|
|
51853
|
+
}
|
|
51854
|
+
}
|
|
51855
|
+
};
|
|
51856
|
+
extractPsr4(json["autoload"]);
|
|
51857
|
+
extractPsr4(json["autoload-dev"]);
|
|
51858
|
+
if (mappings.size === 0) return void 0;
|
|
51859
|
+
return new _Psr4Resolver(mappings, rootPath);
|
|
51860
|
+
} catch {
|
|
51861
|
+
return void 0;
|
|
51862
|
+
}
|
|
51863
|
+
}
|
|
51864
|
+
/**
|
|
51865
|
+
* Resolve a fully qualified class name to a relative file path.
|
|
51866
|
+
* Matches the longest prefix first.
|
|
51867
|
+
*
|
|
51868
|
+
* Example: "App\Models\User" → "app/Models/User.php"
|
|
51869
|
+
*/
|
|
51870
|
+
resolve(fqn) {
|
|
51871
|
+
let bestPrefix = "";
|
|
51872
|
+
let bestDir = "";
|
|
51873
|
+
for (const [prefix, dir] of this.mappings) {
|
|
51874
|
+
if (fqn.startsWith(prefix) && prefix.length > bestPrefix.length) {
|
|
51875
|
+
bestPrefix = prefix;
|
|
51876
|
+
bestDir = dir;
|
|
51877
|
+
}
|
|
51878
|
+
const prefixNoSlash = prefix.slice(0, -1);
|
|
51879
|
+
if (fqn === prefixNoSlash && prefix.length > bestPrefix.length) {
|
|
51880
|
+
bestPrefix = prefix;
|
|
51881
|
+
bestDir = dir;
|
|
51882
|
+
}
|
|
51883
|
+
}
|
|
51884
|
+
if (!bestPrefix) return void 0;
|
|
51885
|
+
const remainder = fqn.substring(bestPrefix.length);
|
|
51886
|
+
const relativePath = remainder.replace(/\\/g, "/");
|
|
51887
|
+
return bestDir + relativePath + ".php";
|
|
51888
|
+
}
|
|
51889
|
+
/**
|
|
51890
|
+
* Reverse-resolve a relative file path to a fully qualified class name.
|
|
51891
|
+
*
|
|
51892
|
+
* Example: "app/Models/User.php" → "App\Models\User"
|
|
51893
|
+
*/
|
|
51894
|
+
resolveToFqn(filePath) {
|
|
51895
|
+
let normalised = filePath.replace(/\\/g, "/");
|
|
51896
|
+
const rootNorm = this.rootPath.replace(/\\/g, "/").replace(/\/$/, "") + "/";
|
|
51897
|
+
if (normalised.startsWith(rootNorm)) {
|
|
51898
|
+
normalised = normalised.substring(rootNorm.length);
|
|
51899
|
+
}
|
|
51900
|
+
if (!normalised.endsWith(".php")) return void 0;
|
|
51901
|
+
const withoutExt = normalised.slice(0, -4);
|
|
51902
|
+
let bestPrefix = "";
|
|
51903
|
+
let bestDir = "";
|
|
51904
|
+
for (const [prefix, dir] of this.mappings) {
|
|
51905
|
+
if (withoutExt.startsWith(dir) && dir.length > bestDir.length) {
|
|
51906
|
+
bestPrefix = prefix;
|
|
51907
|
+
bestDir = dir;
|
|
51908
|
+
}
|
|
51909
|
+
const dirNoSlash = dir.replace(/\/$/, "");
|
|
51910
|
+
if (withoutExt.startsWith(dirNoSlash + "/") && dir.length > bestDir.length) {
|
|
51911
|
+
bestPrefix = prefix;
|
|
51912
|
+
bestDir = dir;
|
|
51913
|
+
}
|
|
51914
|
+
}
|
|
51915
|
+
if (!bestDir) return void 0;
|
|
51916
|
+
const remainder = withoutExt.substring(bestDir.length);
|
|
51917
|
+
const fqnSuffix = remainder.replace(/\//g, "\\");
|
|
51918
|
+
return bestPrefix + fqnSuffix;
|
|
51919
|
+
}
|
|
51920
|
+
/** Get all registered mappings (for debugging / inspection). */
|
|
51921
|
+
getMappings() {
|
|
51922
|
+
return this.mappings;
|
|
51923
|
+
}
|
|
51924
|
+
};
|
|
51925
|
+
|
|
51926
|
+
// src/indexer/edge-resolvers/php-imports.ts
|
|
51927
|
+
init_logger();
|
|
51928
|
+
function resolvePhpImportEdges(state) {
|
|
51929
|
+
const { store } = state;
|
|
51930
|
+
if (state.pendingImports.size === 0) return;
|
|
51931
|
+
const allPhpFiles = store.db.prepare(
|
|
51932
|
+
`SELECT id, path, workspace FROM files WHERE language = 'php'`
|
|
51933
|
+
).all();
|
|
51934
|
+
if (allPhpFiles.length === 0) return;
|
|
51935
|
+
const fqnToFile = /* @__PURE__ */ new Map();
|
|
51936
|
+
const fqnRows = store.db.prepare(
|
|
51937
|
+
`SELECT s.fqn, f.id, f.path, f.workspace FROM symbols s
|
|
51938
|
+
JOIN files f ON s.file_id = f.id
|
|
51939
|
+
WHERE s.fqn IS NOT NULL AND f.language = 'php'
|
|
51940
|
+
AND s.kind IN ('class', 'interface', 'trait', 'enum')`
|
|
51941
|
+
).all();
|
|
51942
|
+
for (const row of fqnRows) {
|
|
51943
|
+
const key = `${row.workspace ?? ""}\0${row.fqn}`;
|
|
51944
|
+
fqnToFile.set(key, { id: row.id, path: row.path, workspace: row.workspace });
|
|
51945
|
+
}
|
|
51946
|
+
const psr4Resolvers = /* @__PURE__ */ new Map();
|
|
51947
|
+
const workspacePaths = /* @__PURE__ */ new Set();
|
|
51948
|
+
for (const f of allPhpFiles) {
|
|
51949
|
+
if (f.workspace) workspacePaths.add(f.workspace);
|
|
51950
|
+
}
|
|
51951
|
+
for (const wsPath of workspacePaths) {
|
|
51952
|
+
const wsRoot = path17.join(state.rootPath, wsPath);
|
|
51953
|
+
const composerPath = path17.join(wsRoot, "composer.json");
|
|
51954
|
+
if (fs18.existsSync(composerPath)) {
|
|
51955
|
+
const resolver = Psr4Resolver.fromComposerJson(composerPath, wsRoot);
|
|
51956
|
+
if (resolver) psr4Resolvers.set(wsPath, resolver);
|
|
51957
|
+
}
|
|
51958
|
+
}
|
|
51959
|
+
const rootComposer = path17.join(state.rootPath, "composer.json");
|
|
51960
|
+
if (fs18.existsSync(rootComposer)) {
|
|
51961
|
+
const resolver = Psr4Resolver.fromComposerJson(rootComposer, state.rootPath);
|
|
51962
|
+
if (resolver) psr4Resolvers.set("", resolver);
|
|
51963
|
+
}
|
|
51964
|
+
const pathToFile = /* @__PURE__ */ new Map();
|
|
51965
|
+
for (const f of allPhpFiles) {
|
|
51966
|
+
pathToFile.set(f.path, f);
|
|
51967
|
+
}
|
|
51968
|
+
const fileNodeMap = /* @__PURE__ */ new Map();
|
|
51969
|
+
const allFileIds = allPhpFiles.map((f) => f.id);
|
|
51970
|
+
const CHUNK = 500;
|
|
51971
|
+
for (let i = 0; i < allFileIds.length; i += CHUNK) {
|
|
51972
|
+
for (const [k2, v] of store.getNodeIdsBatch("file", allFileIds.slice(i, i + CHUNK))) {
|
|
51973
|
+
fileNodeMap.set(k2, v);
|
|
51974
|
+
}
|
|
51975
|
+
}
|
|
51976
|
+
const importsEdgeType = store.db.prepare(
|
|
51977
|
+
`SELECT id FROM edge_types WHERE name = ?`
|
|
51978
|
+
).get("imports");
|
|
51979
|
+
if (!importsEdgeType) return;
|
|
51980
|
+
const insertStmt = store.db.prepare(
|
|
51981
|
+
`INSERT INTO edges (source_node_id, target_node_id, edge_type_id, resolved, metadata, is_cross_ws)
|
|
51982
|
+
VALUES (?, ?, ?, 1, ?, ?)
|
|
51983
|
+
ON CONFLICT(source_node_id, target_node_id, edge_type_id)
|
|
51984
|
+
DO UPDATE SET metadata = excluded.metadata`
|
|
51985
|
+
);
|
|
51986
|
+
const pendingFileIds = Array.from(state.pendingImports.keys());
|
|
51987
|
+
const fileMap = store.getFilesByIds(pendingFileIds);
|
|
51988
|
+
const fileWorkspace = /* @__PURE__ */ new Map();
|
|
51989
|
+
for (const f of allPhpFiles) {
|
|
51990
|
+
fileWorkspace.set(f.id, f.workspace);
|
|
51991
|
+
}
|
|
51992
|
+
for (let i = 0; i < pendingFileIds.length; i += CHUNK) {
|
|
51993
|
+
for (const [k2, v] of store.getNodeIdsBatch("file", pendingFileIds.slice(i, i + CHUNK))) {
|
|
51994
|
+
fileNodeMap.set(k2, v);
|
|
51995
|
+
}
|
|
51996
|
+
}
|
|
51997
|
+
let created = 0;
|
|
51998
|
+
store.db.transaction(() => {
|
|
51999
|
+
for (const [fileId, imports] of state.pendingImports) {
|
|
52000
|
+
const file = fileMap.get(fileId);
|
|
52001
|
+
if (!file || file.language !== "php") continue;
|
|
52002
|
+
const sourceNodeId = fileNodeMap.get(fileId);
|
|
52003
|
+
if (sourceNodeId == null) continue;
|
|
52004
|
+
const sourceWs = fileWorkspace.get(fileId) ?? null;
|
|
52005
|
+
const consolidated = /* @__PURE__ */ new Map();
|
|
52006
|
+
for (const { from, specifiers } of imports) {
|
|
52007
|
+
const existing = consolidated.get(from);
|
|
52008
|
+
if (existing) existing.push(...specifiers);
|
|
52009
|
+
else consolidated.set(from, [...specifiers]);
|
|
52010
|
+
}
|
|
52011
|
+
for (const [fqn, specifiers] of consolidated) {
|
|
52012
|
+
const target = resolvePhpFqn(fqn, sourceWs, fqnToFile, psr4Resolvers, pathToFile, state.rootPath);
|
|
52013
|
+
if (!target) continue;
|
|
52014
|
+
const targetNodeId = fileNodeMap.get(target.id);
|
|
52015
|
+
if (targetNodeId == null) continue;
|
|
52016
|
+
if (sourceNodeId === targetNodeId) continue;
|
|
52017
|
+
const isCrossWs = sourceWs !== target.workspace ? 1 : 0;
|
|
52018
|
+
insertStmt.run(
|
|
52019
|
+
sourceNodeId,
|
|
52020
|
+
targetNodeId,
|
|
52021
|
+
importsEdgeType.id,
|
|
52022
|
+
JSON.stringify({ from: fqn, specifiers }),
|
|
52023
|
+
isCrossWs
|
|
52024
|
+
);
|
|
52025
|
+
created++;
|
|
52026
|
+
}
|
|
52027
|
+
}
|
|
52028
|
+
})();
|
|
52029
|
+
if (created > 0) {
|
|
52030
|
+
logger.info({ edges: created }, "PHP import edges resolved");
|
|
52031
|
+
}
|
|
52032
|
+
}
|
|
52033
|
+
function resolvePhpFqn(fqn, sourceWorkspace, fqnIndex, psr4Resolvers, pathIndex, rootPath) {
|
|
52034
|
+
if (!fqn) return null;
|
|
52035
|
+
const wsKey = sourceWorkspace ?? "";
|
|
52036
|
+
const sameWs = fqnIndex.get(`${wsKey}\0${fqn}`);
|
|
52037
|
+
if (sameWs) return sameWs;
|
|
52038
|
+
const psr4 = psr4Resolvers.get(wsKey);
|
|
52039
|
+
if (psr4) {
|
|
52040
|
+
const resolved = psr4.resolve(fqn);
|
|
52041
|
+
if (resolved) {
|
|
52042
|
+
const projectRelative = sourceWorkspace ? `${sourceWorkspace}/${resolved}` : resolved;
|
|
52043
|
+
const fromPath = pathIndex.get(projectRelative);
|
|
52044
|
+
if (fromPath) return fromPath;
|
|
52045
|
+
}
|
|
52046
|
+
}
|
|
52047
|
+
if (sourceWorkspace) {
|
|
52048
|
+
const noWs = fqnIndex.get(`\0${fqn}`);
|
|
52049
|
+
if (noWs) return noWs;
|
|
52050
|
+
}
|
|
52051
|
+
return null;
|
|
52052
|
+
}
|
|
52053
|
+
|
|
51422
52054
|
// src/indexer/edge-resolvers/tests.ts
|
|
51423
52055
|
init_logger();
|
|
51424
52056
|
var TEST_PATH_RE = /\.(test|spec)\.[jt]sx?$|__tests__\/|(?:^|[/\\])test_[^/\\]+\.py$|(?:^|[/\\])[^/\\]+_test\.py$|conftest\.py$/;
|
|
@@ -51521,7 +52153,7 @@ var EdgeResolver = class {
|
|
|
51521
52153
|
for (const p of activeResult.value) seen.add(p.manifest.name);
|
|
51522
52154
|
}
|
|
51523
52155
|
for (const ws2 of this.state.workspaces) {
|
|
51524
|
-
const wsRoot =
|
|
52156
|
+
const wsRoot = path18.join(this.state.rootPath, ws2.path);
|
|
51525
52157
|
const wsCtx = buildProjectContext(wsRoot);
|
|
51526
52158
|
const wsPlugins = this.state.registry.getAllFrameworkPlugins().filter((p) => !seen.has(p.manifest.name) && p.detect(wsCtx));
|
|
51527
52159
|
if (wsPlugins.length === 0) continue;
|
|
@@ -51558,6 +52190,10 @@ var EdgeResolver = class {
|
|
|
51558
52190
|
resolvePythonImportEdges() {
|
|
51559
52191
|
resolvePythonImportEdges(this.state);
|
|
51560
52192
|
}
|
|
52193
|
+
/** Pass 2e2: PHP import edges (PSR-4 use statements). */
|
|
52194
|
+
resolvePhpImportEdges() {
|
|
52195
|
+
resolvePhpImportEdges(this.state);
|
|
52196
|
+
}
|
|
51561
52197
|
/** Pass 2f: Python heritage edges (class inheritance). */
|
|
51562
52198
|
resolvePythonHeritageEdges() {
|
|
51563
52199
|
resolvePythonHeritageEdges(this.state);
|
|
@@ -51730,12 +52366,12 @@ var EdgeResolver = class {
|
|
|
51730
52366
|
};
|
|
51731
52367
|
|
|
51732
52368
|
// src/indexer/file-extractor.ts
|
|
51733
|
-
import
|
|
51734
|
-
import
|
|
52369
|
+
import fs20 from "fs";
|
|
52370
|
+
import path19 from "path";
|
|
51735
52371
|
|
|
51736
52372
|
// src/utils/hasher.ts
|
|
51737
52373
|
import crypto5 from "crypto";
|
|
51738
|
-
import
|
|
52374
|
+
import fs19 from "fs";
|
|
51739
52375
|
function hashContent(content) {
|
|
51740
52376
|
return crypto5.createHash("md5").update(content).digest("hex");
|
|
51741
52377
|
}
|
|
@@ -51749,7 +52385,7 @@ var FileExtractor = class {
|
|
|
51749
52385
|
ctx;
|
|
51750
52386
|
async extract(relPath, force) {
|
|
51751
52387
|
const { store, registry, rootPath } = this.ctx;
|
|
51752
|
-
const absPath =
|
|
52388
|
+
const absPath = path19.resolve(rootPath, relPath);
|
|
51753
52389
|
const pathCheck = validatePath(relPath, rootPath);
|
|
51754
52390
|
if (pathCheck.isErr()) {
|
|
51755
52391
|
logger.warn({ file: relPath }, "Path traversal blocked");
|
|
@@ -51757,7 +52393,7 @@ var FileExtractor = class {
|
|
|
51757
52393
|
}
|
|
51758
52394
|
let fileMtimeMs = null;
|
|
51759
52395
|
try {
|
|
51760
|
-
const stat =
|
|
52396
|
+
const stat = fs20.lstatSync(absPath);
|
|
51761
52397
|
if (stat.isSymbolicLink()) {
|
|
51762
52398
|
logger.warn({ file: relPath }, "Symlink skipped");
|
|
51763
52399
|
return "error";
|
|
@@ -51775,7 +52411,7 @@ var FileExtractor = class {
|
|
|
51775
52411
|
}
|
|
51776
52412
|
let content;
|
|
51777
52413
|
try {
|
|
51778
|
-
content =
|
|
52414
|
+
content = fs20.readFileSync(absPath);
|
|
51779
52415
|
} catch {
|
|
51780
52416
|
logger.warn({ file: relPath }, "Cannot read file");
|
|
51781
52417
|
return "error";
|
|
@@ -51812,7 +52448,7 @@ var FileExtractor = class {
|
|
|
51812
52448
|
const importEdges = [];
|
|
51813
52449
|
if (parsed.edges?.length) {
|
|
51814
52450
|
for (const edge of parsed.edges) {
|
|
51815
|
-
const isImportEdge = (edge.edgeType === "imports" || edge.edgeType === "py_imports") && !edge.sourceNodeType && !edge.sourceSymbolId;
|
|
52451
|
+
const isImportEdge = (edge.edgeType === "imports" || edge.edgeType === "py_imports" || edge.edgeType === "php_imports") && !edge.sourceNodeType && !edge.sourceSymbolId;
|
|
51816
52452
|
if (isImportEdge) {
|
|
51817
52453
|
importEdges.push({
|
|
51818
52454
|
from: edge.metadata?.["from"] ?? "",
|
|
@@ -51881,7 +52517,7 @@ var FileExtractor = class {
|
|
|
51881
52517
|
if (wsPath) {
|
|
51882
52518
|
let cached = this.wsPluginCache.get(wsPath);
|
|
51883
52519
|
if (cached === void 0) {
|
|
51884
|
-
const wsRoot =
|
|
52520
|
+
const wsRoot = path19.join(this.ctx.rootPath, wsPath);
|
|
51885
52521
|
const wsCtx = buildProjectContext(wsRoot);
|
|
51886
52522
|
cached = this.ctx.registry.getAllFrameworkPlugins().filter((p) => p.detect(wsCtx));
|
|
51887
52523
|
this.wsPluginCache.set(wsPath, cached);
|
|
@@ -51918,7 +52554,7 @@ var FileExtractor = class {
|
|
|
51918
52554
|
return null;
|
|
51919
52555
|
}
|
|
51920
52556
|
detectLanguage(filePath) {
|
|
51921
|
-
const ext =
|
|
52557
|
+
const ext = path19.extname(filePath).slice(1);
|
|
51922
52558
|
const map = {
|
|
51923
52559
|
php: "php",
|
|
51924
52560
|
ts: "typescript",
|
|
@@ -51934,8 +52570,8 @@ var FileExtractor = class {
|
|
|
51934
52570
|
};
|
|
51935
52571
|
|
|
51936
52572
|
// src/indexer/env-indexer.ts
|
|
51937
|
-
import
|
|
51938
|
-
import
|
|
52573
|
+
import fs21 from "fs";
|
|
52574
|
+
import path20 from "path";
|
|
51939
52575
|
import fg2 from "fast-glob";
|
|
51940
52576
|
|
|
51941
52577
|
// src/utils/env-parser.ts
|
|
@@ -52066,12 +52702,12 @@ var EnvIndexer = class {
|
|
|
52066
52702
|
logger.debug({ file: relPath }, ".env file skipped by .traceignore");
|
|
52067
52703
|
continue;
|
|
52068
52704
|
}
|
|
52069
|
-
const absPath =
|
|
52705
|
+
const absPath = path20.resolve(this.rootPath, relPath);
|
|
52070
52706
|
const pathCheck = validatePath(relPath, this.rootPath);
|
|
52071
52707
|
if (pathCheck.isErr()) continue;
|
|
52072
52708
|
let content;
|
|
52073
52709
|
try {
|
|
52074
|
-
content =
|
|
52710
|
+
content = fs21.readFileSync(absPath, "utf-8");
|
|
52075
52711
|
} catch {
|
|
52076
52712
|
logger.warn({ file: relPath }, "Cannot read .env file");
|
|
52077
52713
|
continue;
|
|
@@ -52165,7 +52801,7 @@ var IndexingPipeline = class _IndexingPipeline {
|
|
|
52165
52801
|
if (filePaths.length === 0) return;
|
|
52166
52802
|
this.store.db.transaction(() => {
|
|
52167
52803
|
for (const fp of filePaths) {
|
|
52168
|
-
const relPath =
|
|
52804
|
+
const relPath = path21.isAbsolute(fp) ? path21.relative(this.rootPath, fp) : fp;
|
|
52169
52805
|
const file = this.store.getFile(relPath);
|
|
52170
52806
|
if (file) {
|
|
52171
52807
|
this.store.deleteFile(file.id);
|
|
@@ -52180,7 +52816,7 @@ var IndexingPipeline = class _IndexingPipeline {
|
|
|
52180
52816
|
const start = Date.now();
|
|
52181
52817
|
const relPaths = [];
|
|
52182
52818
|
for (const fp of filePaths) {
|
|
52183
|
-
const rel =
|
|
52819
|
+
const rel = path21.isAbsolute(fp) ? path21.relative(this.rootPath, fp) : fp;
|
|
52184
52820
|
const check = validatePath(rel, this.rootPath);
|
|
52185
52821
|
if (check.isErr()) {
|
|
52186
52822
|
logger.warn({ file: fp }, "Path traversal blocked in indexFiles");
|
|
@@ -52298,6 +52934,7 @@ var IndexingPipeline = class _IndexingPipeline {
|
|
|
52298
52934
|
edgeResolver.resolveTypeScriptHeritageEdges();
|
|
52299
52935
|
edgeResolver.resolveEsmImportEdges();
|
|
52300
52936
|
edgeResolver.resolvePythonImportEdges();
|
|
52937
|
+
edgeResolver.resolvePhpImportEdges();
|
|
52301
52938
|
edgeResolver.resolvePythonHeritageEdges();
|
|
52302
52939
|
edgeResolver.resolvePythonCallEdges();
|
|
52303
52940
|
edgeResolver.resolveTestCoversEdges();
|
|
@@ -52343,7 +52980,7 @@ var IndexingPipeline = class _IndexingPipeline {
|
|
|
52343
52980
|
const activeResult = this.registry.getActiveFrameworkPlugins(ctx);
|
|
52344
52981
|
if (activeResult.isOk()) registerSchema(activeResult.value);
|
|
52345
52982
|
for (const ws2 of this.workspaces) {
|
|
52346
|
-
const wsRoot =
|
|
52983
|
+
const wsRoot = path21.join(this.rootPath, ws2.path);
|
|
52347
52984
|
const wsCtx = buildProjectContext(wsRoot);
|
|
52348
52985
|
const wsPlugins = this.registry.getAllFrameworkPlugins().filter((p) => p.detect(wsCtx));
|
|
52349
52986
|
registerSchema(wsPlugins);
|
|
@@ -52378,7 +53015,7 @@ var IndexingPipeline = class _IndexingPipeline {
|
|
|
52378
53015
|
const cached = this._fileContentCache.get(relPath);
|
|
52379
53016
|
if (cached !== void 0) return cached;
|
|
52380
53017
|
try {
|
|
52381
|
-
return
|
|
53018
|
+
return fs23.readFileSync(path21.resolve(this.rootPath, relPath), "utf-8");
|
|
52382
53019
|
} catch {
|
|
52383
53020
|
return void 0;
|
|
52384
53021
|
}
|
|
@@ -52734,28 +53371,28 @@ function registerCoreTools(server, ctx) {
|
|
|
52734
53371
|
import { z as z3 } from "zod";
|
|
52735
53372
|
|
|
52736
53373
|
// src/tools/navigation/navigation.ts
|
|
52737
|
-
import
|
|
53374
|
+
import path24 from "path";
|
|
52738
53375
|
|
|
52739
53376
|
// src/utils/source-reader.ts
|
|
52740
|
-
import
|
|
52741
|
-
import
|
|
53377
|
+
import fs24 from "fs";
|
|
53378
|
+
import path23 from "path";
|
|
52742
53379
|
var GITIGNORED_NOTICE = "[content hidden \u2014 file is gitignored]";
|
|
52743
53380
|
function readByteRange(filePath, byteStart, byteEnd, gitignored) {
|
|
52744
53381
|
if (gitignored && !isEnvFile(filePath)) return GITIGNORED_NOTICE;
|
|
52745
53382
|
if (byteEnd <= byteStart || byteStart < 0) return "";
|
|
52746
|
-
const fd =
|
|
53383
|
+
const fd = fs24.openSync(filePath, "r");
|
|
52747
53384
|
try {
|
|
52748
53385
|
const length = byteEnd - byteStart;
|
|
52749
53386
|
const buffer = Buffer.alloc(length);
|
|
52750
|
-
const bytesRead =
|
|
53387
|
+
const bytesRead = fs24.readSync(fd, buffer, 0, length, byteStart);
|
|
52751
53388
|
return buffer.subarray(0, bytesRead).toString("utf8");
|
|
52752
53389
|
} finally {
|
|
52753
|
-
|
|
53390
|
+
fs24.closeSync(fd);
|
|
52754
53391
|
}
|
|
52755
53392
|
}
|
|
52756
53393
|
var ENV_BASENAME_RE = /^\.env(\..+)?$/;
|
|
52757
53394
|
function isEnvFile(filePath) {
|
|
52758
|
-
return ENV_BASENAME_RE.test(
|
|
53395
|
+
return ENV_BASENAME_RE.test(path23.basename(filePath));
|
|
52759
53396
|
}
|
|
52760
53397
|
|
|
52761
53398
|
// src/scoring/signal-fusion.ts
|
|
@@ -52910,7 +53547,7 @@ function getSymbol(store, rootPath, opts) {
|
|
|
52910
53547
|
if (!file) {
|
|
52911
53548
|
return err3(notFound(`file:${symbol.file_id}`));
|
|
52912
53549
|
}
|
|
52913
|
-
const absPath =
|
|
53550
|
+
const absPath = path24.resolve(rootPath, file.path);
|
|
52914
53551
|
let source;
|
|
52915
53552
|
let truncated;
|
|
52916
53553
|
try {
|
|
@@ -53797,9 +54434,9 @@ function deduplicateByFile(rawDeps) {
|
|
|
53797
54434
|
}
|
|
53798
54435
|
}
|
|
53799
54436
|
const result = [];
|
|
53800
|
-
for (const [
|
|
54437
|
+
for (const [path67, entry] of fileMap) {
|
|
53801
54438
|
const dep = {
|
|
53802
|
-
path:
|
|
54439
|
+
path: path67,
|
|
53803
54440
|
edgeTypes: [...entry.edgeTypes],
|
|
53804
54441
|
depth: entry.depth
|
|
53805
54442
|
};
|
|
@@ -53992,7 +54629,7 @@ function getPennantImpact(store, name) {
|
|
|
53992
54629
|
}
|
|
53993
54630
|
|
|
53994
54631
|
// src/tools/navigation/context.ts
|
|
53995
|
-
import
|
|
54632
|
+
import path25 from "path";
|
|
53996
54633
|
|
|
53997
54634
|
// src/utils/token-counter.ts
|
|
53998
54635
|
function estimateTokens(text) {
|
|
@@ -54252,7 +54889,7 @@ function getFeatureContext(store, rootPath, description, tokenBudget = 4e3) {
|
|
|
54252
54889
|
const meta = `[${item.symbol.kind}] ${item.symbol.fqn ?? item.symbol.name} (${item.file.path})`;
|
|
54253
54890
|
let source;
|
|
54254
54891
|
try {
|
|
54255
|
-
const absPath =
|
|
54892
|
+
const absPath = path25.resolve(rootPath, item.file.path);
|
|
54256
54893
|
source = readByteRange(absPath, item.symbol.byte_start, item.symbol.byte_end, !!item.file.gitignored);
|
|
54257
54894
|
} catch {
|
|
54258
54895
|
}
|
|
@@ -54288,7 +54925,7 @@ function getFeatureContext(store, rootPath, description, tokenBudget = 4e3) {
|
|
|
54288
54925
|
}
|
|
54289
54926
|
|
|
54290
54927
|
// src/tools/navigation/context-bundle.ts
|
|
54291
|
-
import
|
|
54928
|
+
import path26 from "path";
|
|
54292
54929
|
import { ok as ok3, err as err4 } from "neverthrow";
|
|
54293
54930
|
|
|
54294
54931
|
// src/scoring/structured-assembly.ts
|
|
@@ -54376,9 +55013,9 @@ var FileReadCache = class {
|
|
|
54376
55013
|
let buf = this.cache.get(file.id);
|
|
54377
55014
|
if (buf === void 0) {
|
|
54378
55015
|
try {
|
|
54379
|
-
const absPath =
|
|
54380
|
-
const
|
|
54381
|
-
buf =
|
|
55016
|
+
const absPath = path26.resolve(this.rootPath, file.path);
|
|
55017
|
+
const fs57 = __require("fs");
|
|
55018
|
+
buf = fs57.readFileSync(absPath);
|
|
54382
55019
|
} catch {
|
|
54383
55020
|
buf = null;
|
|
54384
55021
|
}
|
|
@@ -54536,7 +55173,7 @@ function getContextBundle(store, rootPath, opts) {
|
|
|
54536
55173
|
}
|
|
54537
55174
|
|
|
54538
55175
|
// src/tools/navigation/task-context.ts
|
|
54539
|
-
import
|
|
55176
|
+
import path27 from "path";
|
|
54540
55177
|
var INTENT_PATTERNS = [
|
|
54541
55178
|
[/\b(fix|bug|error|crash(?:es|ed|ing)?|broken|issue|fail(?:ing|s|ed)?|wrong|regression|debug|patch|hotfix)\b/i, "bugfix"],
|
|
54542
55179
|
[/\b(add|create|new|implement|build|introduce|feature|setup|integrate|wire|connect)\b/i, "new_feature"],
|
|
@@ -54763,7 +55400,7 @@ async function getTaskContext(store, rootPath, opts, ai) {
|
|
|
54763
55400
|
const meta = `[${entry.symbol.kind}] ${entry.symbol.fqn ?? entry.symbol.name} (${entry.file.path})`;
|
|
54764
55401
|
let source;
|
|
54765
55402
|
try {
|
|
54766
|
-
const absPath =
|
|
55403
|
+
const absPath = path27.resolve(rootPath, entry.file.path);
|
|
54767
55404
|
source = readByteRange(absPath, entry.symbol.byte_start, entry.symbol.byte_end, !!entry.file.gitignored);
|
|
54768
55405
|
} catch {
|
|
54769
55406
|
}
|
|
@@ -55132,8 +55769,8 @@ function buildNegativeEvidence(filesOrOpts, indexedSymbols, queryExpanded, toolN
|
|
|
55132
55769
|
}
|
|
55133
55770
|
|
|
55134
55771
|
// src/tools/navigation/search-text.ts
|
|
55135
|
-
import
|
|
55136
|
-
import
|
|
55772
|
+
import fs25 from "fs";
|
|
55773
|
+
import path28 from "path";
|
|
55137
55774
|
import picomatch from "picomatch";
|
|
55138
55775
|
function searchText(store, projectRoot, opts) {
|
|
55139
55776
|
const {
|
|
@@ -55177,14 +55814,14 @@ function searchText(store, projectRoot, opts) {
|
|
|
55177
55814
|
truncated = true;
|
|
55178
55815
|
break;
|
|
55179
55816
|
}
|
|
55180
|
-
const absPath =
|
|
55817
|
+
const absPath = path28.resolve(projectRoot, file.path);
|
|
55181
55818
|
const pathCheck = validatePath(file.path, projectRoot);
|
|
55182
55819
|
if (pathCheck.isErr()) continue;
|
|
55183
55820
|
let content;
|
|
55184
55821
|
try {
|
|
55185
|
-
const stat =
|
|
55822
|
+
const stat = fs25.statSync(absPath);
|
|
55186
55823
|
if (stat.size > 1048576) continue;
|
|
55187
|
-
content =
|
|
55824
|
+
content = fs25.readFileSync(absPath, "utf-8");
|
|
55188
55825
|
} catch {
|
|
55189
55826
|
continue;
|
|
55190
55827
|
}
|
|
@@ -55232,8 +55869,8 @@ function escapeRegex(str2) {
|
|
|
55232
55869
|
|
|
55233
55870
|
// src/tools/navigation/zero-index.ts
|
|
55234
55871
|
import { execFileSync as execFileSync3 } from "child_process";
|
|
55235
|
-
import { readFileSync as
|
|
55236
|
-
import
|
|
55872
|
+
import { readFileSync as readFileSync3, readdirSync, statSync } from "fs";
|
|
55873
|
+
import path29 from "path";
|
|
55237
55874
|
var RG_ARGS_BASE = [
|
|
55238
55875
|
"--json",
|
|
55239
55876
|
"--max-count=200",
|
|
@@ -55264,7 +55901,7 @@ function searchWithRipgrep(projectRoot, query, opts) {
|
|
|
55264
55901
|
const parsed = JSON.parse(line);
|
|
55265
55902
|
if (parsed.type !== "match") continue;
|
|
55266
55903
|
const data = parsed.data;
|
|
55267
|
-
const relPath =
|
|
55904
|
+
const relPath = path29.relative(projectRoot, data.path.text);
|
|
55268
55905
|
matches.push({
|
|
55269
55906
|
file: relPath,
|
|
55270
55907
|
line: data.line_number,
|
|
@@ -55300,7 +55937,7 @@ function manualSearch(projectRoot, query, opts) {
|
|
|
55300
55937
|
for (const entry of entries) {
|
|
55301
55938
|
if (matches.length >= limit) return;
|
|
55302
55939
|
if (traceignore.isSkippedDir(entry)) continue;
|
|
55303
|
-
const full2 =
|
|
55940
|
+
const full2 = path29.join(dir, entry);
|
|
55304
55941
|
let stat;
|
|
55305
55942
|
try {
|
|
55306
55943
|
stat = statSync(full2);
|
|
@@ -55310,17 +55947,17 @@ function manualSearch(projectRoot, query, opts) {
|
|
|
55310
55947
|
if (stat.isDirectory()) {
|
|
55311
55948
|
walk(full2);
|
|
55312
55949
|
} else if (stat.isFile() && stat.size < 512 * 1024) {
|
|
55313
|
-
const rel =
|
|
55950
|
+
const rel = path29.relative(projectRoot, full2);
|
|
55314
55951
|
if (traceignore.isIgnored(rel)) continue;
|
|
55315
55952
|
try {
|
|
55316
|
-
const content =
|
|
55953
|
+
const content = readFileSync3(full2, "utf-8");
|
|
55317
55954
|
const lines = content.split("\n");
|
|
55318
55955
|
for (let i = 0; i < lines.length; i++) {
|
|
55319
55956
|
regex.lastIndex = 0;
|
|
55320
55957
|
const m = regex.exec(lines[i]);
|
|
55321
55958
|
if (m) {
|
|
55322
55959
|
matches.push({
|
|
55323
|
-
file:
|
|
55960
|
+
file: path29.relative(projectRoot, full2),
|
|
55324
55961
|
line: i + 1,
|
|
55325
55962
|
column: m.index + 1,
|
|
55326
55963
|
text: lines[i].trimEnd()
|
|
@@ -55387,7 +56024,7 @@ SYMBOL_PATTERNS["tsx"] = SYMBOL_PATTERNS["typescript"];
|
|
|
55387
56024
|
SYMBOL_PATTERNS["jsx"] = SYMBOL_PATTERNS["javascript"];
|
|
55388
56025
|
SYMBOL_PATTERNS["kotlin"] = SYMBOL_PATTERNS["java"];
|
|
55389
56026
|
function detectLanguage(filePath) {
|
|
55390
|
-
const ext =
|
|
56027
|
+
const ext = path29.extname(filePath).toLowerCase();
|
|
55391
56028
|
const map = {
|
|
55392
56029
|
".ts": "typescript",
|
|
55393
56030
|
".tsx": "typescript",
|
|
@@ -55438,8 +56075,8 @@ function fallbackSearch(projectRoot, query, opts = {}) {
|
|
|
55438
56075
|
};
|
|
55439
56076
|
}
|
|
55440
56077
|
function fallbackOutline(projectRoot, filePath) {
|
|
55441
|
-
const absPath =
|
|
55442
|
-
const content =
|
|
56078
|
+
const absPath = path29.resolve(projectRoot, filePath);
|
|
56079
|
+
const content = readFileSync3(absPath, "utf-8");
|
|
55443
56080
|
const language = detectLanguage(filePath);
|
|
55444
56081
|
const symbols = extractSymbolsFromContent(content, language);
|
|
55445
56082
|
return {
|
|
@@ -55495,13 +56132,13 @@ function computeAdaptiveBudget(toolName, state, userBudget) {
|
|
|
55495
56132
|
}
|
|
55496
56133
|
|
|
55497
56134
|
// src/subproject/manager.ts
|
|
55498
|
-
import
|
|
55499
|
-
import
|
|
56135
|
+
import path34 from "path";
|
|
56136
|
+
import fs31 from "fs";
|
|
55500
56137
|
|
|
55501
56138
|
// src/topology/contract-parser.ts
|
|
55502
56139
|
init_logger();
|
|
55503
|
-
import
|
|
55504
|
-
import
|
|
56140
|
+
import fs26 from "fs";
|
|
56141
|
+
import path30 from "path";
|
|
55505
56142
|
import Database2 from "better-sqlite3";
|
|
55506
56143
|
var EXCLUDE_DIRS = ["node_modules", "vendor", ".git", "dist", "build", "__pycache__"];
|
|
55507
56144
|
function parseContracts(repoRoot) {
|
|
@@ -55509,8 +56146,8 @@ function parseContracts(repoRoot) {
|
|
|
55509
56146
|
const specFiles = findSpecFiles(repoRoot);
|
|
55510
56147
|
for (const { filePath, type } of specFiles) {
|
|
55511
56148
|
try {
|
|
55512
|
-
const content =
|
|
55513
|
-
const relPath =
|
|
56149
|
+
const content = fs26.readFileSync(filePath, "utf-8");
|
|
56150
|
+
const relPath = path30.relative(repoRoot, filePath);
|
|
55514
56151
|
let contract = null;
|
|
55515
56152
|
switch (type) {
|
|
55516
56153
|
case "openapi":
|
|
@@ -55683,13 +56320,13 @@ function findSpecFiles(root) {
|
|
|
55683
56320
|
if (depth > 5) return;
|
|
55684
56321
|
let entries;
|
|
55685
56322
|
try {
|
|
55686
|
-
entries =
|
|
56323
|
+
entries = fs26.readdirSync(dir, { withFileTypes: true });
|
|
55687
56324
|
} catch {
|
|
55688
56325
|
return;
|
|
55689
56326
|
}
|
|
55690
56327
|
for (const entry of entries) {
|
|
55691
56328
|
if (EXCLUDE_DIRS.includes(entry.name)) continue;
|
|
55692
|
-
const fullPath =
|
|
56329
|
+
const fullPath = path30.join(dir, entry.name);
|
|
55693
56330
|
if (entry.isDirectory()) {
|
|
55694
56331
|
walk(fullPath, depth + 1);
|
|
55695
56332
|
} else if (entry.isFile()) {
|
|
@@ -55707,8 +56344,9 @@ function findSpecFiles(root) {
|
|
|
55707
56344
|
walk(root, 0);
|
|
55708
56345
|
return results;
|
|
55709
56346
|
}
|
|
56347
|
+
var HTTP_METHODS = /* @__PURE__ */ new Set(["GET", "POST", "PUT", "PATCH", "DELETE", "HEAD", "OPTIONS", "ANY"]);
|
|
55710
56348
|
function extractRoutesFromDb(dbPath, pathPrefix) {
|
|
55711
|
-
if (!
|
|
56349
|
+
if (!fs26.existsSync(dbPath)) return null;
|
|
55712
56350
|
try {
|
|
55713
56351
|
const db = new Database2(dbPath, { readonly: true });
|
|
55714
56352
|
try {
|
|
@@ -55727,6 +56365,7 @@ function extractRoutesFromDb(dbPath, pathPrefix) {
|
|
|
55727
56365
|
"SELECT method, uri, name FROM routes ORDER BY uri"
|
|
55728
56366
|
).all();
|
|
55729
56367
|
}
|
|
56368
|
+
rows = rows.filter((r) => HTTP_METHODS.has(r.method));
|
|
55730
56369
|
if (rows.length === 0) return null;
|
|
55731
56370
|
const endpoints = rows.map((r) => ({
|
|
55732
56371
|
method: r.method === "ANY" ? null : r.method,
|
|
@@ -55752,12 +56391,12 @@ function extractRoutesFromDb(dbPath, pathPrefix) {
|
|
|
55752
56391
|
|
|
55753
56392
|
// src/topology/service-detector.ts
|
|
55754
56393
|
init_logger();
|
|
55755
|
-
import
|
|
55756
|
-
import
|
|
56394
|
+
import fs28 from "fs";
|
|
56395
|
+
import path32 from "path";
|
|
55757
56396
|
|
|
55758
56397
|
// src/project-root.ts
|
|
55759
|
-
import
|
|
55760
|
-
import
|
|
56398
|
+
import fs27 from "fs";
|
|
56399
|
+
import path31 from "path";
|
|
55761
56400
|
var ROOT_MARKERS = [
|
|
55762
56401
|
// VCS
|
|
55763
56402
|
".git",
|
|
@@ -55821,7 +56460,7 @@ var SKIP_DIRS2 = /* @__PURE__ */ new Set([".git", "node_modules", "vendor", ".sv
|
|
|
55821
56460
|
function detectServices(repoRoots) {
|
|
55822
56461
|
const services = [];
|
|
55823
56462
|
for (const root of repoRoots) {
|
|
55824
|
-
const absRoot =
|
|
56463
|
+
const absRoot = path32.resolve(root);
|
|
55825
56464
|
const composeServices = detectFromDockerCompose(absRoot);
|
|
55826
56465
|
if (composeServices.length > 0) {
|
|
55827
56466
|
services.push(...composeServices);
|
|
@@ -55833,7 +56472,7 @@ function detectServices(repoRoots) {
|
|
|
55833
56472
|
continue;
|
|
55834
56473
|
}
|
|
55835
56474
|
services.push({
|
|
55836
|
-
name:
|
|
56475
|
+
name: path32.basename(absRoot),
|
|
55837
56476
|
repoRoot: absRoot,
|
|
55838
56477
|
serviceType: "monolith",
|
|
55839
56478
|
detectionSource: "workspace"
|
|
@@ -55844,7 +56483,7 @@ function detectServices(repoRoots) {
|
|
|
55844
56483
|
function detectFromWorkspaceStructure(root) {
|
|
55845
56484
|
let entries;
|
|
55846
56485
|
try {
|
|
55847
|
-
entries =
|
|
56486
|
+
entries = fs28.readdirSync(root, { withFileTypes: true });
|
|
55848
56487
|
} catch {
|
|
55849
56488
|
return [];
|
|
55850
56489
|
}
|
|
@@ -55853,7 +56492,7 @@ function detectFromWorkspaceStructure(root) {
|
|
|
55853
56492
|
for (const entry of entries) {
|
|
55854
56493
|
if (!entry.isDirectory()) continue;
|
|
55855
56494
|
if (entry.name.startsWith(".") || SKIP_DIRS2.has(entry.name)) continue;
|
|
55856
|
-
const childDir =
|
|
56495
|
+
const childDir = path32.join(root, entry.name);
|
|
55857
56496
|
if (hasRootMarker(childDir)) {
|
|
55858
56497
|
flatServices.push({
|
|
55859
56498
|
name: entry.name,
|
|
@@ -55873,14 +56512,14 @@ function detectFromWorkspaceStructure(root) {
|
|
|
55873
56512
|
for (const { name: groupName, dir: groupDir } of dirsWithoutMarker) {
|
|
55874
56513
|
let childEntries;
|
|
55875
56514
|
try {
|
|
55876
|
-
childEntries =
|
|
56515
|
+
childEntries = fs28.readdirSync(groupDir, { withFileTypes: true });
|
|
55877
56516
|
} catch {
|
|
55878
56517
|
continue;
|
|
55879
56518
|
}
|
|
55880
56519
|
for (const childEntry of childEntries) {
|
|
55881
56520
|
if (!childEntry.isDirectory()) continue;
|
|
55882
56521
|
if (childEntry.name.startsWith(".") || SKIP_DIRS2.has(childEntry.name)) continue;
|
|
55883
|
-
const childDir =
|
|
56522
|
+
const childDir = path32.join(groupDir, childEntry.name);
|
|
55884
56523
|
if (hasRootMarker(childDir)) {
|
|
55885
56524
|
groupedServices.push({
|
|
55886
56525
|
name: `${groupName}/${childEntry.name}`,
|
|
@@ -55901,7 +56540,7 @@ function detectFromWorkspaceStructure(root) {
|
|
|
55901
56540
|
}
|
|
55902
56541
|
function hasRootMarker(dir) {
|
|
55903
56542
|
for (const marker of ROOT_MARKERS) {
|
|
55904
|
-
if (
|
|
56543
|
+
if (fs28.existsSync(path32.join(dir, marker))) return true;
|
|
55905
56544
|
}
|
|
55906
56545
|
return false;
|
|
55907
56546
|
}
|
|
@@ -55909,15 +56548,15 @@ function detectFromDockerCompose(root) {
|
|
|
55909
56548
|
const composeFiles = ["docker-compose.yml", "docker-compose.yaml", "compose.yml", "compose.yaml"];
|
|
55910
56549
|
let composePath;
|
|
55911
56550
|
for (const f of composeFiles) {
|
|
55912
|
-
const p =
|
|
55913
|
-
if (
|
|
56551
|
+
const p = path32.join(root, f);
|
|
56552
|
+
if (fs28.existsSync(p)) {
|
|
55914
56553
|
composePath = p;
|
|
55915
56554
|
break;
|
|
55916
56555
|
}
|
|
55917
56556
|
}
|
|
55918
56557
|
if (!composePath) return [];
|
|
55919
56558
|
try {
|
|
55920
|
-
const content =
|
|
56559
|
+
const content = fs28.readFileSync(composePath, "utf-8");
|
|
55921
56560
|
const services = [];
|
|
55922
56561
|
const lines = content.split("\n");
|
|
55923
56562
|
let inServices = false;
|
|
@@ -55964,8 +56603,8 @@ function detectFromDockerCompose(root) {
|
|
|
55964
56603
|
|
|
55965
56604
|
// src/subproject/scanner.ts
|
|
55966
56605
|
init_logger();
|
|
55967
|
-
import
|
|
55968
|
-
import
|
|
56606
|
+
import fs29 from "fs";
|
|
56607
|
+
import path33 from "path";
|
|
55969
56608
|
var CALL_PATTERNS = [
|
|
55970
56609
|
// fetch('url') / fetch(`url`)
|
|
55971
56610
|
{
|
|
@@ -56092,19 +56731,19 @@ function walkAndScan(dir, repoRoot, results, depth) {
|
|
|
56092
56731
|
if (depth > 10) return;
|
|
56093
56732
|
let entries;
|
|
56094
56733
|
try {
|
|
56095
|
-
entries =
|
|
56734
|
+
entries = fs29.readdirSync(dir, { withFileTypes: true });
|
|
56096
56735
|
} catch {
|
|
56097
56736
|
return;
|
|
56098
56737
|
}
|
|
56099
56738
|
for (const entry of entries) {
|
|
56100
56739
|
if (EXCLUDE_DIRS2.has(entry.name)) continue;
|
|
56101
|
-
const fullPath =
|
|
56740
|
+
const fullPath = path33.join(dir, entry.name);
|
|
56102
56741
|
if (entry.isDirectory()) {
|
|
56103
56742
|
walkAndScan(fullPath, repoRoot, results, depth + 1);
|
|
56104
|
-
} else if (entry.isFile() && CODE_EXTENSIONS.has(
|
|
56743
|
+
} else if (entry.isFile() && CODE_EXTENSIONS.has(path33.extname(entry.name).toLowerCase())) {
|
|
56105
56744
|
try {
|
|
56106
|
-
const content =
|
|
56107
|
-
const relPath =
|
|
56745
|
+
const content = fs29.readFileSync(fullPath, "utf-8");
|
|
56746
|
+
const relPath = path33.relative(repoRoot, fullPath);
|
|
56108
56747
|
scanFileContent(relPath, content, results);
|
|
56109
56748
|
} catch {
|
|
56110
56749
|
}
|
|
@@ -56144,7 +56783,7 @@ function scanFileContent(filePath, content, results) {
|
|
|
56144
56783
|
init_logger();
|
|
56145
56784
|
|
|
56146
56785
|
// src/subproject/subproject-search.ts
|
|
56147
|
-
import
|
|
56786
|
+
import fs30 from "fs";
|
|
56148
56787
|
import Database3 from "better-sqlite3";
|
|
56149
56788
|
init_logger();
|
|
56150
56789
|
function subprojectSearch(topoStore, query, filters, limit = 20, excludeRoot) {
|
|
@@ -56153,7 +56792,7 @@ function subprojectSearch(topoStore, query, filters, limit = 20, excludeRoot) {
|
|
|
56153
56792
|
let reposSearched = 0;
|
|
56154
56793
|
const normalizedExclude = excludeRoot?.replace(/\/+$/, "");
|
|
56155
56794
|
for (const repo of repos) {
|
|
56156
|
-
if (!repo.db_path || !
|
|
56795
|
+
if (!repo.db_path || !fs30.existsSync(repo.db_path)) continue;
|
|
56157
56796
|
if (normalizedExclude && repo.repo_root.replace(/\/+$/, "") === normalizedExclude) continue;
|
|
56158
56797
|
let db = null;
|
|
56159
56798
|
try {
|
|
@@ -56462,18 +57101,18 @@ var SubprojectManager = class {
|
|
|
56462
57101
|
* @param opts - optional name, contract paths
|
|
56463
57102
|
*/
|
|
56464
57103
|
add(repoRoot, projectRoot, opts) {
|
|
56465
|
-
const absRoot =
|
|
56466
|
-
const absProjectRoot =
|
|
56467
|
-
if (!
|
|
57104
|
+
const absRoot = path34.resolve(repoRoot);
|
|
57105
|
+
const absProjectRoot = path34.resolve(projectRoot);
|
|
57106
|
+
if (!fs31.existsSync(absRoot)) {
|
|
56468
57107
|
throw new Error(`Repository path does not exist: ${absRoot}`);
|
|
56469
57108
|
}
|
|
56470
|
-
const repoName = opts?.name ??
|
|
57109
|
+
const repoName = opts?.name ?? path34.basename(absRoot);
|
|
56471
57110
|
const dbPath = getDbPath(absRoot);
|
|
56472
57111
|
const repoId = this.topoStore.upsertSubproject({
|
|
56473
57112
|
name: repoName,
|
|
56474
57113
|
repoRoot: absRoot,
|
|
56475
57114
|
projectRoot: absProjectRoot,
|
|
56476
|
-
dbPath:
|
|
57115
|
+
dbPath: fs31.existsSync(dbPath) ? dbPath : void 0,
|
|
56477
57116
|
contractPaths: opts?.contractPaths
|
|
56478
57117
|
});
|
|
56479
57118
|
const detected = detectServices([absRoot]);
|
|
@@ -56487,6 +57126,7 @@ var SubprojectManager = class {
|
|
|
56487
57126
|
projectGroup: svc.projectGroup,
|
|
56488
57127
|
metadata: svc.metadata
|
|
56489
57128
|
});
|
|
57129
|
+
this.topoStore.deleteContractsByService(serviceId);
|
|
56490
57130
|
this.registerContracts(serviceId, svc.repoRoot, absRoot, opts?.contractPaths);
|
|
56491
57131
|
}
|
|
56492
57132
|
const clientCalls = this.scanAndLinkClientCalls(repoId, absRoot);
|
|
@@ -56509,8 +57149,8 @@ var SubprojectManager = class {
|
|
|
56509
57149
|
* sub-services (from docker-compose, workspace structure, or root markers).
|
|
56510
57150
|
*/
|
|
56511
57151
|
autoDiscoverSubprojects(projectRoot, opts) {
|
|
56512
|
-
const absProjectRoot =
|
|
56513
|
-
if (!
|
|
57152
|
+
const absProjectRoot = path34.resolve(projectRoot);
|
|
57153
|
+
if (!fs31.existsSync(absProjectRoot)) {
|
|
56514
57154
|
throw new Error(`Project path does not exist: ${absProjectRoot}`);
|
|
56515
57155
|
}
|
|
56516
57156
|
const detected = detectServices([absProjectRoot]);
|
|
@@ -56522,7 +57162,7 @@ var SubprojectManager = class {
|
|
|
56522
57162
|
name: repoName,
|
|
56523
57163
|
repoRoot: svc.repoRoot,
|
|
56524
57164
|
projectRoot: absProjectRoot,
|
|
56525
|
-
dbPath:
|
|
57165
|
+
dbPath: fs31.existsSync(dbPath) ? dbPath : void 0,
|
|
56526
57166
|
contractPaths: opts?.contractPaths
|
|
56527
57167
|
});
|
|
56528
57168
|
const serviceId = this.topoStore.upsertService({
|
|
@@ -56534,6 +57174,7 @@ var SubprojectManager = class {
|
|
|
56534
57174
|
projectGroup: svc.projectGroup,
|
|
56535
57175
|
metadata: svc.metadata
|
|
56536
57176
|
});
|
|
57177
|
+
this.topoStore.deleteContractsByService(serviceId);
|
|
56537
57178
|
this.registerContracts(serviceId, svc.repoRoot, svc.repoRoot, opts?.contractPaths);
|
|
56538
57179
|
const clientCalls = this.scanAndLinkClientCalls(repoId, svc.repoRoot);
|
|
56539
57180
|
this.topoStore.updateSubprojectSyncTime(repoId);
|
|
@@ -56636,7 +57277,7 @@ var SubprojectManager = class {
|
|
|
56636
57277
|
let endpointsUpdated = 0;
|
|
56637
57278
|
let clientCallsScanned = 0;
|
|
56638
57279
|
for (const repo of repos) {
|
|
56639
|
-
if (!
|
|
57280
|
+
if (!fs31.existsSync(repo.repo_root)) {
|
|
56640
57281
|
logger.warn({ repo: repo.name, root: repo.repo_root }, "Subproject repo no longer exists, skipping");
|
|
56641
57282
|
continue;
|
|
56642
57283
|
}
|
|
@@ -56712,11 +57353,11 @@ var SubprojectManager = class {
|
|
|
56712
57353
|
const contracts = parseContracts(serviceRoot);
|
|
56713
57354
|
if (explicitPaths && repoRoot) {
|
|
56714
57355
|
for (const cp of explicitPaths) {
|
|
56715
|
-
const absContract =
|
|
56716
|
-
if (
|
|
56717
|
-
const additional = parseContracts(
|
|
57356
|
+
const absContract = path34.resolve(repoRoot, cp);
|
|
57357
|
+
if (fs31.existsSync(absContract)) {
|
|
57358
|
+
const additional = parseContracts(path34.dirname(absContract));
|
|
56718
57359
|
contracts.push(...additional.filter(
|
|
56719
|
-
(c) =>
|
|
57360
|
+
(c) => path34.resolve(repoRoot, c.specPath) === absContract
|
|
56720
57361
|
));
|
|
56721
57362
|
}
|
|
56722
57363
|
}
|
|
@@ -56817,7 +57458,7 @@ var SubprojectManager = class {
|
|
|
56817
57458
|
for (const [repoName, calls] of byRepo) {
|
|
56818
57459
|
const repo = this.topoStore.getSubproject(repoName);
|
|
56819
57460
|
for (const call of calls) {
|
|
56820
|
-
const symbols = repo?.db_path &&
|
|
57461
|
+
const symbols = repo?.db_path && fs31.existsSync(repo.db_path) ? resolveSymbolsAtLocation(repo.db_path, call.file_path, call.line) : [];
|
|
56821
57462
|
clients.push({
|
|
56822
57463
|
repo: repoName,
|
|
56823
57464
|
filePath: call.file_path,
|
|
@@ -57583,8 +58224,8 @@ function splitControllerRef(ref) {
|
|
|
57583
58224
|
}
|
|
57584
58225
|
|
|
57585
58226
|
// src/tools/framework/middleware-chain.ts
|
|
57586
|
-
import
|
|
57587
|
-
import
|
|
58227
|
+
import fs32 from "fs";
|
|
58228
|
+
import path35 from "path";
|
|
57588
58229
|
function getMiddlewareChain(store, rootPath, url2) {
|
|
57589
58230
|
const allRoutes = store.getAllRoutes();
|
|
57590
58231
|
const matchingRoute = allRoutes.find((r) => {
|
|
@@ -57633,7 +58274,7 @@ function detectFramework(allFiles) {
|
|
|
57633
58274
|
}
|
|
57634
58275
|
function readSource(rootPath, filePath) {
|
|
57635
58276
|
try {
|
|
57636
|
-
return
|
|
58277
|
+
return fs32.readFileSync(path35.resolve(rootPath, filePath), "utf-8");
|
|
57637
58278
|
} catch {
|
|
57638
58279
|
return void 0;
|
|
57639
58280
|
}
|
|
@@ -57791,12 +58432,12 @@ function buildDjangoChain(store, rootPath, allFiles, chain) {
|
|
|
57791
58432
|
}
|
|
57792
58433
|
|
|
57793
58434
|
// src/tools/analysis/module-graph.ts
|
|
57794
|
-
import
|
|
57795
|
-
import
|
|
58435
|
+
import fs34 from "fs";
|
|
58436
|
+
import path37 from "path";
|
|
57796
58437
|
|
|
57797
58438
|
// src/indexer/plugins/integration/framework/nestjs/index.ts
|
|
57798
|
-
import
|
|
57799
|
-
import
|
|
58439
|
+
import fs33 from "fs";
|
|
58440
|
+
import path36 from "path";
|
|
57800
58441
|
var MODULE_RE = /@Module\(\s*\{([^}]*(?:\{[^}]*\}[^}]*)*)\}\s*\)/s;
|
|
57801
58442
|
function extractModuleArray(body, prop) {
|
|
57802
58443
|
const re = new RegExp(`${escapeRegExp(prop)}\\s*:\\s*\\[([^\\]]*?)\\]`, "s");
|
|
@@ -57827,14 +58468,14 @@ function getModuleGraph(store, rootPath, moduleName) {
|
|
|
57827
58468
|
for (const file of moduleFiles) {
|
|
57828
58469
|
let source;
|
|
57829
58470
|
try {
|
|
57830
|
-
source =
|
|
58471
|
+
source = fs34.readFileSync(path37.resolve(rootPath, file.path), "utf-8");
|
|
57831
58472
|
} catch {
|
|
57832
58473
|
continue;
|
|
57833
58474
|
}
|
|
57834
58475
|
const info = extractModuleInfo(source);
|
|
57835
58476
|
if (!info) continue;
|
|
57836
58477
|
const classMatch = source.match(/export\s+class\s+(\w+)/);
|
|
57837
|
-
const name = classMatch?.[1] ??
|
|
58478
|
+
const name = classMatch?.[1] ?? path37.basename(file.path, path37.extname(file.path));
|
|
57838
58479
|
moduleMap.set(name, {
|
|
57839
58480
|
name,
|
|
57840
58481
|
file: file.path,
|
|
@@ -58915,7 +59556,7 @@ function findNovaSymbol(store, name) {
|
|
|
58915
59556
|
}
|
|
58916
59557
|
|
|
58917
59558
|
// src/tools/framework/tests.ts
|
|
58918
|
-
import
|
|
59559
|
+
import path38 from "path";
|
|
58919
59560
|
import { ok as ok8, err as err9 } from "neverthrow";
|
|
58920
59561
|
function getTestsFor(store, opts) {
|
|
58921
59562
|
let targetFile;
|
|
@@ -58969,14 +59610,14 @@ function getTestsFor(store, opts) {
|
|
|
58969
59610
|
}
|
|
58970
59611
|
}
|
|
58971
59612
|
if (targetFile) {
|
|
58972
|
-
const baseName =
|
|
59613
|
+
const baseName = path38.basename(targetFile, path38.extname(targetFile));
|
|
58973
59614
|
const normalized = baseName.replace(/([A-Z])/g, (m) => `-${m.toLowerCase()}`).replace(/^-/, "").toLowerCase();
|
|
58974
59615
|
const variants = [baseName.toLowerCase(), normalized];
|
|
58975
59616
|
const allFiles = store.getAllFiles();
|
|
58976
59617
|
for (const f of allFiles) {
|
|
58977
59618
|
if (seen.has(f.path)) continue;
|
|
58978
59619
|
if (!isTestFile(f.path)) continue;
|
|
58979
|
-
const testBase =
|
|
59620
|
+
const testBase = path38.basename(f.path).toLowerCase();
|
|
58980
59621
|
if (variants.some((v) => testBase.includes(v))) {
|
|
58981
59622
|
seen.add(f.path);
|
|
58982
59623
|
tests.push({ test_file: f.path, edge_type: "heuristic_path" });
|
|
@@ -60485,8 +61126,8 @@ import { z as z6 } from "zod";
|
|
|
60485
61126
|
|
|
60486
61127
|
// src/tools/refactoring/dead-code.ts
|
|
60487
61128
|
init_logger();
|
|
60488
|
-
import
|
|
60489
|
-
import
|
|
61129
|
+
import fs35 from "fs";
|
|
61130
|
+
import path39 from "path";
|
|
60490
61131
|
var DECORATOR_DRIVEN_FRAMEWORKS = /* @__PURE__ */ new Set([
|
|
60491
61132
|
"nestjs",
|
|
60492
61133
|
"laravel",
|
|
@@ -60521,7 +61162,7 @@ var BARREL_PATTERNS = [
|
|
|
60521
61162
|
/^main\.[jt]sx?$/
|
|
60522
61163
|
];
|
|
60523
61164
|
function isBarrelFile(filePath) {
|
|
60524
|
-
const base =
|
|
61165
|
+
const base = path39.basename(filePath);
|
|
60525
61166
|
return BARREL_PATTERNS.some((p) => p.test(base));
|
|
60526
61167
|
}
|
|
60527
61168
|
function buildImportedNamesSet(store) {
|
|
@@ -60721,12 +61362,12 @@ function readPackageEntries(projectRoot) {
|
|
|
60721
61362
|
const paths = /* @__PURE__ */ new Set();
|
|
60722
61363
|
const sources = {};
|
|
60723
61364
|
if (!projectRoot) return { paths, sources };
|
|
60724
|
-
const pkgPath =
|
|
60725
|
-
if (!
|
|
61365
|
+
const pkgPath = path39.join(projectRoot, "package.json");
|
|
61366
|
+
if (!fs35.existsSync(pkgPath)) return { paths, sources };
|
|
60726
61367
|
try {
|
|
60727
|
-
const pkg = JSON.parse(
|
|
61368
|
+
const pkg = JSON.parse(fs35.readFileSync(pkgPath, "utf-8"));
|
|
60728
61369
|
const add = (rel, src) => {
|
|
60729
|
-
const norm =
|
|
61370
|
+
const norm = path39.normalize(rel).replace(/\\/g, "/");
|
|
60730
61371
|
paths.add(norm);
|
|
60731
61372
|
sources[norm] = src;
|
|
60732
61373
|
};
|
|
@@ -60944,8 +61585,8 @@ function getDeadCodeReachability(store, options = {}) {
|
|
|
60944
61585
|
}
|
|
60945
61586
|
|
|
60946
61587
|
// src/tools/quality/security-scan.ts
|
|
60947
|
-
import { readFileSync as
|
|
60948
|
-
import
|
|
61588
|
+
import { readFileSync as readFileSync4 } from "fs";
|
|
61589
|
+
import path40 from "path";
|
|
60949
61590
|
var ALL_LANGUAGES = /* @__PURE__ */ new Set([
|
|
60950
61591
|
"typescript",
|
|
60951
61592
|
"javascript",
|
|
@@ -61227,10 +61868,10 @@ function scanSecurity(store, projectRoot, opts) {
|
|
|
61227
61868
|
const batch = files.slice(i, i + BATCH_SIZE);
|
|
61228
61869
|
for (const file of batch) {
|
|
61229
61870
|
if (/\.(?:test|spec)\.|__tests__|\/tests?\//i.test(file.path)) continue;
|
|
61230
|
-
const absPath =
|
|
61871
|
+
const absPath = path40.resolve(projectRoot, file.path);
|
|
61231
61872
|
let content;
|
|
61232
61873
|
try {
|
|
61233
|
-
const buf =
|
|
61874
|
+
const buf = readFileSync4(absPath);
|
|
61234
61875
|
if (buf.length > MAX_FILE_SIZE) continue;
|
|
61235
61876
|
content = buf.toString("utf-8");
|
|
61236
61877
|
} catch {
|
|
@@ -61925,8 +62566,8 @@ function detectAntipatterns(store, _projectRoot, opts = {}) {
|
|
|
61925
62566
|
}
|
|
61926
62567
|
|
|
61927
62568
|
// src/tools/quality/code-smells.ts
|
|
61928
|
-
import { readFileSync as
|
|
61929
|
-
import
|
|
62569
|
+
import { readFileSync as readFileSync5 } from "fs";
|
|
62570
|
+
import path41 from "path";
|
|
61930
62571
|
var ALL_CATEGORIES2 = [
|
|
61931
62572
|
"todo_comment",
|
|
61932
62573
|
"empty_function",
|
|
@@ -62181,10 +62822,10 @@ function scanCodeSmells(store, projectRoot, opts = {}) {
|
|
|
62181
62822
|
const batch = files.slice(i, i + BATCH_SIZE2);
|
|
62182
62823
|
for (const file of batch) {
|
|
62183
62824
|
if (!includeTests && /\.(?:test|spec)\.|__tests__|\/tests?\//i.test(file.path)) continue;
|
|
62184
|
-
const absPath =
|
|
62825
|
+
const absPath = path41.resolve(projectRoot, file.path);
|
|
62185
62826
|
let content;
|
|
62186
62827
|
try {
|
|
62187
|
-
const buf =
|
|
62828
|
+
const buf = readFileSync5(absPath);
|
|
62188
62829
|
if (buf.length > MAX_FILE_SIZE2) continue;
|
|
62189
62830
|
content = buf.toString("utf-8");
|
|
62190
62831
|
} catch {
|
|
@@ -62237,8 +62878,8 @@ function scanCodeSmells(store, projectRoot, opts = {}) {
|
|
|
62237
62878
|
}
|
|
62238
62879
|
|
|
62239
62880
|
// src/tools/quality/taint-analysis.ts
|
|
62240
|
-
import { readFileSync as
|
|
62241
|
-
import
|
|
62881
|
+
import { readFileSync as readFileSync6 } from "fs";
|
|
62882
|
+
import path42 from "path";
|
|
62242
62883
|
var JS_TS2 = /* @__PURE__ */ new Set(["typescript", "javascript"]);
|
|
62243
62884
|
var PY2 = /* @__PURE__ */ new Set(["python"]);
|
|
62244
62885
|
var PHP2 = /* @__PURE__ */ new Set(["php"]);
|
|
@@ -62594,10 +63235,10 @@ function interProceduralAnalysis(store, projectRoot, perFileResults, limit) {
|
|
|
62594
63235
|
for (const [filePath, fileData] of perFileResults) {
|
|
62595
63236
|
if (crossFileFlows.length >= limit) break;
|
|
62596
63237
|
if (fileData.sources.length === 0) continue;
|
|
62597
|
-
const absPath =
|
|
63238
|
+
const absPath = path42.join(projectRoot, filePath);
|
|
62598
63239
|
let content;
|
|
62599
63240
|
try {
|
|
62600
|
-
content =
|
|
63241
|
+
content = readFileSync6(absPath, "utf-8");
|
|
62601
63242
|
} catch {
|
|
62602
63243
|
continue;
|
|
62603
63244
|
}
|
|
@@ -62616,10 +63257,10 @@ function interProceduralAnalysis(store, projectRoot, perFileResults, limit) {
|
|
|
62616
63257
|
).all(call.funcName, filePath);
|
|
62617
63258
|
for (const sym of symbols) {
|
|
62618
63259
|
if (crossFileFlows.length >= limit) break;
|
|
62619
|
-
const targetPath =
|
|
63260
|
+
const targetPath = path42.join(projectRoot, sym.file_path);
|
|
62620
63261
|
let targetContent;
|
|
62621
63262
|
try {
|
|
62622
|
-
targetContent =
|
|
63263
|
+
targetContent = readFileSync6(targetPath, "utf-8");
|
|
62623
63264
|
} catch {
|
|
62624
63265
|
continue;
|
|
62625
63266
|
}
|
|
@@ -62677,10 +63318,10 @@ function taintAnalysis(store, projectRoot, opts = {}) {
|
|
|
62677
63318
|
const perFileData = /* @__PURE__ */ new Map();
|
|
62678
63319
|
for (const file of sourceFiles) {
|
|
62679
63320
|
if (allFlows.length >= limit) break;
|
|
62680
|
-
const absPath =
|
|
63321
|
+
const absPath = path42.join(projectRoot, file.path);
|
|
62681
63322
|
let content;
|
|
62682
63323
|
try {
|
|
62683
|
-
content =
|
|
63324
|
+
content = readFileSync6(absPath, "utf-8");
|
|
62684
63325
|
} catch {
|
|
62685
63326
|
continue;
|
|
62686
63327
|
}
|
|
@@ -62762,8 +63403,8 @@ function taintAnalysis(store, projectRoot, opts = {}) {
|
|
|
62762
63403
|
}
|
|
62763
63404
|
|
|
62764
63405
|
// src/tools/project/sbom.ts
|
|
62765
|
-
import { readFileSync as
|
|
62766
|
-
import
|
|
63406
|
+
import { readFileSync as readFileSync7, existsSync as existsSync3 } from "fs";
|
|
63407
|
+
import path43 from "path";
|
|
62767
63408
|
var COPYLEFT_LICENSES = /* @__PURE__ */ new Set([
|
|
62768
63409
|
"GPL-2.0",
|
|
62769
63410
|
"GPL-2.0-only",
|
|
@@ -62798,21 +63439,21 @@ function checkLicenseWarning(name, version2, license) {
|
|
|
62798
63439
|
}
|
|
62799
63440
|
function readJson(filePath) {
|
|
62800
63441
|
try {
|
|
62801
|
-
return JSON.parse(
|
|
63442
|
+
return JSON.parse(readFileSync7(filePath, "utf-8"));
|
|
62802
63443
|
} catch {
|
|
62803
63444
|
return null;
|
|
62804
63445
|
}
|
|
62805
63446
|
}
|
|
62806
63447
|
function readLines(filePath) {
|
|
62807
63448
|
try {
|
|
62808
|
-
return
|
|
63449
|
+
return readFileSync7(filePath, "utf-8").split("\n");
|
|
62809
63450
|
} catch {
|
|
62810
63451
|
return [];
|
|
62811
63452
|
}
|
|
62812
63453
|
}
|
|
62813
63454
|
function parseNpm(root, includeDev, includeTransitive) {
|
|
62814
|
-
const pkgPath =
|
|
62815
|
-
const lockPath =
|
|
63455
|
+
const pkgPath = path43.join(root, "package.json");
|
|
63456
|
+
const lockPath = path43.join(root, "package-lock.json");
|
|
62816
63457
|
const pkg = readJson(pkgPath);
|
|
62817
63458
|
if (!pkg) return [];
|
|
62818
63459
|
const deps = pkg.dependencies ?? {};
|
|
@@ -62852,8 +63493,8 @@ function parseNpm(root, includeDev, includeTransitive) {
|
|
|
62852
63493
|
return components;
|
|
62853
63494
|
}
|
|
62854
63495
|
function parseComposer(root, includeDev, includeTransitive) {
|
|
62855
|
-
const lockPath =
|
|
62856
|
-
const manifestPath =
|
|
63496
|
+
const lockPath = path43.join(root, "composer.lock");
|
|
63497
|
+
const manifestPath = path43.join(root, "composer.json");
|
|
62857
63498
|
const manifest = readJson(manifestPath);
|
|
62858
63499
|
const directNames = /* @__PURE__ */ new Set();
|
|
62859
63500
|
if (manifest) {
|
|
@@ -62896,8 +63537,8 @@ function parseComposer(root, includeDev, includeTransitive) {
|
|
|
62896
63537
|
}
|
|
62897
63538
|
function parsePip(root, includeDev, includeTransitive) {
|
|
62898
63539
|
const components = [];
|
|
62899
|
-
const reqPath =
|
|
62900
|
-
if (
|
|
63540
|
+
const reqPath = path43.join(root, "requirements.txt");
|
|
63541
|
+
if (existsSync3(reqPath)) {
|
|
62901
63542
|
for (const line of readLines(reqPath)) {
|
|
62902
63543
|
const trimmed = line.trim();
|
|
62903
63544
|
if (!trimmed || trimmed.startsWith("#") || trimmed.startsWith("-")) continue;
|
|
@@ -62912,9 +63553,9 @@ function parsePip(root, includeDev, includeTransitive) {
|
|
|
62912
63553
|
}
|
|
62913
63554
|
}
|
|
62914
63555
|
}
|
|
62915
|
-
const poetryLock =
|
|
62916
|
-
if (
|
|
62917
|
-
const content =
|
|
63556
|
+
const poetryLock = path43.join(root, "poetry.lock");
|
|
63557
|
+
if (existsSync3(poetryLock) && includeTransitive) {
|
|
63558
|
+
const content = readFileSync7(poetryLock, "utf-8");
|
|
62918
63559
|
const directNames = new Set(components.map((c) => c.name.toLowerCase()));
|
|
62919
63560
|
let currentName = "";
|
|
62920
63561
|
let currentVersion = "";
|
|
@@ -62943,8 +63584,8 @@ function parsePip(root, includeDev, includeTransitive) {
|
|
|
62943
63584
|
return components;
|
|
62944
63585
|
}
|
|
62945
63586
|
function parseGo(root, _includeDev, includeTransitive) {
|
|
62946
|
-
const modPath =
|
|
62947
|
-
if (!
|
|
63587
|
+
const modPath = path43.join(root, "go.mod");
|
|
63588
|
+
if (!existsSync3(modPath)) return [];
|
|
62948
63589
|
const components = [];
|
|
62949
63590
|
const directNames = /* @__PURE__ */ new Set();
|
|
62950
63591
|
let inRequire = false;
|
|
@@ -62976,10 +63617,10 @@ function parseGo(root, _includeDev, includeTransitive) {
|
|
|
62976
63617
|
return components;
|
|
62977
63618
|
}
|
|
62978
63619
|
function parseCargo(root, _includeDev, includeTransitive) {
|
|
62979
|
-
const lockPath =
|
|
62980
|
-
if (!
|
|
62981
|
-
const tomlPath =
|
|
62982
|
-
if (!
|
|
63620
|
+
const lockPath = path43.join(root, "Cargo.lock");
|
|
63621
|
+
if (!existsSync3(lockPath)) {
|
|
63622
|
+
const tomlPath = path43.join(root, "Cargo.toml");
|
|
63623
|
+
if (!existsSync3(tomlPath)) return [];
|
|
62983
63624
|
const components2 = [];
|
|
62984
63625
|
let inDeps = false;
|
|
62985
63626
|
for (const line of readLines(tomlPath)) {
|
|
@@ -63043,8 +63684,8 @@ function parseCargo(root, _includeDev, includeTransitive) {
|
|
|
63043
63684
|
});
|
|
63044
63685
|
}
|
|
63045
63686
|
if (!includeTransitive) {
|
|
63046
|
-
const tomlPath =
|
|
63047
|
-
if (
|
|
63687
|
+
const tomlPath = path43.join(root, "Cargo.toml");
|
|
63688
|
+
if (existsSync3(tomlPath)) {
|
|
63048
63689
|
const directNames = /* @__PURE__ */ new Set();
|
|
63049
63690
|
let inDeps = false;
|
|
63050
63691
|
for (const line of readLines(tomlPath)) {
|
|
@@ -63068,8 +63709,8 @@ function parseCargo(root, _includeDev, includeTransitive) {
|
|
|
63068
63709
|
return components;
|
|
63069
63710
|
}
|
|
63070
63711
|
function parseBundler(root, _includeDev, includeTransitive) {
|
|
63071
|
-
const lockPath =
|
|
63072
|
-
if (!
|
|
63712
|
+
const lockPath = path43.join(root, "Gemfile.lock");
|
|
63713
|
+
if (!existsSync3(lockPath)) return [];
|
|
63073
63714
|
const components = [];
|
|
63074
63715
|
let inSpecs = false;
|
|
63075
63716
|
for (const line of readLines(lockPath)) {
|
|
@@ -63107,9 +63748,9 @@ function parseBundler(root, _includeDev, includeTransitive) {
|
|
|
63107
63748
|
return components;
|
|
63108
63749
|
}
|
|
63109
63750
|
function parseMaven(root, _includeDev, _includeTransitive) {
|
|
63110
|
-
const pomPath =
|
|
63111
|
-
if (!
|
|
63112
|
-
const content =
|
|
63751
|
+
const pomPath = path43.join(root, "pom.xml");
|
|
63752
|
+
if (!existsSync3(pomPath)) return [];
|
|
63753
|
+
const content = readFileSync7(pomPath, "utf-8");
|
|
63113
63754
|
const components = [];
|
|
63114
63755
|
const depRegex = /<dependency>\s*<groupId>([^<]+)<\/groupId>\s*<artifactId>([^<]+)<\/artifactId>\s*(?:<version>([^<]+)<\/version>)?/gs;
|
|
63115
63756
|
let match;
|
|
@@ -63946,13 +64587,13 @@ function registerGitTools(server, ctx) {
|
|
|
63946
64587
|
import { z as z7 } from "zod";
|
|
63947
64588
|
|
|
63948
64589
|
// src/tools/refactoring/refactor.ts
|
|
63949
|
-
import
|
|
63950
|
-
import
|
|
64590
|
+
import fs38 from "fs";
|
|
64591
|
+
import path46 from "path";
|
|
63951
64592
|
import fg5 from "fast-glob";
|
|
63952
64593
|
|
|
63953
64594
|
// src/tools/refactoring/shared.ts
|
|
63954
|
-
import
|
|
63955
|
-
import
|
|
64595
|
+
import fs36 from "fs";
|
|
64596
|
+
import path44 from "path";
|
|
63956
64597
|
var BINARY_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
63957
64598
|
".png",
|
|
63958
64599
|
".jpg",
|
|
@@ -63995,10 +64636,10 @@ var BINARY_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
|
63995
64636
|
]);
|
|
63996
64637
|
var SKIP_DIRS3 = ["node_modules", ".git", "dist", "build", "vendor", "__pycache__", ".next", ".nuxt"];
|
|
63997
64638
|
function readLines2(filePath) {
|
|
63998
|
-
return
|
|
64639
|
+
return fs36.readFileSync(filePath, "utf-8").split("\n");
|
|
63999
64640
|
}
|
|
64000
64641
|
function writeLines(filePath, lines) {
|
|
64001
|
-
|
|
64642
|
+
fs36.writeFileSync(filePath, lines.join("\n"), "utf-8");
|
|
64002
64643
|
}
|
|
64003
64644
|
function buildRenameRegex(name) {
|
|
64004
64645
|
const escaped = name.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
@@ -64024,7 +64665,7 @@ function getImportingFiles(store, fileId, projectRoot) {
|
|
|
64024
64665
|
seen.add(importFileId);
|
|
64025
64666
|
const file = store.getFileById(importFileId);
|
|
64026
64667
|
if (file) {
|
|
64027
|
-
importingFiles.push({ filePath:
|
|
64668
|
+
importingFiles.push({ filePath: path44.resolve(projectRoot, file.path), fileId: importFileId });
|
|
64028
64669
|
}
|
|
64029
64670
|
}
|
|
64030
64671
|
}
|
|
@@ -64216,8 +64857,8 @@ function getIndent(line) {
|
|
|
64216
64857
|
}
|
|
64217
64858
|
|
|
64218
64859
|
// src/tools/refactoring/non-code-scanner.ts
|
|
64219
|
-
import
|
|
64220
|
-
import
|
|
64860
|
+
import fs37 from "fs";
|
|
64861
|
+
import path45 from "path";
|
|
64221
64862
|
import fg4 from "fast-glob";
|
|
64222
64863
|
var NON_CODE_PATTERNS = [
|
|
64223
64864
|
"**/*.yaml",
|
|
@@ -64260,14 +64901,14 @@ function scanNonCodeFiles(projectRoot, oldName, newName) {
|
|
|
64260
64901
|
} catch {
|
|
64261
64902
|
return mentions;
|
|
64262
64903
|
}
|
|
64263
|
-
files = files.filter((f) => !SKIP_FILES.has(
|
|
64904
|
+
files = files.filter((f) => !SKIP_FILES.has(path45.basename(f)));
|
|
64264
64905
|
for (const relPath of files) {
|
|
64265
|
-
const absPath =
|
|
64906
|
+
const absPath = path45.resolve(projectRoot, relPath);
|
|
64266
64907
|
let content;
|
|
64267
64908
|
try {
|
|
64268
|
-
const stat =
|
|
64909
|
+
const stat = fs37.statSync(absPath);
|
|
64269
64910
|
if (stat.size > 1e6) continue;
|
|
64270
|
-
content =
|
|
64911
|
+
content = fs37.readFileSync(absPath, "utf-8");
|
|
64271
64912
|
} catch {
|
|
64272
64913
|
continue;
|
|
64273
64914
|
}
|
|
@@ -64322,7 +64963,7 @@ function applyRename(store, projectRoot, symbolId, newName, dryRun = false) {
|
|
|
64322
64963
|
result.error = `File not found for symbol ${symbolId}`;
|
|
64323
64964
|
return result;
|
|
64324
64965
|
}
|
|
64325
|
-
const definitionFilePath =
|
|
64966
|
+
const definitionFilePath = path46.resolve(projectRoot, symbolFile.path);
|
|
64326
64967
|
const importingFiles = getImportingFiles(store, symbol.file_id, projectRoot);
|
|
64327
64968
|
const allFiles = [
|
|
64328
64969
|
{ filePath: definitionFilePath, fileId: symbol.file_id },
|
|
@@ -64331,7 +64972,7 @@ function applyRename(store, projectRoot, symbolId, newName, dryRun = false) {
|
|
|
64331
64972
|
const regex = buildRenameRegex(oldName);
|
|
64332
64973
|
const modifiedFiles = /* @__PURE__ */ new Set();
|
|
64333
64974
|
for (const { filePath } of allFiles) {
|
|
64334
|
-
if (!
|
|
64975
|
+
if (!fs38.existsSync(filePath)) {
|
|
64335
64976
|
result.warnings.push(`File not found on disk: ${filePath}`);
|
|
64336
64977
|
continue;
|
|
64337
64978
|
}
|
|
@@ -64344,7 +64985,7 @@ function applyRename(store, projectRoot, symbolId, newName, dryRun = false) {
|
|
|
64344
64985
|
regex.lastIndex = 0;
|
|
64345
64986
|
if (newLine !== line) {
|
|
64346
64987
|
result.edits.push({
|
|
64347
|
-
file:
|
|
64988
|
+
file: path46.relative(projectRoot, filePath),
|
|
64348
64989
|
original_line: i + 1,
|
|
64349
64990
|
original_text: line.trimStart(),
|
|
64350
64991
|
new_text: newLine.trimStart()
|
|
@@ -64359,7 +65000,7 @@ function applyRename(store, projectRoot, symbolId, newName, dryRun = false) {
|
|
|
64359
65000
|
if (!dryRun) {
|
|
64360
65001
|
writeLines(filePath, lines);
|
|
64361
65002
|
}
|
|
64362
|
-
modifiedFiles.add(
|
|
65003
|
+
modifiedFiles.add(path46.relative(projectRoot, filePath));
|
|
64363
65004
|
}
|
|
64364
65005
|
}
|
|
64365
65006
|
result.success = true;
|
|
@@ -64420,8 +65061,8 @@ function removeDeadCode(store, projectRoot, symbolId, dryRun = false) {
|
|
|
64420
65061
|
result.error = `Symbol "${symbol.name}" has no line range \u2014 cannot remove`;
|
|
64421
65062
|
return result;
|
|
64422
65063
|
}
|
|
64423
|
-
const filePath =
|
|
64424
|
-
if (!
|
|
65064
|
+
const filePath = path46.resolve(projectRoot, symbolFile.path);
|
|
65065
|
+
if (!fs38.existsSync(filePath)) {
|
|
64425
65066
|
result.error = `File not found on disk: ${filePath}`;
|
|
64426
65067
|
return result;
|
|
64427
65068
|
}
|
|
@@ -64473,7 +65114,7 @@ function removeDeadCode(store, projectRoot, symbolId, dryRun = false) {
|
|
|
64473
65114
|
const importers = getImportingFiles(store, symbol.file_id, projectRoot);
|
|
64474
65115
|
if (importers.length > 0) {
|
|
64475
65116
|
result.warnings.push(
|
|
64476
|
-
`Removed the last exported symbol from ${symbolFile.path}. ${importers.length} file(s) still import from it \u2014 review for unused imports: ` + importers.map((f) =>
|
|
65117
|
+
`Removed the last exported symbol from ${symbolFile.path}. ${importers.length} file(s) still import from it \u2014 review for unused imports: ` + importers.map((f) => path46.relative(projectRoot, f.filePath)).join(", ")
|
|
64477
65118
|
);
|
|
64478
65119
|
}
|
|
64479
65120
|
}
|
|
@@ -64489,8 +65130,8 @@ function extractFunction(store, projectRoot, filePath, startLine, endLine, funct
|
|
|
64489
65130
|
files_modified: [],
|
|
64490
65131
|
warnings: []
|
|
64491
65132
|
};
|
|
64492
|
-
const absPath =
|
|
64493
|
-
if (!
|
|
65133
|
+
const absPath = path46.resolve(projectRoot, filePath);
|
|
65134
|
+
if (!fs38.existsSync(absPath)) {
|
|
64494
65135
|
result.error = `File not found: ${filePath}`;
|
|
64495
65136
|
return result;
|
|
64496
65137
|
}
|
|
@@ -64499,7 +65140,7 @@ function extractFunction(store, projectRoot, filePath, startLine, endLine, funct
|
|
|
64499
65140
|
result.error = `Invalid line range ${startLine}-${endLine} (file has ${lines.length} lines)`;
|
|
64500
65141
|
return result;
|
|
64501
65142
|
}
|
|
64502
|
-
const ext =
|
|
65143
|
+
const ext = path46.extname(filePath).toLowerCase();
|
|
64503
65144
|
const lang = detectLanguage2(ext);
|
|
64504
65145
|
const extractedLines = lines.slice(startLine - 1, endLine);
|
|
64505
65146
|
const extractedText = extractedLines.join("\n");
|
|
@@ -64637,7 +65278,7 @@ function applyCodemod(projectRoot, pattern, replacement, filePattern, options) {
|
|
|
64637
65278
|
result.error = `Invalid file pattern: ${e.message}`;
|
|
64638
65279
|
return result;
|
|
64639
65280
|
}
|
|
64640
|
-
files = files.filter((f) => !BINARY_EXTENSIONS.has(
|
|
65281
|
+
files = files.filter((f) => !BINARY_EXTENSIONS.has(path46.extname(f).toLowerCase()));
|
|
64641
65282
|
if (files.length === 0) {
|
|
64642
65283
|
result.error = `No files matched pattern: ${filePattern}`;
|
|
64643
65284
|
return result;
|
|
@@ -64645,11 +65286,11 @@ function applyCodemod(projectRoot, pattern, replacement, filePattern, options) {
|
|
|
64645
65286
|
const allMatches = [];
|
|
64646
65287
|
const filesWithMatches = /* @__PURE__ */ new Set();
|
|
64647
65288
|
for (const relPath of files) {
|
|
64648
|
-
const absPath =
|
|
64649
|
-
if (!
|
|
65289
|
+
const absPath = path46.resolve(projectRoot, relPath);
|
|
65290
|
+
if (!fs38.existsSync(absPath)) continue;
|
|
64650
65291
|
let content;
|
|
64651
65292
|
try {
|
|
64652
|
-
content =
|
|
65293
|
+
content = fs38.readFileSync(absPath, "utf-8");
|
|
64653
65294
|
} catch {
|
|
64654
65295
|
result.warnings.push(`Could not read: ${relPath}`);
|
|
64655
65296
|
continue;
|
|
@@ -64731,14 +65372,14 @@ function applyCodemod(projectRoot, pattern, replacement, filePattern, options) {
|
|
|
64731
65372
|
return result;
|
|
64732
65373
|
}
|
|
64733
65374
|
for (const relPath of filesWithMatches) {
|
|
64734
|
-
const absPath =
|
|
65375
|
+
const absPath = path46.resolve(projectRoot, relPath);
|
|
64735
65376
|
try {
|
|
64736
|
-
const content =
|
|
65377
|
+
const content = fs38.readFileSync(absPath, "utf-8");
|
|
64737
65378
|
const flags = options.multiline ? "gms" : "gm";
|
|
64738
65379
|
const freshRegex = new RegExp(pattern, flags);
|
|
64739
65380
|
const newContent = content.replace(freshRegex, replacement);
|
|
64740
65381
|
if (newContent !== content) {
|
|
64741
|
-
|
|
65382
|
+
fs38.writeFileSync(absPath, newContent, "utf-8");
|
|
64742
65383
|
result.files_modified.push(relPath);
|
|
64743
65384
|
}
|
|
64744
65385
|
} catch (e) {
|
|
@@ -64751,12 +65392,12 @@ function applyCodemod(projectRoot, pattern, replacement, filePattern, options) {
|
|
|
64751
65392
|
}
|
|
64752
65393
|
|
|
64753
65394
|
// src/tools/refactoring/move.ts
|
|
64754
|
-
import
|
|
64755
|
-
import
|
|
65395
|
+
import fs40 from "fs";
|
|
65396
|
+
import path48 from "path";
|
|
64756
65397
|
|
|
64757
65398
|
// src/tools/refactoring/import-rewriter.ts
|
|
64758
|
-
import
|
|
64759
|
-
import
|
|
65399
|
+
import fs39 from "fs";
|
|
65400
|
+
import path47 from "path";
|
|
64760
65401
|
var STRIP_EXTENSIONS = /* @__PURE__ */ new Set([".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs", ".mts", ".cts"]);
|
|
64761
65402
|
var IMPORT_PATTERNS = [
|
|
64762
65403
|
// import ... from 'specifier'
|
|
@@ -64776,8 +65417,8 @@ function computeNewImportSpecifier(importingFilePath, oldSpecifier, newTargetAbs
|
|
|
64776
65417
|
const oldSuffix = oldSpecifier.slice(aliasPrefix.length);
|
|
64777
65418
|
const resolved = resolver.resolve(aliasPrefix, importingFilePath);
|
|
64778
65419
|
if (resolved) {
|
|
64779
|
-
const aliasRoot =
|
|
64780
|
-
const newRelToAlias =
|
|
65420
|
+
const aliasRoot = path47.dirname(resolved);
|
|
65421
|
+
const newRelToAlias = path47.relative(aliasRoot, newTargetAbsPath);
|
|
64781
65422
|
if (!newRelToAlias.startsWith("..")) {
|
|
64782
65423
|
const newSpecifier = aliasPrefix + "/" + stripExtension(newRelToAlias);
|
|
64783
65424
|
const check = resolver.resolve(newSpecifier, importingFilePath);
|
|
@@ -64791,8 +65432,8 @@ function computeNewImportSpecifier(importingFilePath, oldSpecifier, newTargetAbs
|
|
|
64791
65432
|
return computeRelativeSpecifier(importingFilePath, newTargetAbsPath);
|
|
64792
65433
|
}
|
|
64793
65434
|
function computeRelativeSpecifier(fromFile, toFile) {
|
|
64794
|
-
const fromDir =
|
|
64795
|
-
let rel =
|
|
65435
|
+
const fromDir = path47.dirname(fromFile);
|
|
65436
|
+
let rel = path47.relative(fromDir, toFile);
|
|
64796
65437
|
rel = stripExtension(rel);
|
|
64797
65438
|
if (rel.endsWith("/index") || rel === "index") {
|
|
64798
65439
|
rel = rel === "index" ? "." : rel.slice(0, -6);
|
|
@@ -64803,22 +65444,22 @@ function computeRelativeSpecifier(fromFile, toFile) {
|
|
|
64803
65444
|
return rel.replace(/\\/g, "/");
|
|
64804
65445
|
}
|
|
64805
65446
|
function stripExtension(filePath) {
|
|
64806
|
-
const ext =
|
|
65447
|
+
const ext = path47.extname(filePath);
|
|
64807
65448
|
if (STRIP_EXTENSIONS.has(ext)) {
|
|
64808
65449
|
return filePath.slice(0, -ext.length);
|
|
64809
65450
|
}
|
|
64810
65451
|
return filePath;
|
|
64811
65452
|
}
|
|
64812
65453
|
function normalizePath(p) {
|
|
64813
|
-
return
|
|
65454
|
+
return path47.resolve(p).replace(/\\/g, "/");
|
|
64814
65455
|
}
|
|
64815
65456
|
function rewriteImportSpecifiers(filePath, projectRoot, oldSpecifier, newSpecifier, dryRun) {
|
|
64816
65457
|
const edits = [];
|
|
64817
|
-
if (!
|
|
65458
|
+
if (!fs39.existsSync(filePath)) {
|
|
64818
65459
|
return { edits, lines: [] };
|
|
64819
65460
|
}
|
|
64820
65461
|
const lines = readLines2(filePath);
|
|
64821
|
-
const relPath =
|
|
65462
|
+
const relPath = path47.relative(projectRoot, filePath);
|
|
64822
65463
|
let modified = false;
|
|
64823
65464
|
for (let i = 0; i < lines.length; i++) {
|
|
64824
65465
|
const line = lines[i];
|
|
@@ -64850,7 +65491,7 @@ function rewriteImportSpecifiers(filePath, projectRoot, oldSpecifier, newSpecifi
|
|
|
64850
65491
|
return { edits, lines };
|
|
64851
65492
|
}
|
|
64852
65493
|
function findImportSpecifier(sourceFilePath, targetAbsPath, projectRoot, resolver) {
|
|
64853
|
-
if (!
|
|
65494
|
+
if (!fs39.existsSync(sourceFilePath)) return void 0;
|
|
64854
65495
|
const lines = readLines2(sourceFilePath);
|
|
64855
65496
|
const fullText = lines.join("\n");
|
|
64856
65497
|
for (const pattern of IMPORT_PATTERNS) {
|
|
@@ -64864,11 +65505,11 @@ function findImportSpecifier(sourceFilePath, targetAbsPath, projectRoot, resolve
|
|
|
64864
65505
|
resolvedPath = resolver.resolve(specifier, sourceFilePath);
|
|
64865
65506
|
}
|
|
64866
65507
|
if (!resolvedPath && (specifier.startsWith(".") || specifier.startsWith("/"))) {
|
|
64867
|
-
const fromDir =
|
|
64868
|
-
const candidate =
|
|
65508
|
+
const fromDir = path47.dirname(sourceFilePath);
|
|
65509
|
+
const candidate = path47.resolve(fromDir, specifier);
|
|
64869
65510
|
for (const ext of ["", ".ts", ".tsx", ".js", ".jsx", "/index.ts", "/index.js"]) {
|
|
64870
65511
|
const full2 = candidate + ext;
|
|
64871
|
-
if (
|
|
65512
|
+
if (fs39.existsSync(full2)) {
|
|
64872
65513
|
resolvedPath = full2;
|
|
64873
65514
|
break;
|
|
64874
65515
|
}
|
|
@@ -64932,13 +65573,13 @@ function moveSymbol(store, projectRoot, params, resolver) {
|
|
|
64932
65573
|
result.error = `Source file not found for symbol ${params.symbol_id}`;
|
|
64933
65574
|
return result;
|
|
64934
65575
|
}
|
|
64935
|
-
const sourceAbsPath =
|
|
64936
|
-
const targetAbsPath =
|
|
64937
|
-
if (!
|
|
65576
|
+
const sourceAbsPath = path48.resolve(projectRoot, sourceFile.path);
|
|
65577
|
+
const targetAbsPath = path48.resolve(projectRoot, params.target_file);
|
|
65578
|
+
if (!fs40.existsSync(sourceAbsPath)) {
|
|
64938
65579
|
result.error = `Source file not found on disk: ${sourceFile.path}`;
|
|
64939
65580
|
return result;
|
|
64940
65581
|
}
|
|
64941
|
-
if (
|
|
65582
|
+
if (fs40.existsSync(targetAbsPath)) {
|
|
64942
65583
|
const targetFile = store.getFile(params.target_file);
|
|
64943
65584
|
if (targetFile) {
|
|
64944
65585
|
const targetSymbols = store.getSymbolsByFile(targetFile.id);
|
|
@@ -64965,7 +65606,7 @@ function moveSymbol(store, projectRoot, params, resolver) {
|
|
|
64965
65606
|
const meta = symbol.metadata ? typeof symbol.metadata === "string" ? JSON.parse(symbol.metadata) : symbol.metadata : {};
|
|
64966
65607
|
const isExported = !!meta?.exported;
|
|
64967
65608
|
let targetLines;
|
|
64968
|
-
const targetExists =
|
|
65609
|
+
const targetExists = fs40.existsSync(targetAbsPath);
|
|
64969
65610
|
if (targetExists) {
|
|
64970
65611
|
targetLines = readLines2(targetAbsPath);
|
|
64971
65612
|
} else {
|
|
@@ -65011,7 +65652,7 @@ function moveSymbol(store, projectRoot, params, resolver) {
|
|
|
65011
65652
|
if (isExported) {
|
|
65012
65653
|
const importingFiles = getImportingFiles(store, symbol.file_id, projectRoot);
|
|
65013
65654
|
for (const { filePath: importerAbsPath } of importingFiles) {
|
|
65014
|
-
if (!
|
|
65655
|
+
if (!fs40.existsSync(importerAbsPath)) continue;
|
|
65015
65656
|
const importerLines = readLines2(importerAbsPath);
|
|
65016
65657
|
const importerContent = importerLines.join("\n");
|
|
65017
65658
|
const nameRegex = new RegExp(`\\b${escapeRegex3(symbol.name)}\\b`);
|
|
@@ -65027,7 +65668,7 @@ function moveSymbol(store, projectRoot, params, resolver) {
|
|
|
65027
65668
|
);
|
|
65028
65669
|
result.edits.push(...importEdits);
|
|
65029
65670
|
if (importEdits.length > 0) {
|
|
65030
|
-
result.files_modified.push(
|
|
65671
|
+
result.files_modified.push(path48.relative(projectRoot, importerAbsPath));
|
|
65031
65672
|
}
|
|
65032
65673
|
}
|
|
65033
65674
|
const remainingExports = fileSymbols.filter((s) => {
|
|
@@ -65055,9 +65696,9 @@ function moveSymbol(store, projectRoot, params, resolver) {
|
|
|
65055
65696
|
tLines.splice(insertIdx, 0, ...insertLines);
|
|
65056
65697
|
writeLines(targetAbsPath, tLines);
|
|
65057
65698
|
} else {
|
|
65058
|
-
const targetDir =
|
|
65059
|
-
if (!
|
|
65060
|
-
|
|
65699
|
+
const targetDir = path48.dirname(targetAbsPath);
|
|
65700
|
+
if (!fs40.existsSync(targetDir)) {
|
|
65701
|
+
fs40.mkdirSync(targetDir, { recursive: true });
|
|
65061
65702
|
}
|
|
65062
65703
|
writeLines(targetAbsPath, insertLines);
|
|
65063
65704
|
}
|
|
@@ -65077,13 +65718,13 @@ function moveFile(store, projectRoot, params, resolver) {
|
|
|
65077
65718
|
files_modified: [],
|
|
65078
65719
|
warnings: []
|
|
65079
65720
|
};
|
|
65080
|
-
const sourceAbsPath =
|
|
65081
|
-
const targetAbsPath =
|
|
65082
|
-
if (!
|
|
65721
|
+
const sourceAbsPath = path48.resolve(projectRoot, params.source_file);
|
|
65722
|
+
const targetAbsPath = path48.resolve(projectRoot, params.new_path);
|
|
65723
|
+
if (!fs40.existsSync(sourceAbsPath)) {
|
|
65083
65724
|
result.error = `Source file not found: ${params.source_file}`;
|
|
65084
65725
|
return result;
|
|
65085
65726
|
}
|
|
65086
|
-
if (
|
|
65727
|
+
if (fs40.existsSync(targetAbsPath)) {
|
|
65087
65728
|
result.error = `Target path already exists: ${params.new_path}`;
|
|
65088
65729
|
return result;
|
|
65089
65730
|
}
|
|
@@ -65094,7 +65735,7 @@ function moveFile(store, projectRoot, params, resolver) {
|
|
|
65094
65735
|
}
|
|
65095
65736
|
const importingFiles = getImportingFiles(store, fileRow.id, projectRoot);
|
|
65096
65737
|
for (const { filePath: importerAbsPath } of importingFiles) {
|
|
65097
|
-
if (!
|
|
65738
|
+
if (!fs40.existsSync(importerAbsPath)) continue;
|
|
65098
65739
|
const edits = rewriteImportForMovedTarget(
|
|
65099
65740
|
importerAbsPath,
|
|
65100
65741
|
sourceAbsPath,
|
|
@@ -65105,7 +65746,7 @@ function moveFile(store, projectRoot, params, resolver) {
|
|
|
65105
65746
|
);
|
|
65106
65747
|
result.edits.push(...edits);
|
|
65107
65748
|
if (edits.length > 0) {
|
|
65108
|
-
result.files_modified.push(
|
|
65749
|
+
result.files_modified.push(path48.relative(projectRoot, importerAbsPath));
|
|
65109
65750
|
}
|
|
65110
65751
|
}
|
|
65111
65752
|
const selfEdits = rewriteOwnImports(
|
|
@@ -65124,14 +65765,14 @@ function moveFile(store, projectRoot, params, resolver) {
|
|
|
65124
65765
|
new_text: `(moved to ${params.new_path})`
|
|
65125
65766
|
});
|
|
65126
65767
|
if (!dryRun) {
|
|
65127
|
-
const targetDir =
|
|
65128
|
-
if (!
|
|
65129
|
-
|
|
65768
|
+
const targetDir = path48.dirname(targetAbsPath);
|
|
65769
|
+
if (!fs40.existsSync(targetDir)) {
|
|
65770
|
+
fs40.mkdirSync(targetDir, { recursive: true });
|
|
65130
65771
|
}
|
|
65131
65772
|
if (selfEdits.length > 0) {
|
|
65132
|
-
|
|
65773
|
+
fs40.renameSync(sourceAbsPath, targetAbsPath);
|
|
65133
65774
|
} else {
|
|
65134
|
-
|
|
65775
|
+
fs40.renameSync(sourceAbsPath, targetAbsPath);
|
|
65135
65776
|
}
|
|
65136
65777
|
}
|
|
65137
65778
|
result.files_modified.push(params.source_file, params.new_path);
|
|
@@ -65141,9 +65782,9 @@ function moveFile(store, projectRoot, params, resolver) {
|
|
|
65141
65782
|
function rewriteOwnImports(currentAbsPath, newAbsPath, projectRoot, store, dryRun, resolver) {
|
|
65142
65783
|
const lines = readLines2(currentAbsPath);
|
|
65143
65784
|
const edits = [];
|
|
65144
|
-
const relPath =
|
|
65145
|
-
const currentDir =
|
|
65146
|
-
const newDir =
|
|
65785
|
+
const relPath = path48.relative(projectRoot, currentAbsPath);
|
|
65786
|
+
const currentDir = path48.dirname(currentAbsPath);
|
|
65787
|
+
const newDir = path48.dirname(newAbsPath);
|
|
65147
65788
|
if (currentDir === newDir) return edits;
|
|
65148
65789
|
let modified = false;
|
|
65149
65790
|
for (let i = 0; i < lines.length; i++) {
|
|
@@ -65181,11 +65822,11 @@ function extractSpecifierFromLine(line) {
|
|
|
65181
65822
|
return void 0;
|
|
65182
65823
|
}
|
|
65183
65824
|
function resolveRelativeSpecifier(fromDir, specifier) {
|
|
65184
|
-
const candidate =
|
|
65825
|
+
const candidate = path48.resolve(fromDir, specifier);
|
|
65185
65826
|
const extensions = ["", ".ts", ".tsx", ".js", ".jsx", "/index.ts", "/index.js"];
|
|
65186
65827
|
for (const ext of extensions) {
|
|
65187
65828
|
const full2 = candidate + ext;
|
|
65188
|
-
if (
|
|
65829
|
+
if (fs40.existsSync(full2)) {
|
|
65189
65830
|
return full2;
|
|
65190
65831
|
}
|
|
65191
65832
|
}
|
|
@@ -65194,8 +65835,8 @@ function resolveRelativeSpecifier(fromDir, specifier) {
|
|
|
65194
65835
|
function rewriteSymbolImport(importerAbsPath, sourceAbsPath, targetAbsPath, symbolName, projectRoot, dryRun, resolver) {
|
|
65195
65836
|
const edits = [];
|
|
65196
65837
|
const lines = readLines2(importerAbsPath);
|
|
65197
|
-
const relPath =
|
|
65198
|
-
const importerDir =
|
|
65838
|
+
const relPath = path48.relative(projectRoot, importerAbsPath);
|
|
65839
|
+
const importerDir = path48.dirname(importerAbsPath);
|
|
65199
65840
|
let modified = false;
|
|
65200
65841
|
for (let i = 0; i < lines.length; i++) {
|
|
65201
65842
|
const line = lines[i];
|
|
@@ -65203,8 +65844,8 @@ function rewriteSymbolImport(importerAbsPath, sourceAbsPath, targetAbsPath, symb
|
|
|
65203
65844
|
if (!specifier) continue;
|
|
65204
65845
|
const resolvedAbs = resolver ? resolver.resolve(specifier, importerAbsPath) : resolveRelativeSpecifier(importerDir, specifier);
|
|
65205
65846
|
if (!resolvedAbs) continue;
|
|
65206
|
-
const normalizedResolved =
|
|
65207
|
-
const normalizedSource =
|
|
65847
|
+
const normalizedResolved = path48.resolve(resolvedAbs).replace(/\\/g, "/");
|
|
65848
|
+
const normalizedSource = path48.resolve(sourceAbsPath).replace(/\\/g, "/");
|
|
65208
65849
|
if (normalizedResolved !== normalizedSource) continue;
|
|
65209
65850
|
const nameRegex = new RegExp(`\\b${escapeRegex3(symbolName)}\\b`);
|
|
65210
65851
|
if (!nameRegex.test(line)) continue;
|
|
@@ -65281,8 +65922,8 @@ function escapeRegex3(str2) {
|
|
|
65281
65922
|
}
|
|
65282
65923
|
|
|
65283
65924
|
// src/tools/refactoring/change-signature.ts
|
|
65284
|
-
import
|
|
65285
|
-
import
|
|
65925
|
+
import fs41 from "fs";
|
|
65926
|
+
import path49 from "path";
|
|
65286
65927
|
function changeSignature(store, projectRoot, symbolId, changes, dryRun = true) {
|
|
65287
65928
|
const result = {
|
|
65288
65929
|
success: false,
|
|
@@ -65314,12 +65955,12 @@ function changeSignature(store, projectRoot, symbolId, changes, dryRun = true) {
|
|
|
65314
65955
|
result.error = `File not found for symbol ${symbolId}`;
|
|
65315
65956
|
return result;
|
|
65316
65957
|
}
|
|
65317
|
-
const filePath =
|
|
65318
|
-
if (!
|
|
65958
|
+
const filePath = path49.resolve(projectRoot, symbolFile.path);
|
|
65959
|
+
if (!fs41.existsSync(filePath)) {
|
|
65319
65960
|
result.error = `File not found on disk: ${symbolFile.path}`;
|
|
65320
65961
|
return result;
|
|
65321
65962
|
}
|
|
65322
|
-
const ext =
|
|
65963
|
+
const ext = path49.extname(symbolFile.path).toLowerCase();
|
|
65323
65964
|
const lang = detectLanguage2(ext);
|
|
65324
65965
|
const lines = readLines2(filePath);
|
|
65325
65966
|
const defStartIdx = symbol.line_start - 1;
|
|
@@ -65573,8 +66214,8 @@ function updateCallSites(store, projectRoot, symbol, oldParams, newParams, chang
|
|
|
65573
66214
|
for (const fileId of fileIds) {
|
|
65574
66215
|
const file = store.getFileById(fileId);
|
|
65575
66216
|
if (!file) continue;
|
|
65576
|
-
const filePath =
|
|
65577
|
-
if (!
|
|
66217
|
+
const filePath = path49.resolve(projectRoot, file.path);
|
|
66218
|
+
if (!fs41.existsSync(filePath)) continue;
|
|
65578
66219
|
const lines = readLines2(filePath);
|
|
65579
66220
|
let fileModified = false;
|
|
65580
66221
|
const callPattern = new RegExp(`\\b${escapeRegex4(symbol.name)}\\s*\\(`, "g");
|
|
@@ -66352,8 +66993,8 @@ function getContractVersions(topoStore, opts) {
|
|
|
66352
66993
|
}
|
|
66353
66994
|
|
|
66354
66995
|
// src/tools/advanced/claude-sessions.ts
|
|
66355
|
-
import
|
|
66356
|
-
import
|
|
66996
|
+
import fs42 from "fs";
|
|
66997
|
+
import path50 from "path";
|
|
66357
66998
|
import os6 from "os";
|
|
66358
66999
|
import { err as err11, ok as ok9 } from "neverthrow";
|
|
66359
67000
|
init_logger();
|
|
@@ -66366,9 +67007,9 @@ function decodeClaudeProjectName(name) {
|
|
|
66366
67007
|
while (i < tokens.length) {
|
|
66367
67008
|
let entries = [];
|
|
66368
67009
|
try {
|
|
66369
|
-
entries =
|
|
67010
|
+
entries = fs42.readdirSync(current);
|
|
66370
67011
|
} catch {
|
|
66371
|
-
return current === "/" ? "/" + tokens.slice(i).join("/") :
|
|
67012
|
+
return current === "/" ? "/" + tokens.slice(i).join("/") : path50.join(current, tokens.slice(i).join("/"));
|
|
66372
67013
|
}
|
|
66373
67014
|
const entrySet = new Set(entries);
|
|
66374
67015
|
let matched = -1;
|
|
@@ -66376,12 +67017,12 @@ function decodeClaudeProjectName(name) {
|
|
|
66376
67017
|
const candidate = tokens.slice(i, j3).join("-");
|
|
66377
67018
|
if (entrySet.has(candidate)) {
|
|
66378
67019
|
matched = j3;
|
|
66379
|
-
current = current === "/" ? "/" + candidate :
|
|
67020
|
+
current = current === "/" ? "/" + candidate : path50.join(current, candidate);
|
|
66380
67021
|
break;
|
|
66381
67022
|
}
|
|
66382
67023
|
}
|
|
66383
67024
|
if (matched === -1) {
|
|
66384
|
-
return current === "/" ? "/" + tokens.slice(i).join("/") :
|
|
67025
|
+
return current === "/" ? "/" + tokens.slice(i).join("/") : path50.join(current, tokens.slice(i).join("/"));
|
|
66385
67026
|
}
|
|
66386
67027
|
i = matched;
|
|
66387
67028
|
}
|
|
@@ -66389,7 +67030,7 @@ function decodeClaudeProjectName(name) {
|
|
|
66389
67030
|
}
|
|
66390
67031
|
function countSessionFiles(dir) {
|
|
66391
67032
|
try {
|
|
66392
|
-
const entries =
|
|
67033
|
+
const entries = fs42.readdirSync(dir, { withFileTypes: true });
|
|
66393
67034
|
return entries.filter((e) => e.isFile() && (e.name.endsWith(".jsonl") || e.name.endsWith(".json"))).length;
|
|
66394
67035
|
} catch {
|
|
66395
67036
|
return 0;
|
|
@@ -66397,19 +67038,19 @@ function countSessionFiles(dir) {
|
|
|
66397
67038
|
}
|
|
66398
67039
|
function dirMtime(dir) {
|
|
66399
67040
|
try {
|
|
66400
|
-
return
|
|
67041
|
+
return fs42.statSync(dir).mtimeMs;
|
|
66401
67042
|
} catch {
|
|
66402
67043
|
return null;
|
|
66403
67044
|
}
|
|
66404
67045
|
}
|
|
66405
67046
|
function discoverClaudeSessions(opts = {}) {
|
|
66406
|
-
const scanRoot = opts.scanRoot ??
|
|
66407
|
-
if (!
|
|
67047
|
+
const scanRoot = opts.scanRoot ?? path50.join(os6.homedir(), ".claude", "projects");
|
|
67048
|
+
if (!fs42.existsSync(scanRoot)) {
|
|
66408
67049
|
return err11(validationError(`Claude projects root not found: ${scanRoot}`));
|
|
66409
67050
|
}
|
|
66410
67051
|
let entries;
|
|
66411
67052
|
try {
|
|
66412
|
-
entries =
|
|
67053
|
+
entries = fs42.readdirSync(scanRoot, { withFileTypes: true });
|
|
66413
67054
|
} catch (e) {
|
|
66414
67055
|
return err11(validationError(`Failed to read ${scanRoot}: ${e.message}`));
|
|
66415
67056
|
}
|
|
@@ -66421,17 +67062,17 @@ function discoverClaudeSessions(opts = {}) {
|
|
|
66421
67062
|
if (opts.excludePrefix && decoded === opts.excludePrefix) continue;
|
|
66422
67063
|
let exists = false;
|
|
66423
67064
|
try {
|
|
66424
|
-
exists =
|
|
67065
|
+
exists = fs42.statSync(decoded).isDirectory();
|
|
66425
67066
|
} catch {
|
|
66426
67067
|
exists = false;
|
|
66427
67068
|
}
|
|
66428
67069
|
if (opts.onlyExisting && !exists) continue;
|
|
66429
|
-
const projectStateDir =
|
|
67070
|
+
const projectStateDir = path50.join(scanRoot, entry.name);
|
|
66430
67071
|
sessions.push({
|
|
66431
67072
|
projectPath: decoded,
|
|
66432
67073
|
exists,
|
|
66433
67074
|
sessionFiles: countSessionFiles(projectStateDir),
|
|
66434
|
-
hasMemory:
|
|
67075
|
+
hasMemory: fs42.existsSync(path50.join(projectStateDir, "memory")),
|
|
66435
67076
|
lastActiveMs: dirMtime(projectStateDir)
|
|
66436
67077
|
});
|
|
66437
67078
|
}
|
|
@@ -66456,7 +67097,7 @@ function discoverAndRegisterSubprojects(topoStore, opts = {}) {
|
|
|
66456
67097
|
const totalEndpoints = services.reduce((sum, s) => sum + s.endpoints, 0);
|
|
66457
67098
|
added.push({
|
|
66458
67099
|
repo: session.projectPath,
|
|
66459
|
-
name:
|
|
67100
|
+
name: path50.basename(session.projectPath),
|
|
66460
67101
|
services: services.length,
|
|
66461
67102
|
endpoints: totalEndpoints
|
|
66462
67103
|
});
|
|
@@ -68101,16 +68742,16 @@ function findShortestPath(store, startNodeId, endNodeId, maxDepth) {
|
|
|
68101
68742
|
parent.set(nodeId, { from, edgeType: edge.edge_type_name });
|
|
68102
68743
|
nextFrontier.push(nodeId);
|
|
68103
68744
|
if (nodeId === endNodeId) {
|
|
68104
|
-
const
|
|
68745
|
+
const path67 = [endNodeId];
|
|
68105
68746
|
const edgeTypes = [];
|
|
68106
68747
|
let cur = endNodeId;
|
|
68107
68748
|
while (cur !== startNodeId) {
|
|
68108
68749
|
const p = parent.get(cur);
|
|
68109
|
-
|
|
68750
|
+
path67.unshift(p.from);
|
|
68110
68751
|
edgeTypes.unshift(p.edgeType);
|
|
68111
68752
|
cur = p.from;
|
|
68112
68753
|
}
|
|
68113
|
-
return { path:
|
|
68754
|
+
return { path: path67, edgeTypes };
|
|
68114
68755
|
}
|
|
68115
68756
|
}
|
|
68116
68757
|
}
|
|
@@ -68304,8 +68945,8 @@ function graphQuery(store, query, options = {}) {
|
|
|
68304
68945
|
}
|
|
68305
68946
|
|
|
68306
68947
|
// src/tools/analysis/dataflow.ts
|
|
68307
|
-
import
|
|
68308
|
-
import
|
|
68948
|
+
import fs43 from "fs";
|
|
68949
|
+
import path51 from "path";
|
|
68309
68950
|
function getDataflow(store, projectRoot, opts) {
|
|
68310
68951
|
const symbol = opts.symbolId ? store.getSymbolBySymbolId(opts.symbolId) : opts.fqn ? store.getSymbolByFqn(opts.fqn) : void 0;
|
|
68311
68952
|
if (!symbol) {
|
|
@@ -68316,10 +68957,10 @@ function getDataflow(store, projectRoot, opts) {
|
|
|
68316
68957
|
}
|
|
68317
68958
|
const file = store.getFileById(symbol.file_id);
|
|
68318
68959
|
if (!file) return err(notFound(`file for ${symbol.symbol_id}`));
|
|
68319
|
-
const absPath =
|
|
68960
|
+
const absPath = path51.resolve(projectRoot, file.path);
|
|
68320
68961
|
let content;
|
|
68321
68962
|
try {
|
|
68322
|
-
content =
|
|
68963
|
+
content = fs43.readFileSync(absPath, "utf-8");
|
|
68323
68964
|
} catch {
|
|
68324
68965
|
return err(validationError(`Cannot read file: ${file.path}`));
|
|
68325
68966
|
}
|
|
@@ -68472,8 +69113,8 @@ function escapeRegex5(str2) {
|
|
|
68472
69113
|
}
|
|
68473
69114
|
|
|
68474
69115
|
// src/tools/analysis/visualize.ts
|
|
68475
|
-
import
|
|
68476
|
-
import
|
|
69116
|
+
import fs44 from "fs";
|
|
69117
|
+
import path52 from "path";
|
|
68477
69118
|
|
|
68478
69119
|
// src/db/repositories/file-repository.ts
|
|
68479
69120
|
var FileRepository = class {
|
|
@@ -68499,14 +69140,14 @@ var FileRepository = class {
|
|
|
68499
69140
|
}
|
|
68500
69141
|
db;
|
|
68501
69142
|
_stmts;
|
|
68502
|
-
insertFile(
|
|
68503
|
-
const result = this._stmts.insertFile.run(
|
|
69143
|
+
insertFile(path67, language, contentHash, byteLength, workspace, mtimeMs, createNode) {
|
|
69144
|
+
const result = this._stmts.insertFile.run(path67, language, contentHash, byteLength, workspace, mtimeMs);
|
|
68504
69145
|
const fileId = Number(result.lastInsertRowid);
|
|
68505
69146
|
createNode("file", fileId);
|
|
68506
69147
|
return fileId;
|
|
68507
69148
|
}
|
|
68508
|
-
getFile(
|
|
68509
|
-
return this._stmts.getFile.get(
|
|
69149
|
+
getFile(path67) {
|
|
69150
|
+
return this._stmts.getFile.get(path67);
|
|
68510
69151
|
}
|
|
68511
69152
|
getFileById(id) {
|
|
68512
69153
|
return this._stmts.getFileById.get(id);
|
|
@@ -69364,9 +70005,9 @@ var Store = class {
|
|
|
69364
70005
|
domain;
|
|
69365
70006
|
analytics;
|
|
69366
70007
|
// --- Files (delegates to FileRepository) ---
|
|
69367
|
-
insertFile(
|
|
70008
|
+
insertFile(path67, language, contentHash, byteLength, workspace, mtimeMs) {
|
|
69368
70009
|
return this.files.insertFile(
|
|
69369
|
-
|
|
70010
|
+
path67,
|
|
69370
70011
|
language,
|
|
69371
70012
|
contentHash,
|
|
69372
70013
|
byteLength,
|
|
@@ -69375,8 +70016,8 @@ var Store = class {
|
|
|
69375
70016
|
(nodeType, refId) => this.graph.createNode(nodeType, refId)
|
|
69376
70017
|
);
|
|
69377
70018
|
}
|
|
69378
|
-
getFile(
|
|
69379
|
-
return this.files.getFile(
|
|
70019
|
+
getFile(path67) {
|
|
70020
|
+
return this.files.getFile(path67);
|
|
69380
70021
|
}
|
|
69381
70022
|
getFileById(id) {
|
|
69382
70023
|
return this.files.getFileById(id);
|
|
@@ -69756,14 +70397,14 @@ function buildSubprojectGraph(mainStore, opts) {
|
|
|
69756
70397
|
opts.granularity ?? "file",
|
|
69757
70398
|
opts.hideIsolated === true
|
|
69758
70399
|
);
|
|
69759
|
-
const mainPrefix = allRepos.find((r) => r.repo_root === projectRoot)?.name ??
|
|
70400
|
+
const mainPrefix = allRepos.find((r) => r.repo_root === projectRoot)?.name ?? path52.basename(projectRoot);
|
|
69760
70401
|
for (const n of mainResult.nodes) {
|
|
69761
70402
|
n.repo = mainPrefix;
|
|
69762
70403
|
allNodes.push(n);
|
|
69763
70404
|
}
|
|
69764
70405
|
allEdges.push(...mainResult.edges);
|
|
69765
70406
|
for (const repo of repos) {
|
|
69766
|
-
if (!repo.db_path || !
|
|
70407
|
+
if (!repo.db_path || !fs44.existsSync(repo.db_path)) continue;
|
|
69767
70408
|
let db = null;
|
|
69768
70409
|
try {
|
|
69769
70410
|
db = initializeDatabase(repo.db_path);
|
|
@@ -69892,7 +70533,7 @@ function buildFileGraph2(store, seedFiles, depth, edgeFilter, hideIsolated, opts
|
|
|
69892
70533
|
if (isExcludedPath(file.path)) continue;
|
|
69893
70534
|
vizNodeMap.set(file.path, {
|
|
69894
70535
|
id: file.path,
|
|
69895
|
-
label:
|
|
70536
|
+
label: path52.basename(file.path),
|
|
69896
70537
|
type: "file",
|
|
69897
70538
|
language: file.language,
|
|
69898
70539
|
framework_role: file.framework_role,
|
|
@@ -71161,8 +71802,8 @@ function visualizeGraph(store, opts) {
|
|
|
71161
71802
|
}
|
|
71162
71803
|
const layout = opts.layout ?? "force";
|
|
71163
71804
|
const html = generateHtml(nodes, edges, communities, layout, { highlightDepth: opts.highlightDepth });
|
|
71164
|
-
const outputPath = opts.output ??
|
|
71165
|
-
|
|
71805
|
+
const outputPath = opts.output ?? path52.join(process.env.TMPDIR ?? "/tmp", "trace-mcp-graph.html");
|
|
71806
|
+
fs44.writeFileSync(outputPath, html, "utf-8");
|
|
71166
71807
|
return ok({
|
|
71167
71808
|
outputPath,
|
|
71168
71809
|
nodes: nodes.length,
|
|
@@ -71212,8 +71853,8 @@ function getDependencyDiagram(store, opts) {
|
|
|
71212
71853
|
}
|
|
71213
71854
|
|
|
71214
71855
|
// src/tools/analysis/visualize-subproject.ts
|
|
71215
|
-
import
|
|
71216
|
-
import
|
|
71856
|
+
import fs45 from "fs";
|
|
71857
|
+
import path53 from "path";
|
|
71217
71858
|
function buildSubprojectData(topoStore) {
|
|
71218
71859
|
const services = topoStore.getAllServices();
|
|
71219
71860
|
const allEndpoints = topoStore.getAllEndpoints();
|
|
@@ -71471,8 +72112,8 @@ function visualizeSubprojectTopology(topoStore, opts) {
|
|
|
71471
72112
|
}
|
|
71472
72113
|
const layout = opts?.layout ?? "force";
|
|
71473
72114
|
const html = generateSubprojectHtml(nodes, edges, layout);
|
|
71474
|
-
const outputPath = opts?.output ??
|
|
71475
|
-
|
|
72115
|
+
const outputPath = opts?.output ?? path53.join(process.env.TMPDIR ?? "/tmp", "trace-mcp-subproject-topology.html");
|
|
72116
|
+
fs45.writeFileSync(outputPath, html, "utf-8");
|
|
71476
72117
|
return ok({
|
|
71477
72118
|
outputPath,
|
|
71478
72119
|
services: nodes.length,
|
|
@@ -73453,8 +74094,8 @@ function getCommunityDetail(store, communityId) {
|
|
|
73453
74094
|
}
|
|
73454
74095
|
|
|
73455
74096
|
// src/tools/quality/audit-config.ts
|
|
73456
|
-
import
|
|
73457
|
-
import
|
|
74097
|
+
import fs46 from "fs";
|
|
74098
|
+
import path54 from "path";
|
|
73458
74099
|
var CONFIG_PATTERNS = [
|
|
73459
74100
|
"CLAUDE.md",
|
|
73460
74101
|
".claude/CLAUDE.md",
|
|
@@ -73482,9 +74123,9 @@ function auditConfig(store, projectRoot, options = {}) {
|
|
|
73482
74123
|
const fileContents = /* @__PURE__ */ new Map();
|
|
73483
74124
|
for (const file of configFiles) {
|
|
73484
74125
|
const absPath = resolveConfigPath(file, projectRoot);
|
|
73485
|
-
if (!
|
|
74126
|
+
if (!fs46.existsSync(absPath)) continue;
|
|
73486
74127
|
try {
|
|
73487
|
-
const content =
|
|
74128
|
+
const content = fs46.readFileSync(absPath, "utf-8");
|
|
73488
74129
|
fileContents.set(file, { content, lines: content.split("\n") });
|
|
73489
74130
|
totalTokens += Math.ceil(content.length / 4);
|
|
73490
74131
|
} catch {
|
|
@@ -73496,8 +74137,8 @@ function auditConfig(store, projectRoot, options = {}) {
|
|
|
73496
74137
|
const pathMatches = line.match(/(?:src|lib|app|routes|tests?|components?|pages?)\/[\w/.-]+\.\w+/g);
|
|
73497
74138
|
if (pathMatches) {
|
|
73498
74139
|
for (const ref of pathMatches) {
|
|
73499
|
-
const refPath =
|
|
73500
|
-
if (!
|
|
74140
|
+
const refPath = path54.join(projectRoot, ref);
|
|
74141
|
+
if (!fs46.existsSync(refPath) && !store.getFile(ref)) {
|
|
73501
74142
|
issues.push({
|
|
73502
74143
|
file,
|
|
73503
74144
|
line: i + 1,
|
|
@@ -73609,19 +74250,19 @@ function checkSymbol(store, name, file, line, fixSuggestions, issues) {
|
|
|
73609
74250
|
function findConfigFiles(projectRoot) {
|
|
73610
74251
|
const found = [];
|
|
73611
74252
|
for (const pattern of CONFIG_PATTERNS) {
|
|
73612
|
-
const absPath =
|
|
73613
|
-
if (
|
|
74253
|
+
const absPath = path54.join(projectRoot, pattern);
|
|
74254
|
+
if (fs46.existsSync(absPath)) found.push(pattern);
|
|
73614
74255
|
}
|
|
73615
74256
|
for (const pattern of GLOBAL_CONFIG_PATTERNS) {
|
|
73616
74257
|
const absPath = pattern.replace("~", process.env.HOME ?? "");
|
|
73617
|
-
if (
|
|
74258
|
+
if (fs46.existsSync(absPath)) found.push(pattern);
|
|
73618
74259
|
}
|
|
73619
74260
|
return found;
|
|
73620
74261
|
}
|
|
73621
74262
|
function resolveConfigPath(file, projectRoot) {
|
|
73622
74263
|
if (file.startsWith("~")) return file.replace("~", process.env.HOME ?? "");
|
|
73623
|
-
if (
|
|
73624
|
-
return
|
|
74264
|
+
if (path54.isAbsolute(file)) return file;
|
|
74265
|
+
return path54.join(projectRoot, file);
|
|
73625
74266
|
}
|
|
73626
74267
|
function isGlobalConfig(file) {
|
|
73627
74268
|
return file.startsWith("~") || file.includes(".claude/CLAUDE.md") || file.includes(".claw/settings.json");
|
|
@@ -73876,8 +74517,8 @@ function cfgToAscii(cfg) {
|
|
|
73876
74517
|
}
|
|
73877
74518
|
|
|
73878
74519
|
// src/tools/analysis/control-flow.ts
|
|
73879
|
-
import
|
|
73880
|
-
import
|
|
74520
|
+
import fs47 from "fs";
|
|
74521
|
+
import path55 from "path";
|
|
73881
74522
|
function getControlFlow(store, projectRoot, options) {
|
|
73882
74523
|
const { symbolId, fqn, format: format2, simplify } = options;
|
|
73883
74524
|
let symbol = null;
|
|
@@ -73900,11 +74541,11 @@ function getControlFlow(store, projectRoot, options) {
|
|
|
73900
74541
|
if (!file) {
|
|
73901
74542
|
return err(notFound(`file for symbol`));
|
|
73902
74543
|
}
|
|
73903
|
-
const absPath =
|
|
73904
|
-
if (!
|
|
74544
|
+
const absPath = path55.isAbsolute(file.path) ? file.path : path55.join(projectRoot, file.path);
|
|
74545
|
+
if (!fs47.existsSync(absPath)) {
|
|
73905
74546
|
return err(validationError(`File not on disk: ${file.path}`));
|
|
73906
74547
|
}
|
|
73907
|
-
const content =
|
|
74548
|
+
const content = fs47.readFileSync(absPath, "utf-8");
|
|
73908
74549
|
const lines = content.split("\n");
|
|
73909
74550
|
const startLine = symbol.line_start ?? 1;
|
|
73910
74551
|
const endLine = symbol.line_end ?? lines.length;
|
|
@@ -73965,12 +74606,12 @@ function simplifyCFG(cfg) {
|
|
|
73965
74606
|
}
|
|
73966
74607
|
|
|
73967
74608
|
// src/tools/project/package-deps.ts
|
|
73968
|
-
import
|
|
73969
|
-
import
|
|
74609
|
+
import fs48 from "fs";
|
|
74610
|
+
import path56 from "path";
|
|
73970
74611
|
function loadRegistry() {
|
|
73971
|
-
if (!
|
|
74612
|
+
if (!fs48.existsSync(REGISTRY_PATH)) return {};
|
|
73972
74613
|
try {
|
|
73973
|
-
const raw = JSON.parse(
|
|
74614
|
+
const raw = JSON.parse(fs48.readFileSync(REGISTRY_PATH, "utf-8"));
|
|
73974
74615
|
return raw.projects ?? raw ?? {};
|
|
73975
74616
|
} catch {
|
|
73976
74617
|
return {};
|
|
@@ -73978,10 +74619,10 @@ function loadRegistry() {
|
|
|
73978
74619
|
}
|
|
73979
74620
|
function readManifest(repoPath) {
|
|
73980
74621
|
const result = { name: void 0, deps: /* @__PURE__ */ new Map(), publishes: [] };
|
|
73981
|
-
const pkgJsonPath =
|
|
73982
|
-
if (
|
|
74622
|
+
const pkgJsonPath = path56.join(repoPath, "package.json");
|
|
74623
|
+
if (fs48.existsSync(pkgJsonPath)) {
|
|
73983
74624
|
try {
|
|
73984
|
-
const pkg = JSON.parse(
|
|
74625
|
+
const pkg = JSON.parse(fs48.readFileSync(pkgJsonPath, "utf-8"));
|
|
73985
74626
|
result.name = pkg.name;
|
|
73986
74627
|
if (pkg.name) result.publishes.push(pkg.name);
|
|
73987
74628
|
for (const [dep, ver] of Object.entries(pkg.dependencies ?? {})) {
|
|
@@ -73993,10 +74634,10 @@ function readManifest(repoPath) {
|
|
|
73993
74634
|
} catch {
|
|
73994
74635
|
}
|
|
73995
74636
|
}
|
|
73996
|
-
const composerPath =
|
|
73997
|
-
if (
|
|
74637
|
+
const composerPath = path56.join(repoPath, "composer.json");
|
|
74638
|
+
if (fs48.existsSync(composerPath)) {
|
|
73998
74639
|
try {
|
|
73999
|
-
const composer = JSON.parse(
|
|
74640
|
+
const composer = JSON.parse(fs48.readFileSync(composerPath, "utf-8"));
|
|
74000
74641
|
if (composer.name) {
|
|
74001
74642
|
result.name ??= composer.name;
|
|
74002
74643
|
result.publishes.push(composer.name);
|
|
@@ -74011,10 +74652,10 @@ function readManifest(repoPath) {
|
|
|
74011
74652
|
} catch {
|
|
74012
74653
|
}
|
|
74013
74654
|
}
|
|
74014
|
-
const pyprojectPath =
|
|
74015
|
-
if (
|
|
74655
|
+
const pyprojectPath = path56.join(repoPath, "pyproject.toml");
|
|
74656
|
+
if (fs48.existsSync(pyprojectPath)) {
|
|
74016
74657
|
try {
|
|
74017
|
-
const content =
|
|
74658
|
+
const content = fs48.readFileSync(pyprojectPath, "utf-8");
|
|
74018
74659
|
const nameMatch = content.match(/^name\s*=\s*"([^"]+)"/m);
|
|
74019
74660
|
if (nameMatch) {
|
|
74020
74661
|
result.name ??= nameMatch[1];
|
|
@@ -74039,12 +74680,12 @@ function getPackageDeps(options) {
|
|
|
74039
74680
|
const publishMap = /* @__PURE__ */ new Map();
|
|
74040
74681
|
for (const [repoPath, entry] of Object.entries(registry)) {
|
|
74041
74682
|
const absPath = repoPath;
|
|
74042
|
-
if (!
|
|
74683
|
+
if (!fs48.existsSync(absPath)) continue;
|
|
74043
74684
|
const manifest = readManifest(absPath);
|
|
74044
74685
|
repoManifests.set(repoPath, manifest);
|
|
74045
74686
|
const allPublishes = [...entry.publishes ?? [], ...manifest.publishes];
|
|
74046
74687
|
for (const p of new Set(allPublishes)) {
|
|
74047
|
-
publishMap.set(p, { repo: entry.name ??
|
|
74688
|
+
publishMap.set(p, { repo: entry.name ?? path56.basename(repoPath), repoPath });
|
|
74048
74689
|
}
|
|
74049
74690
|
}
|
|
74050
74691
|
const results = [];
|
|
@@ -74054,7 +74695,7 @@ function getPackageDeps(options) {
|
|
|
74054
74695
|
} else if (project) {
|
|
74055
74696
|
for (const [repoPath, manifest] of repoManifests) {
|
|
74056
74697
|
const entry = registry[repoPath];
|
|
74057
|
-
if (entry?.name === project ||
|
|
74698
|
+
if (entry?.name === project || path56.basename(repoPath) === project) {
|
|
74058
74699
|
for (const p of manifest.publishes) {
|
|
74059
74700
|
targetPackages.add(p);
|
|
74060
74701
|
}
|
|
@@ -74073,7 +74714,7 @@ function getPackageDeps(options) {
|
|
|
74073
74714
|
if (direction === "dependents" || direction === "both") {
|
|
74074
74715
|
for (const [repoPath, manifest] of repoManifests) {
|
|
74075
74716
|
const entry = registry[repoPath];
|
|
74076
|
-
const repoName = entry?.name ??
|
|
74717
|
+
const repoName = entry?.name ?? path56.basename(repoPath);
|
|
74077
74718
|
for (const targetPkg of targetPackages) {
|
|
74078
74719
|
const dep = manifest.deps.get(targetPkg);
|
|
74079
74720
|
if (dep) {
|
|
@@ -74092,7 +74733,7 @@ function getPackageDeps(options) {
|
|
|
74092
74733
|
if (direction === "dependencies" || direction === "both") {
|
|
74093
74734
|
for (const [repoPath, manifest] of repoManifests) {
|
|
74094
74735
|
const entry = registry[repoPath];
|
|
74095
|
-
const repoName = entry?.name ??
|
|
74736
|
+
const repoName = entry?.name ?? path56.basename(repoPath);
|
|
74096
74737
|
const isTarget = manifest.publishes.some((p) => targetPackages.has(p));
|
|
74097
74738
|
if (!isTarget && targetPackages.size > 0) continue;
|
|
74098
74739
|
for (const [dep, info] of manifest.deps) {
|
|
@@ -74589,8 +75230,8 @@ function evaluateQualityGates(store, projectRoot, gatesConfig, options = {}) {
|
|
|
74589
75230
|
}
|
|
74590
75231
|
|
|
74591
75232
|
// src/tools/quality/security-context-export.ts
|
|
74592
|
-
import { readFileSync as
|
|
74593
|
-
import
|
|
75233
|
+
import { readFileSync as readFileSync8 } from "fs";
|
|
75234
|
+
import path58 from "path";
|
|
74594
75235
|
import { ok as ok10 } from "neverthrow";
|
|
74595
75236
|
var CATEGORY_PATTERNS = [
|
|
74596
75237
|
// file_read
|
|
@@ -74759,9 +75400,9 @@ function scanInlineHandler(source, toolCallIndex, filePath, store, projectRoot,
|
|
|
74759
75400
|
}
|
|
74760
75401
|
const file = sym.file_id ? store.getFileById(sym.file_id) : null;
|
|
74761
75402
|
if (file && sym.line_start && sym.line_end) {
|
|
74762
|
-
const symAbsPath =
|
|
75403
|
+
const symAbsPath = path58.resolve(projectRoot, file.path);
|
|
74763
75404
|
try {
|
|
74764
|
-
const symSource =
|
|
75405
|
+
const symSource = readFileSync8(symAbsPath, "utf-8");
|
|
74765
75406
|
const lines = symSource.split("\n");
|
|
74766
75407
|
const symBody = lines.slice(sym.line_start - 1, sym.line_end).join("\n");
|
|
74767
75408
|
scanSourceForSecurityCalls(symBody, file.path, sym.line_start, results);
|
|
@@ -74788,7 +75429,7 @@ function scanSourceForSecurityCalls(body, filePath, startLine, results) {
|
|
|
74788
75429
|
results.push({ function: "process.env", file: filePath, line: lineOffset, category: "env_read" });
|
|
74789
75430
|
}
|
|
74790
75431
|
}
|
|
74791
|
-
var PKG_VERSION = true ? "1.
|
|
75432
|
+
var PKG_VERSION = true ? "1.23.0" : "0.0.0-dev";
|
|
74792
75433
|
function exportSecurityContext(store, projectRoot, opts = {}) {
|
|
74793
75434
|
const depth = Math.min(opts.depth ?? 3, 5);
|
|
74794
75435
|
const warnings = [];
|
|
@@ -74803,10 +75444,10 @@ function exportSecurityContext(store, projectRoot, opts = {}) {
|
|
|
74803
75444
|
const fileRow = route.file_id ? store.getFileById(route.file_id) : null;
|
|
74804
75445
|
if (!fileRow) continue;
|
|
74805
75446
|
if (opts.scope && !fileRow.path.startsWith(opts.scope)) continue;
|
|
74806
|
-
const absPath =
|
|
75447
|
+
const absPath = path58.resolve(projectRoot, fileRow.path);
|
|
74807
75448
|
let source;
|
|
74808
75449
|
try {
|
|
74809
|
-
source =
|
|
75450
|
+
source = readFileSync8(absPath, "utf-8");
|
|
74810
75451
|
} catch {
|
|
74811
75452
|
continue;
|
|
74812
75453
|
}
|
|
@@ -74847,7 +75488,7 @@ function exportSecurityContext(store, projectRoot, opts = {}) {
|
|
|
74847
75488
|
const sensitiveFlows = [];
|
|
74848
75489
|
const mcpServerFiles = new Set(toolRegistrations.map((t) => t.file));
|
|
74849
75490
|
if (mcpServerFiles.size > 0) {
|
|
74850
|
-
const mcpDirs = [...new Set([...mcpServerFiles].map((f) =>
|
|
75491
|
+
const mcpDirs = [...new Set([...mcpServerFiles].map((f) => path58.dirname(f)))];
|
|
74851
75492
|
for (const dir of mcpDirs) {
|
|
74852
75493
|
const taintResult = taintAnalysis(store, projectRoot, {
|
|
74853
75494
|
scope: dir,
|
|
@@ -75110,7 +75751,7 @@ import { z as z13 } from "zod";
|
|
|
75110
75751
|
|
|
75111
75752
|
// src/tools/ai/ai-tools.ts
|
|
75112
75753
|
import { z as z11 } from "zod";
|
|
75113
|
-
import
|
|
75754
|
+
import path59 from "path";
|
|
75114
75755
|
function j(value) {
|
|
75115
75756
|
return JSON.stringify(value);
|
|
75116
75757
|
}
|
|
@@ -75126,7 +75767,7 @@ function symbolToContextItem(sym, file, projectRoot, score = 1) {
|
|
|
75126
75767
|
}
|
|
75127
75768
|
function readSourceSafe(filePath, byteStart, byteEnd, projectRoot, gitignored) {
|
|
75128
75769
|
try {
|
|
75129
|
-
const absPath =
|
|
75770
|
+
const absPath = path59.resolve(projectRoot, filePath);
|
|
75130
75771
|
return readByteRange(absPath, byteStart, byteEnd, gitignored);
|
|
75131
75772
|
} catch {
|
|
75132
75773
|
return null;
|
|
@@ -75442,22 +76083,22 @@ function registerAITools(server, ctx) {
|
|
|
75442
76083
|
// src/bundles.ts
|
|
75443
76084
|
init_logger();
|
|
75444
76085
|
import Database5 from "better-sqlite3";
|
|
75445
|
-
import
|
|
75446
|
-
import
|
|
76086
|
+
import path60 from "path";
|
|
76087
|
+
import fs50 from "fs";
|
|
75447
76088
|
import crypto6 from "crypto";
|
|
75448
|
-
var BUNDLES_DIR =
|
|
76089
|
+
var BUNDLES_DIR = path60.join(TRACE_MCP_HOME, "bundles");
|
|
75449
76090
|
function getBundlePath(packageName, version2) {
|
|
75450
76091
|
const safeName = packageName.replace(/[^a-zA-Z0-9._-]/g, "_");
|
|
75451
|
-
return
|
|
76092
|
+
return path60.join(BUNDLES_DIR, `${safeName}-${version2}.bundle.db`);
|
|
75452
76093
|
}
|
|
75453
76094
|
function getManifestPath() {
|
|
75454
|
-
return
|
|
76095
|
+
return path60.join(BUNDLES_DIR, "manifest.json");
|
|
75455
76096
|
}
|
|
75456
76097
|
function loadManifest() {
|
|
75457
76098
|
const p = getManifestPath();
|
|
75458
|
-
if (!
|
|
76099
|
+
if (!fs50.existsSync(p)) return { bundles: [] };
|
|
75459
76100
|
try {
|
|
75460
|
-
return JSON.parse(
|
|
76101
|
+
return JSON.parse(fs50.readFileSync(p, "utf-8"));
|
|
75461
76102
|
} catch {
|
|
75462
76103
|
return { bundles: [] };
|
|
75463
76104
|
}
|
|
@@ -75467,7 +76108,7 @@ function listBundles() {
|
|
|
75467
76108
|
}
|
|
75468
76109
|
function loadBundle(packageName, version2) {
|
|
75469
76110
|
const bundlePath = getBundlePath(packageName, version2);
|
|
75470
|
-
if (!
|
|
76111
|
+
if (!fs50.existsSync(bundlePath)) return null;
|
|
75471
76112
|
try {
|
|
75472
76113
|
const db = new Database5(bundlePath, { readonly: true });
|
|
75473
76114
|
return { package: packageName, version: version2, db };
|
|
@@ -75521,8 +76162,8 @@ function searchBundles(bundles, query, opts = {}) {
|
|
|
75521
76162
|
|
|
75522
76163
|
// src/analytics/analytics-store.ts
|
|
75523
76164
|
import Database6 from "better-sqlite3";
|
|
75524
|
-
import
|
|
75525
|
-
var ANALYTICS_DB_PATH =
|
|
76165
|
+
import path61 from "path";
|
|
76166
|
+
var ANALYTICS_DB_PATH = path61.join(TRACE_MCP_HOME, "analytics.db");
|
|
75526
76167
|
var SCHEMA_SQL = `
|
|
75527
76168
|
CREATE TABLE IF NOT EXISTS sessions (
|
|
75528
76169
|
id TEXT PRIMARY KEY,
|
|
@@ -75754,10 +76395,10 @@ var AnalyticsStore = class {
|
|
|
75754
76395
|
|
|
75755
76396
|
// src/analytics/log-parser.ts
|
|
75756
76397
|
init_logger();
|
|
75757
|
-
import
|
|
75758
|
-
import
|
|
76398
|
+
import fs51 from "fs";
|
|
76399
|
+
import path62 from "path";
|
|
75759
76400
|
import os7 from "os";
|
|
75760
|
-
var CLAUDE_PROJECTS_DIR =
|
|
76401
|
+
var CLAUDE_PROJECTS_DIR = path62.join(os7.homedir(), ".claude", "projects");
|
|
75761
76402
|
var CLAW_SESSIONS_DIR_NAME = ".claw/sessions";
|
|
75762
76403
|
function parseToolName(fullName) {
|
|
75763
76404
|
const match = fullName.match(/^mcp__([^_]+)__(.+)$/);
|
|
@@ -75832,9 +76473,9 @@ function processToolResult(item, toolResults) {
|
|
|
75832
76473
|
}
|
|
75833
76474
|
function parseSessionFile(filePath, projectPath) {
|
|
75834
76475
|
try {
|
|
75835
|
-
const content =
|
|
76476
|
+
const content = fs51.readFileSync(filePath, "utf-8");
|
|
75836
76477
|
const lines = content.split("\n").filter((l) => l.trim());
|
|
75837
|
-
const sessionId =
|
|
76478
|
+
const sessionId = path62.basename(filePath, ".jsonl");
|
|
75838
76479
|
const toolCalls = [];
|
|
75839
76480
|
const toolResults = /* @__PURE__ */ new Map();
|
|
75840
76481
|
let model = "";
|
|
@@ -75924,7 +76565,7 @@ function decodeDirName(dirName) {
|
|
|
75924
76565
|
const seg = parts[i];
|
|
75925
76566
|
const candidate = base + "/" + (tail ? tail + "-" + seg : seg);
|
|
75926
76567
|
try {
|
|
75927
|
-
if (
|
|
76568
|
+
if (fs51.statSync(candidate).isDirectory()) {
|
|
75928
76569
|
base = candidate;
|
|
75929
76570
|
tail = "";
|
|
75930
76571
|
continue;
|
|
@@ -75934,7 +76575,7 @@ function decodeDirName(dirName) {
|
|
|
75934
76575
|
if (tail) {
|
|
75935
76576
|
const slashCandidate = base + "/" + tail;
|
|
75936
76577
|
try {
|
|
75937
|
-
if (
|
|
76578
|
+
if (fs51.statSync(slashCandidate).isDirectory()) {
|
|
75938
76579
|
base = slashCandidate;
|
|
75939
76580
|
tail = seg;
|
|
75940
76581
|
continue;
|
|
@@ -75947,20 +76588,20 @@ function decodeDirName(dirName) {
|
|
|
75947
76588
|
return tail ? base + "/" + tail : base;
|
|
75948
76589
|
}
|
|
75949
76590
|
function listProjectDirs() {
|
|
75950
|
-
if (!
|
|
75951
|
-
const entries =
|
|
76591
|
+
if (!fs51.existsSync(CLAUDE_PROJECTS_DIR)) return [];
|
|
76592
|
+
const entries = fs51.readdirSync(CLAUDE_PROJECTS_DIR, { withFileTypes: true });
|
|
75952
76593
|
return entries.filter((e) => e.isDirectory()).map((e) => ({
|
|
75953
76594
|
dirName: e.name,
|
|
75954
76595
|
projectPath: decodeDirName(e.name)
|
|
75955
76596
|
}));
|
|
75956
76597
|
}
|
|
75957
76598
|
function listSessionFiles(projectDirName) {
|
|
75958
|
-
const dir =
|
|
75959
|
-
if (!
|
|
75960
|
-
const entries =
|
|
76599
|
+
const dir = path62.join(CLAUDE_PROJECTS_DIR, projectDirName);
|
|
76600
|
+
if (!fs51.existsSync(dir)) return [];
|
|
76601
|
+
const entries = fs51.readdirSync(dir, { withFileTypes: true });
|
|
75961
76602
|
return entries.filter((e) => e.isFile() && e.name.endsWith(".jsonl")).map((e) => {
|
|
75962
|
-
const filePath =
|
|
75963
|
-
const stat =
|
|
76603
|
+
const filePath = path62.join(dir, e.name);
|
|
76604
|
+
const stat = fs51.statSync(filePath);
|
|
75964
76605
|
return { filePath, mtime: stat.mtimeMs };
|
|
75965
76606
|
});
|
|
75966
76607
|
}
|
|
@@ -75973,15 +76614,15 @@ function listAllSessions() {
|
|
|
75973
76614
|
}
|
|
75974
76615
|
const clawProjectPaths = discoverClawProjects();
|
|
75975
76616
|
for (const projectPath of clawProjectPaths) {
|
|
75976
|
-
const sessionsDir =
|
|
75977
|
-
if (!
|
|
76617
|
+
const sessionsDir = path62.join(projectPath, CLAW_SESSIONS_DIR_NAME);
|
|
76618
|
+
if (!fs51.existsSync(sessionsDir)) continue;
|
|
75978
76619
|
try {
|
|
75979
|
-
const entries =
|
|
76620
|
+
const entries = fs51.readdirSync(sessionsDir, { withFileTypes: true });
|
|
75980
76621
|
for (const e of entries) {
|
|
75981
76622
|
if (!e.isFile() || !e.name.endsWith(".jsonl")) continue;
|
|
75982
|
-
const filePath =
|
|
76623
|
+
const filePath = path62.join(sessionsDir, e.name);
|
|
75983
76624
|
try {
|
|
75984
|
-
const stat =
|
|
76625
|
+
const stat = fs51.statSync(filePath);
|
|
75985
76626
|
results.push({ filePath, projectPath, client: "claw-code", mtime: stat.mtimeMs });
|
|
75986
76627
|
} catch {
|
|
75987
76628
|
}
|
|
@@ -75994,25 +76635,25 @@ function listAllSessions() {
|
|
|
75994
76635
|
function discoverClawProjects() {
|
|
75995
76636
|
const paths = /* @__PURE__ */ new Set();
|
|
75996
76637
|
for (const { projectPath } of listProjectDirs()) {
|
|
75997
|
-
if (
|
|
76638
|
+
if (fs51.existsSync(path62.join(projectPath, CLAW_SESSIONS_DIR_NAME))) {
|
|
75998
76639
|
paths.add(projectPath);
|
|
75999
76640
|
}
|
|
76000
76641
|
}
|
|
76001
76642
|
const cwd = process.cwd();
|
|
76002
|
-
if (
|
|
76643
|
+
if (fs51.existsSync(path62.join(cwd, CLAW_SESSIONS_DIR_NAME))) {
|
|
76003
76644
|
paths.add(cwd);
|
|
76004
76645
|
}
|
|
76005
76646
|
const home = os7.homedir();
|
|
76006
76647
|
const commonRoots = ["Projects", "projects", "dev", "workspace", "code", "PhpstormProjects", "WebstormProjects", "src"];
|
|
76007
76648
|
for (const root of commonRoots) {
|
|
76008
|
-
const rootDir =
|
|
76009
|
-
if (!
|
|
76649
|
+
const rootDir = path62.join(home, root);
|
|
76650
|
+
if (!fs51.existsSync(rootDir)) continue;
|
|
76010
76651
|
try {
|
|
76011
|
-
const entries =
|
|
76652
|
+
const entries = fs51.readdirSync(rootDir, { withFileTypes: true });
|
|
76012
76653
|
for (const e of entries) {
|
|
76013
76654
|
if (!e.isDirectory()) continue;
|
|
76014
|
-
const projectDir =
|
|
76015
|
-
if (
|
|
76655
|
+
const projectDir = path62.join(rootDir, e.name);
|
|
76656
|
+
if (fs51.existsSync(path62.join(projectDir, CLAW_SESSIONS_DIR_NAME))) {
|
|
76016
76657
|
paths.add(projectDir);
|
|
76017
76658
|
}
|
|
76018
76659
|
}
|
|
@@ -76717,8 +77358,8 @@ function formatBenchmarkMarkdown(result) {
|
|
|
76717
77358
|
}
|
|
76718
77359
|
|
|
76719
77360
|
// src/analytics/tech-detector.ts
|
|
76720
|
-
import
|
|
76721
|
-
import
|
|
77361
|
+
import fs52 from "fs";
|
|
77362
|
+
import path63 from "path";
|
|
76722
77363
|
|
|
76723
77364
|
// src/analytics/known-packages.ts
|
|
76724
77365
|
var KNOWN_PACKAGES = {
|
|
@@ -78229,7 +78870,7 @@ var KNOWN_PACKAGES = {
|
|
|
78229
78870
|
// src/analytics/tech-detector.ts
|
|
78230
78871
|
function parsePackageJson(filePath) {
|
|
78231
78872
|
try {
|
|
78232
|
-
const pkg = JSON.parse(
|
|
78873
|
+
const pkg = JSON.parse(fs52.readFileSync(filePath, "utf-8"));
|
|
78233
78874
|
const deps = [];
|
|
78234
78875
|
for (const [name, version2] of Object.entries(pkg.dependencies ?? {})) {
|
|
78235
78876
|
deps.push({ name, version: String(version2), isDev: false });
|
|
@@ -78244,7 +78885,7 @@ function parsePackageJson(filePath) {
|
|
|
78244
78885
|
}
|
|
78245
78886
|
function parseComposerJson(filePath) {
|
|
78246
78887
|
try {
|
|
78247
|
-
const pkg = JSON.parse(
|
|
78888
|
+
const pkg = JSON.parse(fs52.readFileSync(filePath, "utf-8"));
|
|
78248
78889
|
const deps = [];
|
|
78249
78890
|
for (const [name, version2] of Object.entries(pkg.require ?? {})) {
|
|
78250
78891
|
if (name === "php" || name.startsWith("ext-")) continue;
|
|
@@ -78260,7 +78901,7 @@ function parseComposerJson(filePath) {
|
|
|
78260
78901
|
}
|
|
78261
78902
|
function parseRequirementsTxt(filePath) {
|
|
78262
78903
|
try {
|
|
78263
|
-
const content =
|
|
78904
|
+
const content = fs52.readFileSync(filePath, "utf-8");
|
|
78264
78905
|
const deps = [];
|
|
78265
78906
|
for (const line of content.split("\n")) {
|
|
78266
78907
|
const trimmed = line.trim();
|
|
@@ -78277,7 +78918,7 @@ function parseRequirementsTxt(filePath) {
|
|
|
78277
78918
|
}
|
|
78278
78919
|
function parsePyprojectToml(filePath) {
|
|
78279
78920
|
try {
|
|
78280
|
-
const content =
|
|
78921
|
+
const content = fs52.readFileSync(filePath, "utf-8");
|
|
78281
78922
|
const deps = [];
|
|
78282
78923
|
const depSection = content.match(/\[project\][\s\S]*?dependencies\s*=\s*\[([\s\S]*?)\]/);
|
|
78283
78924
|
if (depSection) {
|
|
@@ -78293,7 +78934,7 @@ function parsePyprojectToml(filePath) {
|
|
|
78293
78934
|
}
|
|
78294
78935
|
function parseGoMod(filePath) {
|
|
78295
78936
|
try {
|
|
78296
|
-
const content =
|
|
78937
|
+
const content = fs52.readFileSync(filePath, "utf-8");
|
|
78297
78938
|
const deps = [];
|
|
78298
78939
|
const requireBlock = content.match(/require\s*\(([\s\S]*?)\)/);
|
|
78299
78940
|
if (requireBlock) {
|
|
@@ -78313,7 +78954,7 @@ function parseGoMod(filePath) {
|
|
|
78313
78954
|
}
|
|
78314
78955
|
function parseGemfile(filePath) {
|
|
78315
78956
|
try {
|
|
78316
|
-
const content =
|
|
78957
|
+
const content = fs52.readFileSync(filePath, "utf-8");
|
|
78317
78958
|
const deps = [];
|
|
78318
78959
|
for (const line of content.split("\n")) {
|
|
78319
78960
|
const m = line.match(/gem\s+['"]([^'"]+)['"]\s*(?:,\s*['"]([^'"]*)['""])?/);
|
|
@@ -78382,8 +79023,8 @@ function detectCoverage(projectRoot, opts = {}) {
|
|
|
78382
79023
|
const manifestsFound = [];
|
|
78383
79024
|
const allDeps = [];
|
|
78384
79025
|
for (const { file, ecosystem, parser } of MANIFEST_PARSERS) {
|
|
78385
|
-
const filePath =
|
|
78386
|
-
if (!
|
|
79026
|
+
const filePath = path63.join(projectRoot, file);
|
|
79027
|
+
if (!fs52.existsSync(filePath)) continue;
|
|
78387
79028
|
manifestsFound.push(file);
|
|
78388
79029
|
const rawDeps = parser(filePath);
|
|
78389
79030
|
for (const raw of rawDeps) {
|
|
@@ -79872,8 +80513,8 @@ function registerSessionTools(server, ctx) {
|
|
|
79872
80513
|
import { z as z14 } from "zod";
|
|
79873
80514
|
|
|
79874
80515
|
// src/memory/conversation-miner.ts
|
|
79875
|
-
import * as
|
|
79876
|
-
import * as
|
|
80516
|
+
import * as fs53 from "fs";
|
|
80517
|
+
import * as path64 from "path";
|
|
79877
80518
|
init_logger();
|
|
79878
80519
|
var DECISION_PATTERNS = [
|
|
79879
80520
|
// Architecture decisions: "decided to", "we'll use", "going with", "chose X over Y"
|
|
@@ -79948,7 +80589,7 @@ function truncateTitle(s) {
|
|
|
79948
80589
|
return clean.slice(0, 77) + "...";
|
|
79949
80590
|
}
|
|
79950
80591
|
function parseConversationTurns(filePath) {
|
|
79951
|
-
const content =
|
|
80592
|
+
const content = fs53.readFileSync(filePath, "utf-8");
|
|
79952
80593
|
const lines = content.split("\n").filter((l) => l.trim());
|
|
79953
80594
|
const turns = [];
|
|
79954
80595
|
for (const line of lines) {
|
|
@@ -80101,7 +80742,7 @@ function mineSessions(decisionStore, opts = {}) {
|
|
|
80101
80742
|
file_path: d.file_path,
|
|
80102
80743
|
tags: d.tags,
|
|
80103
80744
|
valid_from: d.timestamp,
|
|
80104
|
-
session_id:
|
|
80745
|
+
session_id: path64.basename(session.filePath, ".jsonl"),
|
|
80105
80746
|
source: "mined",
|
|
80106
80747
|
confidence: d.confidence
|
|
80107
80748
|
}));
|
|
@@ -80126,8 +80767,8 @@ function mineSessions(decisionStore, opts = {}) {
|
|
|
80126
80767
|
}
|
|
80127
80768
|
|
|
80128
80769
|
// src/memory/session-indexer.ts
|
|
80129
|
-
import * as
|
|
80130
|
-
import * as
|
|
80770
|
+
import * as fs54 from "fs";
|
|
80771
|
+
import * as path65 from "path";
|
|
80131
80772
|
init_logger();
|
|
80132
80773
|
var MAX_CHUNK_CHARS = 2e3;
|
|
80133
80774
|
var MIN_MESSAGE_CHARS = 50;
|
|
@@ -80166,9 +80807,9 @@ function truncateChunk(text) {
|
|
|
80166
80807
|
return truncated + "...";
|
|
80167
80808
|
}
|
|
80168
80809
|
function indexSessionFile(filePath, projectPath, decisionStore) {
|
|
80169
|
-
const content =
|
|
80810
|
+
const content = fs54.readFileSync(filePath, "utf-8");
|
|
80170
80811
|
const lines = content.split("\n").filter((l) => l.trim());
|
|
80171
|
-
const sessionId =
|
|
80812
|
+
const sessionId = path65.basename(filePath, ".jsonl");
|
|
80172
80813
|
const chunks = [];
|
|
80173
80814
|
let chunkIndex = 0;
|
|
80174
80815
|
for (const line of lines) {
|
|
@@ -80219,7 +80860,7 @@ function indexSessions(decisionStore, opts = {}) {
|
|
|
80219
80860
|
skipped++;
|
|
80220
80861
|
continue;
|
|
80221
80862
|
}
|
|
80222
|
-
const sessionId =
|
|
80863
|
+
const sessionId = path65.basename(session.filePath, ".jsonl");
|
|
80223
80864
|
if (!opts.force && decisionStore.isSessionIndexed(sessionId)) {
|
|
80224
80865
|
skipped++;
|
|
80225
80866
|
continue;
|
|
@@ -80244,7 +80885,7 @@ function indexSessions(decisionStore, opts = {}) {
|
|
|
80244
80885
|
}
|
|
80245
80886
|
|
|
80246
80887
|
// src/memory/wake-up.ts
|
|
80247
|
-
import * as
|
|
80888
|
+
import * as path66 from "path";
|
|
80248
80889
|
function compactDecision(d) {
|
|
80249
80890
|
const entry = {
|
|
80250
80891
|
id: d.id,
|
|
@@ -80268,7 +80909,7 @@ function assembleWakeUp(decisionStore, projectRoot, opts = {}) {
|
|
|
80268
80909
|
const indexedSessions = decisionStore.getIndexedSessionIds(projectRoot);
|
|
80269
80910
|
const result = {
|
|
80270
80911
|
project: {
|
|
80271
|
-
name:
|
|
80912
|
+
name: path66.basename(projectRoot),
|
|
80272
80913
|
root: projectRoot
|
|
80273
80914
|
},
|
|
80274
80915
|
decisions: {
|
|
@@ -80715,6 +81356,45 @@ var TopologyStore = class {
|
|
|
80715
81356
|
`);
|
|
80716
81357
|
logger.info("Migration: rebuilt subprojects with project_root column, old data cleared");
|
|
80717
81358
|
}
|
|
81359
|
+
this.runOnce("clean_duplicate_contracts_v1", () => {
|
|
81360
|
+
const services = this.db.prepare(
|
|
81361
|
+
`SELECT DISTINCT service_id FROM api_contracts WHERE contract_type = 'framework_routes'`
|
|
81362
|
+
).all();
|
|
81363
|
+
let deletedContracts = 0;
|
|
81364
|
+
let deletedEndpoints = 0;
|
|
81365
|
+
for (const { service_id } of services) {
|
|
81366
|
+
const latest = this.db.prepare(
|
|
81367
|
+
`SELECT id FROM api_contracts WHERE service_id = ? AND contract_type = 'framework_routes' ORDER BY id DESC LIMIT 1`
|
|
81368
|
+
).get(service_id);
|
|
81369
|
+
if (!latest) continue;
|
|
81370
|
+
const result = this.db.prepare(
|
|
81371
|
+
`DELETE FROM api_contracts WHERE service_id = ? AND contract_type = 'framework_routes' AND id != ?`
|
|
81372
|
+
).run(service_id, latest.id);
|
|
81373
|
+
deletedContracts += result.changes;
|
|
81374
|
+
const httpMethods = ["GET", "POST", "PUT", "PATCH", "DELETE", "HEAD", "OPTIONS", "ANY"];
|
|
81375
|
+
const placeholders = httpMethods.map(() => "?").join(",");
|
|
81376
|
+
const epResult = this.db.prepare(
|
|
81377
|
+
`DELETE FROM api_endpoints WHERE contract_id = ? AND method IS NOT NULL AND method NOT IN (${placeholders})`
|
|
81378
|
+
).run(latest.id, ...httpMethods);
|
|
81379
|
+
deletedEndpoints += epResult.changes;
|
|
81380
|
+
}
|
|
81381
|
+
if (deletedContracts > 0 || deletedEndpoints > 0) {
|
|
81382
|
+
logger.info({ deletedContracts, deletedEndpoints }, "Migration: cleaned duplicate contracts and non-HTTP endpoints");
|
|
81383
|
+
}
|
|
81384
|
+
});
|
|
81385
|
+
this.runOnce("rebuild_cross_service_edges_v1", () => {
|
|
81386
|
+
const result = this.db.prepare("DELETE FROM cross_service_edges").run();
|
|
81387
|
+
if (result.changes > 0) {
|
|
81388
|
+
logger.info({ deleted: result.changes }, "Migration: cleared stale cross-service edges for rebuild");
|
|
81389
|
+
}
|
|
81390
|
+
});
|
|
81391
|
+
}
|
|
81392
|
+
/** Run a migration block exactly once, tracked by key in topology_meta. */
|
|
81393
|
+
runOnce(key, fn2) {
|
|
81394
|
+
const existing = this.db.prepare("SELECT value FROM topology_meta WHERE key = ?").get(key);
|
|
81395
|
+
if (existing) return;
|
|
81396
|
+
fn2();
|
|
81397
|
+
this.db.prepare("INSERT OR REPLACE INTO topology_meta (key, value) VALUES (?, ?)").run(key, (/* @__PURE__ */ new Date()).toISOString());
|
|
80718
81398
|
}
|
|
80719
81399
|
close() {
|
|
80720
81400
|
this.db.close();
|
|
@@ -80760,6 +81440,15 @@ var TopologyStore = class {
|
|
|
80760
81440
|
getAllServices() {
|
|
80761
81441
|
return this.db.prepare("SELECT * FROM services ORDER BY name").all();
|
|
80762
81442
|
}
|
|
81443
|
+
updateServiceGroup(serviceId, projectGroup) {
|
|
81444
|
+
this.db.prepare("UPDATE services SET project_group = ? WHERE id = ?").run(projectGroup, serviceId);
|
|
81445
|
+
}
|
|
81446
|
+
getServicesWithEndpointCounts() {
|
|
81447
|
+
return this.db.prepare(`
|
|
81448
|
+
SELECT s.*, (SELECT COUNT(*) FROM api_endpoints WHERE service_id = s.id) as endpoint_count
|
|
81449
|
+
FROM services s ORDER BY s.project_group NULLS LAST, s.name
|
|
81450
|
+
`).all();
|
|
81451
|
+
}
|
|
80763
81452
|
deleteService(id) {
|
|
80764
81453
|
this.db.prepare("DELETE FROM services WHERE id = ?").run(id);
|
|
80765
81454
|
}
|
|
@@ -81038,13 +81727,29 @@ var TopologyStore = class {
|
|
|
81038
81727
|
"SELECT * FROM client_calls WHERE matched_endpoint_id IS NULL"
|
|
81039
81728
|
).all();
|
|
81040
81729
|
const endpoints = this.getAllEndpoints();
|
|
81730
|
+
const services = this.getAllServices();
|
|
81731
|
+
const serviceGroup = /* @__PURE__ */ new Map();
|
|
81732
|
+
for (const svc of services) {
|
|
81733
|
+
serviceGroup.set(svc.id, svc.project_group ?? null);
|
|
81734
|
+
}
|
|
81735
|
+
const repoGroup = /* @__PURE__ */ new Map();
|
|
81736
|
+
const allRepos2 = this.getAllSubprojects();
|
|
81737
|
+
for (const repo of allRepos2) {
|
|
81738
|
+
const svc = services.find((s) => s.repo_root === repo.repo_root);
|
|
81739
|
+
repoGroup.set(repo.id, svc?.project_group ?? null);
|
|
81740
|
+
}
|
|
81041
81741
|
let linked = 0;
|
|
81042
81742
|
const updateStmt = this.db.prepare(
|
|
81043
81743
|
"UPDATE client_calls SET matched_endpoint_id = ?, target_repo_id = ?, confidence = ? WHERE id = ?"
|
|
81044
81744
|
);
|
|
81045
81745
|
this.db.transaction(() => {
|
|
81046
81746
|
for (const call of unlinked) {
|
|
81047
|
-
const
|
|
81747
|
+
const sourceGroup = repoGroup.get(call.source_repo_id);
|
|
81748
|
+
const candidateEndpoints = sourceGroup ? endpoints.filter((ep) => {
|
|
81749
|
+
const epGroup = serviceGroup.get(ep.service_id);
|
|
81750
|
+
return epGroup === sourceGroup || !epGroup || !sourceGroup;
|
|
81751
|
+
}) : endpoints;
|
|
81752
|
+
const match = findBestEndpointMatch(call.url_pattern, call.method, candidateEndpoints);
|
|
81048
81753
|
if (match) {
|
|
81049
81754
|
const svc = this.db.prepare("SELECT repo_root FROM services WHERE id = ?").get(match.service_id);
|
|
81050
81755
|
const targetRepo = svc ? this.db.prepare("SELECT id FROM subprojects WHERE repo_root = ?").get(svc.repo_root) : void 0;
|
|
@@ -81466,7 +82171,7 @@ var DecisionStore = class {
|
|
|
81466
82171
|
};
|
|
81467
82172
|
|
|
81468
82173
|
// src/server/server.ts
|
|
81469
|
-
var PKG_VERSION2 = true ? "1.
|
|
82174
|
+
var PKG_VERSION2 = true ? "1.23.0" : "0.0.0-dev";
|
|
81470
82175
|
function j2(value) {
|
|
81471
82176
|
return JSON.stringify(value, (_key, val) => val === null || val === void 0 ? void 0 : val);
|
|
81472
82177
|
}
|
|
@@ -81891,11 +82596,11 @@ var PluginRegistry = class {
|
|
|
81891
82596
|
// src/config.ts
|
|
81892
82597
|
import { cosmiconfig } from "cosmiconfig";
|
|
81893
82598
|
import { z as z15 } from "zod";
|
|
81894
|
-
import
|
|
82599
|
+
import fs56 from "fs";
|
|
81895
82600
|
init_logger();
|
|
81896
82601
|
|
|
81897
82602
|
// src/config-jsonc.ts
|
|
81898
|
-
import
|
|
82603
|
+
import fs55 from "fs";
|
|
81899
82604
|
import { modify, applyEdits, parse as parse2 } from "jsonc-parser";
|
|
81900
82605
|
init_logger();
|
|
81901
82606
|
|
|
@@ -81917,7 +82622,7 @@ var FrameworkConfigSchema = z15.object({
|
|
|
81917
82622
|
}).optional();
|
|
81918
82623
|
var AiConfigSchema = z15.object({
|
|
81919
82624
|
enabled: z15.boolean().default(false),
|
|
81920
|
-
provider: z15.enum(["onnx", "ollama", "openai"]).default("onnx"),
|
|
82625
|
+
provider: z15.enum(["onnx", "ollama", "openai", "anthropic", "lmstudio", "gemini", "mistral", "deepseek", "groq", "together", "xai"]).default("onnx"),
|
|
81921
82626
|
base_url: z15.string().optional(),
|
|
81922
82627
|
api_key: z15.string().optional(),
|
|
81923
82628
|
inference_model: z15.string().optional(),
|
|
@@ -82129,9 +82834,9 @@ var TraceMcpConfigSchema = z15.object({
|
|
|
82129
82834
|
children: z15.array(z15.string()).optional()
|
|
82130
82835
|
});
|
|
82131
82836
|
function loadGlobalConfigRaw() {
|
|
82132
|
-
if (!
|
|
82837
|
+
if (!fs56.existsSync(GLOBAL_CONFIG_PATH)) return {};
|
|
82133
82838
|
try {
|
|
82134
|
-
return JSON.parse(stripJsonComments(
|
|
82839
|
+
return JSON.parse(stripJsonComments(fs56.readFileSync(GLOBAL_CONFIG_PATH, "utf-8")));
|
|
82135
82840
|
} catch {
|
|
82136
82841
|
return {};
|
|
82137
82842
|
}
|