ctxloom-pro 1.7.5 → 1.7.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md
CHANGED
|
@@ -69,7 +69,7 @@ The full first-run flow is **one install + one trial + one init per project.** E
|
|
|
69
69
|
npm install -g ctxloom-pro
|
|
70
70
|
```
|
|
71
71
|
|
|
72
|
-
> **For local trial / dev use the unpinned command above is fine.** For unattended CI usage, pin to the exact version (`ctxloom-pro@1.7.
|
|
72
|
+
> **For local trial / dev use the unpinned command above is fine.** For unattended CI usage, pin to the exact version (`ctxloom-pro@1.7.7`) so future CLI releases don't silently desync your agent-spec coverage — see the workflow example below.
|
|
73
73
|
|
|
74
74
|
### 2 — Start your free trial (once per email)
|
|
75
75
|
|
|
@@ -383,7 +383,7 @@ jobs:
|
|
|
383
383
|
# Exact pin (not `@^1`) so future CLI releases that add/remove MCP
|
|
384
384
|
# tools don't silently desync your reviewer-agent specs. Bump on
|
|
385
385
|
# every release; see CHANGELOG.md for the live version table.
|
|
386
|
-
- run: npm install -g ctxloom-pro@1.7.
|
|
386
|
+
- run: npm install -g ctxloom-pro@1.7.7
|
|
387
387
|
- run: ctxloom index
|
|
388
388
|
- run: ctxloom rules check --json
|
|
389
389
|
```
|
|
@@ -2929,7 +2929,7 @@ var CallGraphIndex = class _CallGraphIndex {
|
|
|
2929
2929
|
var TS_EXTENSIONS2 = /* @__PURE__ */ new Set([".ts", ".tsx", ".js", ".jsx", ".mjs", ".vue"]);
|
|
2930
2930
|
var PY_EXTENSIONS = /* @__PURE__ */ new Set([".py", ".ipynb"]);
|
|
2931
2931
|
var AST_EXTENSIONS = /* @__PURE__ */ new Set([".ts", ".tsx", ".js", ".jsx", ".mjs", ".py", ".go", ".rs", ".java", ".cs", ".rb", ".kt", ".kts", ".swift", ".ipynb", ".php", ".dart"]);
|
|
2932
|
-
var CTXLOOM_VERSION = "1.7.
|
|
2932
|
+
var CTXLOOM_VERSION = "1.7.7".length > 0 ? "1.7.7" : "dev";
|
|
2933
2933
|
var SNAPSHOT_SCHEMA_VERSION = 2;
|
|
2934
2934
|
function compareCtxloomVersions(snapshotVer, currentVer) {
|
|
2935
2935
|
if (snapshotVer === currentVer) return "same";
|
|
@@ -3112,6 +3112,7 @@ var DependencyGraph = class {
|
|
|
3112
3112
|
});
|
|
3113
3113
|
this.symbolIndex.set(node.name, existing);
|
|
3114
3114
|
}
|
|
3115
|
+
this.indexClassMethods(node, relPath);
|
|
3115
3116
|
}
|
|
3116
3117
|
if (TS_EXTENSIONS2.has(ext)) {
|
|
3117
3118
|
const callEdges = await this.parser.parseAllCallEdges(absPath);
|
|
@@ -3306,6 +3307,19 @@ var DependencyGraph = class {
|
|
|
3306
3307
|
logger.warn("Graph snapshot hot-reload skipped (snapshot invalid or version-stale)");
|
|
3307
3308
|
}
|
|
3308
3309
|
}
|
|
3310
|
+
/**
|
|
3311
|
+
* Absolute root directory this graph was built/loaded against.
|
|
3312
|
+
*
|
|
3313
|
+
* Tools that read file CONTENTS off disk (full-text scan, refactor
|
|
3314
|
+
* preview/apply) must join relpaths against THIS root, not against a
|
|
3315
|
+
* server-level default like ctx.projectRoot — otherwise a call that
|
|
3316
|
+
* passes an explicit project_root different from the default reads
|
|
3317
|
+
* from the wrong directory and silently finds nothing. Returns '' if
|
|
3318
|
+
* the graph was never built (defensive; callers should have a graph).
|
|
3319
|
+
*/
|
|
3320
|
+
getRootDir() {
|
|
3321
|
+
return this.rootDir;
|
|
3322
|
+
}
|
|
3309
3323
|
/**
|
|
3310
3324
|
* Get files that the given file directly imports.
|
|
3311
3325
|
*/
|
|
@@ -3318,6 +3332,36 @@ var DependencyGraph = class {
|
|
|
3318
3332
|
getImporters(fileRel) {
|
|
3319
3333
|
return Array.from(this.reverseEdges.get(fileRel) ?? []);
|
|
3320
3334
|
}
|
|
3335
|
+
/**
|
|
3336
|
+
* Register each class method as its own symbol-index entry.
|
|
3337
|
+
*
|
|
3338
|
+
* TS/JS class methods are parsed as `methodRanges` on the class node,
|
|
3339
|
+
* not as standalone `method` nodes — so the `node.type === 'method'`
|
|
3340
|
+
* branch in the symbol-indexing loops never fired for them. That left
|
|
3341
|
+
* methods (e.g. DependencyGraph.getRootDir) unfindable by
|
|
3342
|
+
* `lookupSymbol`, which is why `ctx_get_call_graph {symbol: aMethod}`
|
|
3343
|
+
* returned "Symbol not found" even though the call-graph snapshot had
|
|
3344
|
+
* edges for it. Indexing methods here closes that gap.
|
|
3345
|
+
*
|
|
3346
|
+
* No-op for nodes without methodRanges (functions, imports, etc.).
|
|
3347
|
+
*/
|
|
3348
|
+
indexClassMethods(node, relPath) {
|
|
3349
|
+
if (!node.methodRanges) return;
|
|
3350
|
+
for (const m of node.methodRanges) {
|
|
3351
|
+
if (!m.name) continue;
|
|
3352
|
+
const existing = this.symbolIndex.get(m.name) ?? [];
|
|
3353
|
+
existing.push({
|
|
3354
|
+
filePath: relPath,
|
|
3355
|
+
type: "method",
|
|
3356
|
+
signature: `method ${m.name}`,
|
|
3357
|
+
// MethodRange only carries the signature line; use it as the
|
|
3358
|
+
// start and fall back to the enclosing class's end for the range.
|
|
3359
|
+
startLine: m.signatureLine,
|
|
3360
|
+
endLine: node.endLine ?? m.signatureLine
|
|
3361
|
+
});
|
|
3362
|
+
this.symbolIndex.set(m.name, existing);
|
|
3363
|
+
}
|
|
3364
|
+
}
|
|
3321
3365
|
/**
|
|
3322
3366
|
* Look up a symbol by name. Returns all definitions across files.
|
|
3323
3367
|
*/
|
|
@@ -3505,6 +3549,7 @@ var DependencyGraph = class {
|
|
|
3505
3549
|
});
|
|
3506
3550
|
this.symbolIndex.set(node.name, existing);
|
|
3507
3551
|
}
|
|
3552
|
+
this.indexClassMethods(node, relPath);
|
|
3508
3553
|
}
|
|
3509
3554
|
if (TS_EXTENSIONS2.has(ext)) {
|
|
3510
3555
|
const callEdges = await this.parser.parseAllCallEdges(absPath);
|
|
@@ -12290,7 +12335,7 @@ function resolveTelemetryLevel() {
|
|
|
12290
12335
|
}
|
|
12291
12336
|
var TELEMETRY_LEVEL = resolveTelemetryLevel();
|
|
12292
12337
|
var TELEMETRY_DISABLED = TELEMETRY_LEVEL === "off";
|
|
12293
|
-
var CTXLOOM_VERSION2 = "1.7.
|
|
12338
|
+
var CTXLOOM_VERSION2 = "1.7.7".length > 0 ? "1.7.7" : "dev";
|
|
12294
12339
|
var POSTHOG_HOST = "https://eu.i.posthog.com";
|
|
12295
12340
|
var POSTHOG_KEY = process.env["POSTHOG_API_KEY"] ?? (true ? "phc_CiDkmFLcZ2K6uCpcoSUQLmFrnnUvsyXGhSxopX5TVKE6" : "");
|
|
12296
12341
|
var SENTRY_DSN = process.env["SENTRY_DSN"] ?? (true ? "https://81c94a0f04a8e242dee493ac1e17f733@o4508531702497280.ingest.de.sentry.io/4511256875368528" : "");
|
|
@@ -2705,7 +2705,7 @@ var CallGraphIndex = class _CallGraphIndex {
|
|
|
2705
2705
|
var TS_EXTENSIONS2 = /* @__PURE__ */ new Set([".ts", ".tsx", ".js", ".jsx", ".mjs", ".vue"]);
|
|
2706
2706
|
var PY_EXTENSIONS = /* @__PURE__ */ new Set([".py", ".ipynb"]);
|
|
2707
2707
|
var AST_EXTENSIONS = /* @__PURE__ */ new Set([".ts", ".tsx", ".js", ".jsx", ".mjs", ".py", ".go", ".rs", ".java", ".cs", ".rb", ".kt", ".kts", ".swift", ".ipynb", ".php", ".dart"]);
|
|
2708
|
-
var CTXLOOM_VERSION = "1.7.
|
|
2708
|
+
var CTXLOOM_VERSION = "1.7.7".length > 0 ? "1.7.7" : "dev";
|
|
2709
2709
|
var SNAPSHOT_SCHEMA_VERSION = 2;
|
|
2710
2710
|
function compareCtxloomVersions(snapshotVer, currentVer) {
|
|
2711
2711
|
if (snapshotVer === currentVer) return "same";
|
|
@@ -2888,6 +2888,7 @@ var DependencyGraph = class {
|
|
|
2888
2888
|
});
|
|
2889
2889
|
this.symbolIndex.set(node.name, existing);
|
|
2890
2890
|
}
|
|
2891
|
+
this.indexClassMethods(node, relPath);
|
|
2891
2892
|
}
|
|
2892
2893
|
if (TS_EXTENSIONS2.has(ext)) {
|
|
2893
2894
|
const callEdges = await this.parser.parseAllCallEdges(absPath);
|
|
@@ -3082,6 +3083,19 @@ var DependencyGraph = class {
|
|
|
3082
3083
|
logger.warn("Graph snapshot hot-reload skipped (snapshot invalid or version-stale)");
|
|
3083
3084
|
}
|
|
3084
3085
|
}
|
|
3086
|
+
/**
|
|
3087
|
+
* Absolute root directory this graph was built/loaded against.
|
|
3088
|
+
*
|
|
3089
|
+
* Tools that read file CONTENTS off disk (full-text scan, refactor
|
|
3090
|
+
* preview/apply) must join relpaths against THIS root, not against a
|
|
3091
|
+
* server-level default like ctx.projectRoot — otherwise a call that
|
|
3092
|
+
* passes an explicit project_root different from the default reads
|
|
3093
|
+
* from the wrong directory and silently finds nothing. Returns '' if
|
|
3094
|
+
* the graph was never built (defensive; callers should have a graph).
|
|
3095
|
+
*/
|
|
3096
|
+
getRootDir() {
|
|
3097
|
+
return this.rootDir;
|
|
3098
|
+
}
|
|
3085
3099
|
/**
|
|
3086
3100
|
* Get files that the given file directly imports.
|
|
3087
3101
|
*/
|
|
@@ -3094,6 +3108,36 @@ var DependencyGraph = class {
|
|
|
3094
3108
|
getImporters(fileRel) {
|
|
3095
3109
|
return Array.from(this.reverseEdges.get(fileRel) ?? []);
|
|
3096
3110
|
}
|
|
3111
|
+
/**
|
|
3112
|
+
* Register each class method as its own symbol-index entry.
|
|
3113
|
+
*
|
|
3114
|
+
* TS/JS class methods are parsed as `methodRanges` on the class node,
|
|
3115
|
+
* not as standalone `method` nodes — so the `node.type === 'method'`
|
|
3116
|
+
* branch in the symbol-indexing loops never fired for them. That left
|
|
3117
|
+
* methods (e.g. DependencyGraph.getRootDir) unfindable by
|
|
3118
|
+
* `lookupSymbol`, which is why `ctx_get_call_graph {symbol: aMethod}`
|
|
3119
|
+
* returned "Symbol not found" even though the call-graph snapshot had
|
|
3120
|
+
* edges for it. Indexing methods here closes that gap.
|
|
3121
|
+
*
|
|
3122
|
+
* No-op for nodes without methodRanges (functions, imports, etc.).
|
|
3123
|
+
*/
|
|
3124
|
+
indexClassMethods(node, relPath) {
|
|
3125
|
+
if (!node.methodRanges) return;
|
|
3126
|
+
for (const m of node.methodRanges) {
|
|
3127
|
+
if (!m.name) continue;
|
|
3128
|
+
const existing = this.symbolIndex.get(m.name) ?? [];
|
|
3129
|
+
existing.push({
|
|
3130
|
+
filePath: relPath,
|
|
3131
|
+
type: "method",
|
|
3132
|
+
signature: `method ${m.name}`,
|
|
3133
|
+
// MethodRange only carries the signature line; use it as the
|
|
3134
|
+
// start and fall back to the enclosing class's end for the range.
|
|
3135
|
+
startLine: m.signatureLine,
|
|
3136
|
+
endLine: node.endLine ?? m.signatureLine
|
|
3137
|
+
});
|
|
3138
|
+
this.symbolIndex.set(m.name, existing);
|
|
3139
|
+
}
|
|
3140
|
+
}
|
|
3097
3141
|
/**
|
|
3098
3142
|
* Look up a symbol by name. Returns all definitions across files.
|
|
3099
3143
|
*/
|
|
@@ -3281,6 +3325,7 @@ var DependencyGraph = class {
|
|
|
3281
3325
|
});
|
|
3282
3326
|
this.symbolIndex.set(node.name, existing);
|
|
3283
3327
|
}
|
|
3328
|
+
this.indexClassMethods(node, relPath);
|
|
3284
3329
|
}
|
|
3285
3330
|
if (TS_EXTENSIONS2.has(ext)) {
|
|
3286
3331
|
const callEdges = await this.parser.parseAllCallEdges(absPath);
|
|
@@ -6371,10 +6416,11 @@ function registerContextPacketTool(registry, ctx) {
|
|
|
6371
6416
|
const primaryContent = pathValidator.readFile(parsed.target_file);
|
|
6372
6417
|
const imports = graph.getImports(parsed.target_file);
|
|
6373
6418
|
const importers = graph.getImporters(parsed.target_file);
|
|
6419
|
+
const rootDir = graph.getRootDir() || ctx.projectRoot;
|
|
6374
6420
|
const skeletons = await Promise.all(
|
|
6375
6421
|
imports.map(async (dep) => {
|
|
6376
6422
|
try {
|
|
6377
|
-
const absDep = path15.resolve(
|
|
6423
|
+
const absDep = path15.resolve(rootDir, dep);
|
|
6378
6424
|
const sk = await skeletonizer.skeletonize(absDep);
|
|
6379
6425
|
return `
|
|
6380
6426
|
<!-- ${dep} -->
|
|
@@ -7025,15 +7071,16 @@ function registerBlastRadiusTool(registry, ctx) {
|
|
|
7025
7071
|
},
|
|
7026
7072
|
async (args) => {
|
|
7027
7073
|
const { changed_files, depth, use_git, detail_level, project_root } = Schema8.parse(args);
|
|
7074
|
+
const graph = await ctx.getGraph(project_root);
|
|
7075
|
+
const gitRoot = graph.getRootDir() || ctx.projectRoot;
|
|
7028
7076
|
let files = changed_files ?? [];
|
|
7029
7077
|
if (files.length === 0 && use_git) {
|
|
7030
|
-
files = await detectChangedFiles(
|
|
7078
|
+
files = await detectChangedFiles(gitRoot);
|
|
7031
7079
|
}
|
|
7032
7080
|
if (files.length === 0) {
|
|
7033
7081
|
return '<blast_radius changed_files="0">\n <!-- No changed files detected -->\n</blast_radius>';
|
|
7034
7082
|
}
|
|
7035
|
-
const
|
|
7036
|
-
const result = await computeBlastRadius({ changedFiles: files, depth, projectRoot: ctx.projectRoot, graph });
|
|
7083
|
+
const result = await computeBlastRadius({ changedFiles: files, depth, projectRoot: gitRoot, graph });
|
|
7037
7084
|
const report = getImpactRadius({ graph, overlay: ctx.overlay, changedFiles: files, depth });
|
|
7038
7085
|
return buildBlastRadiusXml(result, depth, detail_level, report.historicalCoupling);
|
|
7039
7086
|
}
|
|
@@ -7816,10 +7863,10 @@ async function getFileDiff(projectRoot, file) {
|
|
|
7816
7863
|
return "";
|
|
7817
7864
|
}
|
|
7818
7865
|
}
|
|
7819
|
-
async function trySkeletonize(ctx, filePath, projectRoot) {
|
|
7866
|
+
async function trySkeletonize(ctx, filePath, projectRoot, rootDir) {
|
|
7820
7867
|
try {
|
|
7821
7868
|
const sk = await ctx.getSkeletonizer(projectRoot);
|
|
7822
|
-
const absPath = `${
|
|
7869
|
+
const absPath = `${rootDir}/${filePath}`;
|
|
7823
7870
|
return await sk.skeletonize(absPath);
|
|
7824
7871
|
} catch {
|
|
7825
7872
|
return "";
|
|
@@ -7856,13 +7903,15 @@ function registerGitDiffReviewTool(registry, ctx) {
|
|
|
7856
7903
|
async (args) => {
|
|
7857
7904
|
const { changed_files, depth, use_git, include_skeletons, max_diff_lines, project_root } = Schema17.parse(args);
|
|
7858
7905
|
const validator = ctx.getPathValidator(project_root);
|
|
7906
|
+
const graph = await ctx.getGraph(project_root);
|
|
7907
|
+
const gitRoot = graph.getRootDir() || ctx.projectRoot;
|
|
7859
7908
|
let files = (changed_files ?? []).filter((f) => validator.isWithinRoot(f));
|
|
7860
7909
|
if (files.length === 0 && use_git) {
|
|
7861
7910
|
try {
|
|
7862
7911
|
const { stdout } = await execFileAsync(
|
|
7863
7912
|
"git",
|
|
7864
7913
|
["diff", "HEAD~1", "--name-only"],
|
|
7865
|
-
{ cwd:
|
|
7914
|
+
{ cwd: gitRoot, maxBuffer: 10 * 1024 * 1024 }
|
|
7866
7915
|
);
|
|
7867
7916
|
files = stdout.trim().split("\n").filter(Boolean);
|
|
7868
7917
|
} catch {
|
|
@@ -7886,26 +7935,25 @@ function registerGitDiffReviewTool(registry, ctx) {
|
|
|
7886
7935
|
<!-- No changed files detected -->
|
|
7887
7936
|
</git_diff_review>`);
|
|
7888
7937
|
}
|
|
7889
|
-
const graph = await ctx.getGraph(project_root);
|
|
7890
7938
|
const blast = await computeBlastRadius({
|
|
7891
7939
|
changedFiles: files,
|
|
7892
7940
|
depth,
|
|
7893
|
-
projectRoot:
|
|
7941
|
+
projectRoot: gitRoot,
|
|
7894
7942
|
graph
|
|
7895
7943
|
});
|
|
7896
7944
|
const changedFileData = await Promise.all(files.map(async (file) => {
|
|
7897
|
-
const rawDiff = use_git ? await getFileDiff(
|
|
7945
|
+
const rawDiff = use_git ? await getFileDiff(gitRoot, file) : "";
|
|
7898
7946
|
const diffLines = rawDiff ? rawDiff.split("\n") : [];
|
|
7899
7947
|
const truncated = diffLines.length > max_diff_lines;
|
|
7900
7948
|
const diffContent = truncated ? [...diffLines.slice(0, max_diff_lines), `... (${diffLines.length - max_diff_lines} more lines)`].join("\n") : rawDiff;
|
|
7901
|
-
const skeleton = include_skeletons ? await trySkeletonize(ctx, file, project_root) : "";
|
|
7949
|
+
const skeleton = include_skeletons ? await trySkeletonize(ctx, file, project_root, gitRoot) : "";
|
|
7902
7950
|
return { file, diffLines, truncated, diffContent, skeleton };
|
|
7903
7951
|
}));
|
|
7904
7952
|
const skeletonLimit = 5;
|
|
7905
7953
|
const directImporterSkeletons = await Promise.all(
|
|
7906
7954
|
blast.directImporters.map(async (file, i) => ({
|
|
7907
7955
|
file,
|
|
7908
|
-
skeleton: include_skeletons && i < skeletonLimit ? await trySkeletonize(ctx, file, project_root) : ""
|
|
7956
|
+
skeleton: include_skeletons && i < skeletonLimit ? await trySkeletonize(ctx, file, project_root, gitRoot) : ""
|
|
7909
7957
|
}))
|
|
7910
7958
|
);
|
|
7911
7959
|
const render2 = (withSkeletons, withTransitive) => {
|
|
@@ -8049,8 +8097,9 @@ function registerRefactorPreviewTool(registry, ctx) {
|
|
|
8049
8097
|
const candidates = Array.from(candidateSet).slice(0, max_files);
|
|
8050
8098
|
const fileChanges = [];
|
|
8051
8099
|
let totalOccurrences = 0;
|
|
8100
|
+
const rootDir = graph.getRootDir() || ctx.projectRoot;
|
|
8052
8101
|
for (const relPath of candidates) {
|
|
8053
|
-
const absPath = path18.join(
|
|
8102
|
+
const absPath = path18.join(rootDir, relPath);
|
|
8054
8103
|
const occurrences = scanFile(absPath, symbol, new_name);
|
|
8055
8104
|
if (occurrences.length > 0) {
|
|
8056
8105
|
fileChanges.push({ filePath: relPath, occurrences });
|
|
@@ -8567,8 +8616,9 @@ function registerApplyRefactorTool(registry, ctx) {
|
|
|
8567
8616
|
const candidates = Array.from(candidateSet).slice(0, max_files);
|
|
8568
8617
|
const results = [];
|
|
8569
8618
|
let totalOccurrences = 0;
|
|
8619
|
+
const rootDir = graph.getRootDir() || ctx.projectRoot;
|
|
8570
8620
|
for (const relPath of candidates) {
|
|
8571
|
-
const absPath = path20.join(
|
|
8621
|
+
const absPath = path20.join(rootDir, relPath);
|
|
8572
8622
|
const count = applyToFile(absPath, symbol, new_name, dry_run);
|
|
8573
8623
|
if (count > 0) {
|
|
8574
8624
|
results.push({ filePath: relPath, occurrences: count, written: !dry_run });
|
|
@@ -8659,14 +8709,15 @@ function registerDetectChangesTool(registry, ctx) {
|
|
|
8659
8709
|
},
|
|
8660
8710
|
async (args) => {
|
|
8661
8711
|
const { changed_files, use_git, detail_level, project_root } = Schema22.parse(args);
|
|
8712
|
+
const graph = await ctx.getGraph(project_root);
|
|
8713
|
+
const gitRoot = graph.getRootDir() || ctx.projectRoot;
|
|
8662
8714
|
let files = changed_files ?? [];
|
|
8663
8715
|
if (files.length === 0 && use_git) {
|
|
8664
|
-
files = await detectChangedFiles2(
|
|
8716
|
+
files = await detectChangedFiles2(gitRoot);
|
|
8665
8717
|
}
|
|
8666
8718
|
if (files.length === 0) {
|
|
8667
8719
|
return '<detect_changes count="0">\n <!-- No changed files detected -->\n</detect_changes>';
|
|
8668
8720
|
}
|
|
8669
|
-
const graph = await ctx.getGraph(project_root);
|
|
8670
8721
|
const { changedFiles: scored, summary } = detectChanges({
|
|
8671
8722
|
graph,
|
|
8672
8723
|
overlay: ctx.overlay,
|
|
@@ -8836,9 +8887,10 @@ function registerFullTextSearchTool(registry, ctx) {
|
|
|
8836
8887
|
}
|
|
8837
8888
|
const graph = await ctx.getGraph(project_root);
|
|
8838
8889
|
const files = graph.allFiles();
|
|
8890
|
+
const rootDir = graph.getRootDir() || ctx.projectRoot;
|
|
8839
8891
|
const keywordResults = [];
|
|
8840
8892
|
for (const relPath of files) {
|
|
8841
|
-
const absPath = path21.join(
|
|
8893
|
+
const absPath = path21.join(rootDir, relPath);
|
|
8842
8894
|
const hit = scanFile2(absPath, pattern, context_lines);
|
|
8843
8895
|
if (hit) {
|
|
8844
8896
|
keywordResults.push({
|
|
@@ -8939,14 +8991,15 @@ function registerSuggestedQuestionsTool(registry, ctx) {
|
|
|
8939
8991
|
},
|
|
8940
8992
|
async (args) => {
|
|
8941
8993
|
const { changed_files, use_git, project_root } = Schema24.parse(args);
|
|
8994
|
+
const graph = await ctx.getGraph(project_root);
|
|
8995
|
+
const gitRoot = graph.getRootDir() || ctx.projectRoot;
|
|
8942
8996
|
let files = changed_files ?? [];
|
|
8943
8997
|
if (files.length === 0 && use_git) {
|
|
8944
|
-
files = await detectChangedFiles3(
|
|
8998
|
+
files = await detectChangedFiles3(gitRoot);
|
|
8945
8999
|
}
|
|
8946
9000
|
if (files.length === 0) {
|
|
8947
9001
|
return '<suggested_questions count="1" changed_files="0"><question>No changed files detected. Are you on a git branch with commits?</question></suggested_questions>';
|
|
8948
9002
|
}
|
|
8949
|
-
const graph = await ctx.getGraph(project_root);
|
|
8950
9003
|
const questions = [];
|
|
8951
9004
|
const allImporters = /* @__PURE__ */ new Set();
|
|
8952
9005
|
const hubFiles = [];
|
|
@@ -9856,14 +9909,15 @@ function registerGetAffectedFlowsTool(registry, ctx) {
|
|
|
9856
9909
|
},
|
|
9857
9910
|
async (args) => {
|
|
9858
9911
|
const { changed_files, use_git, depth, max_flows, max_steps_per_flow, project_root } = Schema29.parse(args);
|
|
9912
|
+
const graph = await ctx.getGraph(project_root);
|
|
9913
|
+
const gitRoot = graph.getRootDir() || ctx.projectRoot;
|
|
9859
9914
|
let files = changed_files ?? [];
|
|
9860
9915
|
if (files.length === 0 && use_git) {
|
|
9861
|
-
files = await detectChangedFiles4(
|
|
9916
|
+
files = await detectChangedFiles4(gitRoot);
|
|
9862
9917
|
}
|
|
9863
9918
|
if (files.length === 0) {
|
|
9864
9919
|
return '<affected_flows changed_files="0" total_flows="0">\n <!-- No changed files detected -->\n</affected_flows>';
|
|
9865
9920
|
}
|
|
9866
|
-
const graph = await ctx.getGraph(project_root);
|
|
9867
9921
|
const callIdx = graph.getCallGraphIndex();
|
|
9868
9922
|
const changedSymbols = [];
|
|
9869
9923
|
for (const file of files) {
|
|
@@ -11088,7 +11142,7 @@ var TELEMETRY_DISABLED = TELEMETRY_LEVEL === "off";
|
|
|
11088
11142
|
function getTelemetryLevel() {
|
|
11089
11143
|
return TELEMETRY_LEVEL;
|
|
11090
11144
|
}
|
|
11091
|
-
var CTXLOOM_VERSION2 = "1.7.
|
|
11145
|
+
var CTXLOOM_VERSION2 = "1.7.7".length > 0 ? "1.7.7" : "dev";
|
|
11092
11146
|
var POSTHOG_HOST = "https://eu.i.posthog.com";
|
|
11093
11147
|
var POSTHOG_KEY = process.env["POSTHOG_API_KEY"] ?? (true ? "phc_CiDkmFLcZ2K6uCpcoSUQLmFrnnUvsyXGhSxopX5TVKE6" : "");
|
|
11094
11148
|
var SENTRY_DSN = process.env["SENTRY_DSN"] ?? (true ? "https://81c94a0f04a8e242dee493ac1e17f733@o4508531702497280.ingest.de.sentry.io/4511256875368528" : "");
|
|
@@ -12774,4 +12828,4 @@ export {
|
|
|
12774
12828
|
skillFilePath,
|
|
12775
12829
|
installHarness
|
|
12776
12830
|
};
|
|
12777
|
-
//# sourceMappingURL=chunk-
|
|
12831
|
+
//# sourceMappingURL=chunk-OEDNX3CV.js.map
|
package/dist/index.js
CHANGED
|
@@ -47,7 +47,7 @@ import {
|
|
|
47
47
|
validateDefaultRoot,
|
|
48
48
|
wrapWithIndexingEnvelope,
|
|
49
49
|
writeCODEOWNERS
|
|
50
|
-
} from "./chunk-
|
|
50
|
+
} from "./chunk-OEDNX3CV.js";
|
|
51
51
|
import {
|
|
52
52
|
addCtxloomToConfig,
|
|
53
53
|
detectInstalledClients
|
|
@@ -1068,7 +1068,7 @@ try {
|
|
|
1068
1068
|
} catch {
|
|
1069
1069
|
}
|
|
1070
1070
|
var args = process.argv.slice(2);
|
|
1071
|
-
var ctxloomVersion = "1.7.
|
|
1071
|
+
var ctxloomVersion = "1.7.7".length > 0 ? "1.7.7" : "dev";
|
|
1072
1072
|
if (args.includes("--version") || args.includes("-v")) {
|
|
1073
1073
|
process.stdout.write(`ctxloom ${ctxloomVersion}
|
|
1074
1074
|
`);
|
|
@@ -1163,7 +1163,7 @@ async function checkLicense() {
|
|
|
1163
1163
|
if (command !== void 0 && LICENSE_GATE_BYPASS_COMMANDS.has(command)) return;
|
|
1164
1164
|
const ciKey = process.env["CTXLOOM_LICENSE_KEY"];
|
|
1165
1165
|
if (ciKey) {
|
|
1166
|
-
const { ApiClient } = await import("./src-
|
|
1166
|
+
const { ApiClient } = await import("./src-HFPCEHYB.js");
|
|
1167
1167
|
const client = new ApiClient(process.env["CTXLOOM_API_BASE"]);
|
|
1168
1168
|
try {
|
|
1169
1169
|
const result = await client.validate(ciKey, "ci-ephemeral");
|
|
@@ -1556,7 +1556,7 @@ async function main() {
|
|
|
1556
1556
|
}
|
|
1557
1557
|
if (!skipHarness) {
|
|
1558
1558
|
process.stdout.write("\n");
|
|
1559
|
-
const { installHarness } = await import("./src-
|
|
1559
|
+
const { installHarness } = await import("./src-HFPCEHYB.js");
|
|
1560
1560
|
const h = installHarness({ cwd: initRoot, dryRun, force, extraHosts });
|
|
1561
1561
|
const harnessFiles = [
|
|
1562
1562
|
h.claudeMd,
|
|
@@ -1619,7 +1619,7 @@ async function main() {
|
|
|
1619
1619
|
process.exit(1);
|
|
1620
1620
|
}
|
|
1621
1621
|
if (alias !== void 0) {
|
|
1622
|
-
const { validateAlias } = await import("./src-
|
|
1622
|
+
const { validateAlias } = await import("./src-HFPCEHYB.js");
|
|
1623
1623
|
const v = validateAlias(alias);
|
|
1624
1624
|
if (!v.ok) {
|
|
1625
1625
|
console.error(`[ctxloom] Invalid alias: ${v.reason}`);
|
|
@@ -1978,7 +1978,7 @@ Suggested reviewers for ${files.length} file(s):`);
|
|
|
1978
1978
|
process.stderr.write("[ctxloom] --limit must be a non-negative integer (0 for unlimited)\n");
|
|
1979
1979
|
process.exit(2);
|
|
1980
1980
|
}
|
|
1981
|
-
const { loadRulesConfig, RulesChecker, formatText, formatJson, RulesConfigError } = await import("./src-
|
|
1981
|
+
const { loadRulesConfig, RulesChecker, formatText, formatJson, RulesConfigError } = await import("./src-HFPCEHYB.js");
|
|
1982
1982
|
let config;
|
|
1983
1983
|
try {
|
|
1984
1984
|
config = await loadRulesConfig(root);
|
|
@@ -2002,7 +2002,7 @@ Suggested reviewers for ${files.length} file(s):`);
|
|
|
2002
2002
|
}
|
|
2003
2003
|
let graph;
|
|
2004
2004
|
if (useSnapshot) {
|
|
2005
|
-
const { DependencyGraph: DG } = await import("./src-
|
|
2005
|
+
const { DependencyGraph: DG } = await import("./src-HFPCEHYB.js");
|
|
2006
2006
|
graph = new DG();
|
|
2007
2007
|
const loaded = await graph.loadSnapshotOnly(root);
|
|
2008
2008
|
if (!loaded) {
|
|
@@ -2011,7 +2011,7 @@ Suggested reviewers for ${files.length} file(s):`);
|
|
|
2011
2011
|
}
|
|
2012
2012
|
} else {
|
|
2013
2013
|
process.stderr.write("[ctxloom] Building dependency graph...\n");
|
|
2014
|
-
const { ASTParser: ASTParser2, DependencyGraph: DependencyGraph2 } = await import("./src-
|
|
2014
|
+
const { ASTParser: ASTParser2, DependencyGraph: DependencyGraph2 } = await import("./src-HFPCEHYB.js");
|
|
2015
2015
|
let parser;
|
|
2016
2016
|
try {
|
|
2017
2017
|
parser = new ASTParser2();
|
|
@@ -132,7 +132,7 @@ import {
|
|
|
132
132
|
wrapBlock,
|
|
133
133
|
wrapWithIndexingEnvelope,
|
|
134
134
|
writeCODEOWNERS
|
|
135
|
-
} from "./chunk-
|
|
135
|
+
} from "./chunk-OEDNX3CV.js";
|
|
136
136
|
import {
|
|
137
137
|
VectorStore
|
|
138
138
|
} from "./chunk-XQEQLXY5.js";
|
|
@@ -304,4 +304,4 @@ export {
|
|
|
304
304
|
wrapWithIndexingEnvelope,
|
|
305
305
|
writeCODEOWNERS
|
|
306
306
|
};
|
|
307
|
-
//# sourceMappingURL=src-
|
|
307
|
+
//# sourceMappingURL=src-HFPCEHYB.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ctxloom-pro",
|
|
3
|
-
"version": "1.7.
|
|
3
|
+
"version": "1.7.7",
|
|
4
4
|
"description": "ctxloom — The Universal Code Context Engine. A local-first MCP server providing intelligent code context via hybrid Vector + AST + Graph search with Skeletonization (92% token reduction).",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|