@massa-ai/mcp-client 1.17.0 → 1.18.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/config-cli.js +18 -29
- package/dist/index.js +697 -572
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -38111,6 +38111,16 @@ var init_index_manager = __esm(() => {
|
|
|
38111
38111
|
globAsync = glob;
|
|
38112
38112
|
});
|
|
38113
38113
|
|
|
38114
|
+
// ../../packages/core/dist/services/cache/lru-evict.js
|
|
38115
|
+
function evictOldest(cache, maxRetained) {
|
|
38116
|
+
while (cache.size > maxRetained) {
|
|
38117
|
+
const oldest = cache.keys().next().value;
|
|
38118
|
+
if (oldest === undefined)
|
|
38119
|
+
break;
|
|
38120
|
+
cache.delete(oldest);
|
|
38121
|
+
}
|
|
38122
|
+
}
|
|
38123
|
+
|
|
38114
38124
|
// ../../packages/core/dist/services/search/file-filter-cache.js
|
|
38115
38125
|
class FileFilterCache {
|
|
38116
38126
|
cache = new Map;
|
|
@@ -38179,18 +38189,7 @@ class FileFilterCache {
|
|
|
38179
38189
|
return parts.join("|");
|
|
38180
38190
|
}
|
|
38181
38191
|
evictOldest() {
|
|
38182
|
-
|
|
38183
|
-
let oldestTime = Infinity;
|
|
38184
|
-
for (const [key, entry] of this.cache.entries()) {
|
|
38185
|
-
if (entry.createdAt < oldestTime) {
|
|
38186
|
-
oldestTime = entry.createdAt;
|
|
38187
|
-
oldestKey = key;
|
|
38188
|
-
}
|
|
38189
|
-
}
|
|
38190
|
-
if (oldestKey) {
|
|
38191
|
-
this.cache.delete(oldestKey);
|
|
38192
|
-
logger.debug("Evicted oldest filter cache entry", { key: oldestKey });
|
|
38193
|
-
}
|
|
38192
|
+
evictOldest(this.cache, this.MAX_CACHE_SIZE);
|
|
38194
38193
|
}
|
|
38195
38194
|
invalidateProject(projectId) {
|
|
38196
38195
|
let removed = 0;
|
|
@@ -118540,7 +118539,7 @@ var init_memory_repository_factory = __esm(() => {
|
|
|
118540
118539
|
init_memory_repository_pg();
|
|
118541
118540
|
});
|
|
118542
118541
|
|
|
118543
|
-
// ../../packages/core/dist/services/graph/graph-store-pg.js
|
|
118542
|
+
// ../../packages/core/dist/services/memory-graph/graph-store-pg.js
|
|
118544
118543
|
function metadataForEdge(edge) {
|
|
118545
118544
|
return {
|
|
118546
118545
|
autoExtracted: edge.autoExtracted ?? false,
|
|
@@ -118856,7 +118855,7 @@ var init_graph_store_pg = __esm(() => {
|
|
|
118856
118855
|
graphStorePg = GraphStorePg.getInstance();
|
|
118857
118856
|
});
|
|
118858
118857
|
|
|
118859
|
-
// ../../packages/core/dist/services/graph/graph-store-factory.js
|
|
118858
|
+
// ../../packages/core/dist/services/memory-graph/graph-store-factory.js
|
|
118860
118859
|
function getGraphStore() {
|
|
118861
118860
|
if (cachedStore2)
|
|
118862
118861
|
return cachedStore2;
|
|
@@ -129055,6 +129054,133 @@ var init_pipeline = __esm(() => {
|
|
|
129055
129054
|
};
|
|
129056
129055
|
});
|
|
129057
129056
|
|
|
129057
|
+
// ../../packages/core/dist/services/indexing/execute-indexing.js
|
|
129058
|
+
async function executeIndexing(request) {
|
|
129059
|
+
const { jobId, projectId, projectPath, forceReindex, warmCache, warmupQueries, include_tests = false, managedRunLease, warmupCache: warmupCache2 } = request;
|
|
129060
|
+
const startTime = Date.now();
|
|
129061
|
+
try {
|
|
129062
|
+
indexJobTracker.updateStatus(jobId, "running");
|
|
129063
|
+
logger.info("Starting project indexing via ETL Pipeline", {
|
|
129064
|
+
jobId,
|
|
129065
|
+
projectPath,
|
|
129066
|
+
projectId,
|
|
129067
|
+
forceReindex,
|
|
129068
|
+
warmCache,
|
|
129069
|
+
include_tests
|
|
129070
|
+
});
|
|
129071
|
+
const etlResult = await EtlPipeline.getInstance().run({
|
|
129072
|
+
projectId,
|
|
129073
|
+
projectPath,
|
|
129074
|
+
jobId,
|
|
129075
|
+
forceReindex,
|
|
129076
|
+
include_tests,
|
|
129077
|
+
managedRunLease
|
|
129078
|
+
});
|
|
129079
|
+
const duration3 = Date.now() - startTime;
|
|
129080
|
+
logger.info("ETL Pipeline completed", {
|
|
129081
|
+
jobId,
|
|
129082
|
+
projectId,
|
|
129083
|
+
duration: duration3,
|
|
129084
|
+
filesIndexed: etlResult.filesIndexed,
|
|
129085
|
+
filesSkipped: etlResult.filesSkipped,
|
|
129086
|
+
chunksIndexed: etlResult.chunksIndexed,
|
|
129087
|
+
symbolsIndexed: etlResult.symbolsIndexed,
|
|
129088
|
+
errors: etlResult.errors,
|
|
129089
|
+
stageTimings: etlResult.stageTimings
|
|
129090
|
+
});
|
|
129091
|
+
if (warmCache) {
|
|
129092
|
+
logger.info("Starting cache warmup", { jobId, projectId });
|
|
129093
|
+
const warmupStats = await warmupCache2(projectId, projectPath, warmupQueries);
|
|
129094
|
+
logger.info("Cache warmup completed", { jobId, projectId, ...warmupStats });
|
|
129095
|
+
}
|
|
129096
|
+
indexJobTracker.updateProgress(jobId, etlResult.filesIndexed, etlResult.filesIndexed);
|
|
129097
|
+
await indexJobTracker.setResultAndFlush(jobId, {
|
|
129098
|
+
filesIndexed: etlResult.filesIndexed,
|
|
129099
|
+
chunksIndexed: etlResult.chunksIndexed,
|
|
129100
|
+
errors: etlResult.errors,
|
|
129101
|
+
duration: duration3,
|
|
129102
|
+
activatedGraphGenerationId: etlResult.activatedGraphGenerationId,
|
|
129103
|
+
parserDiagnostics: etlResult.parserDiagnostics
|
|
129104
|
+
});
|
|
129105
|
+
} catch (error51) {
|
|
129106
|
+
const duration3 = Date.now() - startTime;
|
|
129107
|
+
logger.error("Project indexing failed", error51, {
|
|
129108
|
+
jobId,
|
|
129109
|
+
projectPath,
|
|
129110
|
+
projectId,
|
|
129111
|
+
duration: duration3
|
|
129112
|
+
});
|
|
129113
|
+
indexJobTracker.setResult(jobId, {
|
|
129114
|
+
filesIndexed: 0,
|
|
129115
|
+
chunksIndexed: 0,
|
|
129116
|
+
errors: 1,
|
|
129117
|
+
duration: duration3
|
|
129118
|
+
}, error51.message);
|
|
129119
|
+
}
|
|
129120
|
+
}
|
|
129121
|
+
var init_execute_indexing = __esm(() => {
|
|
129122
|
+
init_dist();
|
|
129123
|
+
init_index_job_tracker();
|
|
129124
|
+
init_pipeline();
|
|
129125
|
+
});
|
|
129126
|
+
|
|
129127
|
+
// ../../packages/core/dist/services/indexing/acquire-indexing-lease.js
|
|
129128
|
+
async function acquireIndexingLease(request) {
|
|
129129
|
+
const { jobId, projectId } = request;
|
|
129130
|
+
const eventId = `index:${jobId}`;
|
|
129131
|
+
const managedRunRepo = ManagedRunRepositoryPg.getInstance();
|
|
129132
|
+
try {
|
|
129133
|
+
const beginOutcome = await managedRunRepo.begin({
|
|
129134
|
+
projectId,
|
|
129135
|
+
runKind: "indexing",
|
|
129136
|
+
eventId
|
|
129137
|
+
});
|
|
129138
|
+
if (beginOutcome.status === "busy") {
|
|
129139
|
+
indexJobTracker.setResult(jobId, { filesIndexed: 0, chunksIndexed: 0, errors: 0, duration: 0 }, `indexing_busy:${beginOutcome.activeRunId}`);
|
|
129140
|
+
return {
|
|
129141
|
+
status: "busy",
|
|
129142
|
+
activeRunId: beginOutcome.activeRunId,
|
|
129143
|
+
leaseExpiresAt: beginOutcome.leaseExpiresAt
|
|
129144
|
+
};
|
|
129145
|
+
}
|
|
129146
|
+
return { status: "acquired", lease: beginOutcome.lease };
|
|
129147
|
+
} catch (beginError) {
|
|
129148
|
+
logger.error("managed_runs begin failed", beginError, {
|
|
129149
|
+
jobId,
|
|
129150
|
+
projectId
|
|
129151
|
+
});
|
|
129152
|
+
indexJobTracker.setResult(jobId, { filesIndexed: 0, chunksIndexed: 0, errors: 1, duration: 0 }, `managed_runs_begin_failed:${beginError.message}`);
|
|
129153
|
+
return { status: "failed", message: beginError.message };
|
|
129154
|
+
}
|
|
129155
|
+
}
|
|
129156
|
+
var init_acquire_indexing_lease = __esm(() => {
|
|
129157
|
+
init_dist();
|
|
129158
|
+
init_index_job_tracker();
|
|
129159
|
+
init_managed_run_repository_pg();
|
|
129160
|
+
});
|
|
129161
|
+
|
|
129162
|
+
// ../../packages/core/dist/services/project-identity/project-root-identity.js
|
|
129163
|
+
import { realpath as realpath2 } from "fs/promises";
|
|
129164
|
+
import path17 from "path";
|
|
129165
|
+
async function canonicalizeProjectRoot(projectPath, canonicalize = realpath2) {
|
|
129166
|
+
return canonicalize(path17.resolve(projectPath));
|
|
129167
|
+
}
|
|
129168
|
+
async function assertProjectRootReuse(options) {
|
|
129169
|
+
if (!options.storedProjectPath || options.forceReindex)
|
|
129170
|
+
return;
|
|
129171
|
+
const canonicalize = options.canonicalize ?? realpath2;
|
|
129172
|
+
let storedCanonical;
|
|
129173
|
+
try {
|
|
129174
|
+
storedCanonical = await canonicalize(path17.resolve(options.storedProjectPath));
|
|
129175
|
+
} catch {
|
|
129176
|
+
storedCanonical = path17.resolve(options.storedProjectPath);
|
|
129177
|
+
}
|
|
129178
|
+
if (storedCanonical !== options.canonicalProjectPath) {
|
|
129179
|
+
throw new Error(`Project ID "${options.projectId}" already indexes canonical root ` + `"${storedCanonical}", not "${options.canonicalProjectPath}"; ` + "use forceReindex only after verifying ownership of the existing project");
|
|
129180
|
+
}
|
|
129181
|
+
}
|
|
129182
|
+
var init_project_root_identity = () => {};
|
|
129183
|
+
|
|
129058
129184
|
// ../../packages/core/dist/services/symbol/definition-lookup.js
|
|
129059
129185
|
function toSymbolIdentityResolution(result) {
|
|
129060
129186
|
switch (result.status) {
|
|
@@ -129790,16 +129916,16 @@ function detectRoutes(httpEdges, defs, opts = {}) {
|
|
|
129790
129916
|
const seen = new Set;
|
|
129791
129917
|
const out = [];
|
|
129792
129918
|
for (const e of httpEdges) {
|
|
129793
|
-
const
|
|
129794
|
-
if (!
|
|
129919
|
+
const path18 = e.route;
|
|
129920
|
+
if (!path18)
|
|
129795
129921
|
continue;
|
|
129796
129922
|
const method = (e.method ?? "ANY").toUpperCase();
|
|
129797
|
-
const key = method + " " +
|
|
129923
|
+
const key = method + " " + path18;
|
|
129798
129924
|
if (seen.has(key))
|
|
129799
129925
|
continue;
|
|
129800
129926
|
seen.add(key);
|
|
129801
129927
|
out.push({
|
|
129802
|
-
path:
|
|
129928
|
+
path: path18,
|
|
129803
129929
|
method: e.method,
|
|
129804
129930
|
file: e.fromFile,
|
|
129805
129931
|
handler: e.targetFqn ?? e.symbolName
|
|
@@ -129810,12 +129936,12 @@ function detectRoutes(httpEdges, defs, opts = {}) {
|
|
|
129810
129936
|
continue;
|
|
129811
129937
|
const parsed = parseRouteName(d.name);
|
|
129812
129938
|
const method = parsed?.method ?? "ANY";
|
|
129813
|
-
const
|
|
129814
|
-
const key = method + " " +
|
|
129939
|
+
const path18 = parsed?.path ?? d.name;
|
|
129940
|
+
const key = method + " " + path18;
|
|
129815
129941
|
if (seen.has(key))
|
|
129816
129942
|
continue;
|
|
129817
129943
|
seen.add(key);
|
|
129818
|
-
out.push({ path:
|
|
129944
|
+
out.push({ path: path18, method: parsed?.method, file: d.filePath, handler: d.name });
|
|
129819
129945
|
}
|
|
129820
129946
|
for (const d of defs) {
|
|
129821
129947
|
const parsed = parseRouteName(d.name);
|
|
@@ -130036,7 +130162,7 @@ __export(exports_symbol_graph_service, {
|
|
|
130036
130162
|
symbolGraphService: () => symbolGraphService,
|
|
130037
130163
|
SymbolGraphService: () => SymbolGraphService
|
|
130038
130164
|
});
|
|
130039
|
-
import
|
|
130165
|
+
import path18 from "path";
|
|
130040
130166
|
import fs8 from "fs/promises";
|
|
130041
130167
|
|
|
130042
130168
|
class SymbolGraphService {
|
|
@@ -130390,7 +130516,7 @@ class SymbolGraphService {
|
|
|
130390
130516
|
}
|
|
130391
130517
|
async resolveToAbsolute(relativePath, projectId) {
|
|
130392
130518
|
const root = await this.getProjectRoot(projectId);
|
|
130393
|
-
return root ?
|
|
130519
|
+
return root ? path18.resolve(root, relativePath) : relativePath;
|
|
130394
130520
|
}
|
|
130395
130521
|
async getProjectRoot(projectId) {
|
|
130396
130522
|
const cached2 = this.projectRootCache.get(projectId);
|
|
@@ -130410,12 +130536,7 @@ class SymbolGraphService {
|
|
|
130410
130536
|
return null;
|
|
130411
130537
|
}
|
|
130412
130538
|
evictOldestProjectRoot() {
|
|
130413
|
-
|
|
130414
|
-
const oldest = this.projectRootCache.keys().next().value;
|
|
130415
|
-
if (oldest === undefined)
|
|
130416
|
-
break;
|
|
130417
|
-
this.projectRootCache.delete(oldest);
|
|
130418
|
-
}
|
|
130539
|
+
evictOldest(this.projectRootCache, this.PROJECT_ROOT_CACHE_MAX_ENTRIES - 1);
|
|
130419
130540
|
}
|
|
130420
130541
|
clearProjectRoot(projectId) {
|
|
130421
130542
|
this.projectRootCache.delete(projectId);
|
|
@@ -130538,25 +130659,7 @@ var init_workspace_manager = __esm(() => {
|
|
|
130538
130659
|
});
|
|
130539
130660
|
|
|
130540
130661
|
// ../../packages/core/dist/tools/index_project.js
|
|
130541
|
-
import
|
|
130542
|
-
import path18 from "path";
|
|
130543
|
-
async function canonicalizeProjectRoot(projectPath, canonicalize = realpath2) {
|
|
130544
|
-
return canonicalize(path18.resolve(projectPath));
|
|
130545
|
-
}
|
|
130546
|
-
async function assertProjectRootReuse(options) {
|
|
130547
|
-
if (!options.storedProjectPath || options.forceReindex)
|
|
130548
|
-
return;
|
|
130549
|
-
const canonicalize = options.canonicalize ?? realpath2;
|
|
130550
|
-
let storedCanonical;
|
|
130551
|
-
try {
|
|
130552
|
-
storedCanonical = await canonicalize(path18.resolve(options.storedProjectPath));
|
|
130553
|
-
} catch {
|
|
130554
|
-
storedCanonical = path18.resolve(options.storedProjectPath);
|
|
130555
|
-
}
|
|
130556
|
-
if (storedCanonical !== options.canonicalProjectPath) {
|
|
130557
|
-
throw new Error(`Project ID "${options.projectId}" already indexes canonical root ` + `"${storedCanonical}", not "${options.canonicalProjectPath}"; ` + "use forceReindex only after verifying ownership of the existing project");
|
|
130558
|
-
}
|
|
130559
|
-
}
|
|
130662
|
+
import path19 from "path";
|
|
130560
130663
|
|
|
130561
130664
|
class IndexProjectTool {
|
|
130562
130665
|
name = "index_project";
|
|
@@ -130604,7 +130707,7 @@ class IndexProjectTool {
|
|
|
130604
130707
|
try {
|
|
130605
130708
|
await assertParserReadyForIndexing();
|
|
130606
130709
|
const canonicalProjectPath = await canonicalizeProjectRoot(projectPath);
|
|
130607
|
-
const finalProjectId = projectId ||
|
|
130710
|
+
const finalProjectId = projectId || path19.basename(canonicalProjectPath) || "default";
|
|
130608
130711
|
const existing = await workspaceManager.getWorkspace(finalProjectId);
|
|
130609
130712
|
await assertProjectRootReuse({
|
|
130610
130713
|
projectId: finalProjectId,
|
|
@@ -130618,40 +130721,42 @@ class IndexProjectTool {
|
|
|
130618
130721
|
projectPath: canonicalProjectPath,
|
|
130619
130722
|
projectId: finalProjectId
|
|
130620
130723
|
});
|
|
130621
|
-
const
|
|
130622
|
-
|
|
130623
|
-
|
|
130624
|
-
|
|
130625
|
-
|
|
130626
|
-
|
|
130627
|
-
|
|
130628
|
-
|
|
130629
|
-
|
|
130630
|
-
|
|
130631
|
-
|
|
130632
|
-
|
|
130633
|
-
|
|
130634
|
-
|
|
130635
|
-
|
|
130636
|
-
|
|
130637
|
-
|
|
130638
|
-
|
|
130639
|
-
|
|
130640
|
-
leaseExpiresAt: beginOutcome.leaseExpiresAt,
|
|
130641
|
-
message: "Another indexing run is active for this project. Poll get_index_status(activeRunId)."
|
|
130642
|
-
}
|
|
130643
|
-
};
|
|
130644
|
-
}
|
|
130645
|
-
lease = beginOutcome.lease;
|
|
130646
|
-
} catch (beginError) {
|
|
130647
|
-
logger.error("managed_runs begin failed", beginError, { jobId: job.jobId, projectId: finalProjectId });
|
|
130648
|
-
indexJobTracker.setResult(job.jobId, { filesIndexed: 0, chunksIndexed: 0, errors: 1, duration: 0 }, `managed_runs_begin_failed:${beginError.message}`);
|
|
130724
|
+
const leaseOutcome = await acquireIndexingLease({
|
|
130725
|
+
jobId: job.jobId,
|
|
130726
|
+
projectId: finalProjectId
|
|
130727
|
+
});
|
|
130728
|
+
if (leaseOutcome.status === "busy") {
|
|
130729
|
+
return {
|
|
130730
|
+
success: false,
|
|
130731
|
+
error: `indexing_busy:${leaseOutcome.activeRunId}`,
|
|
130732
|
+
data: {
|
|
130733
|
+
jobId: job.jobId,
|
|
130734
|
+
projectId: finalProjectId,
|
|
130735
|
+
status: "busy",
|
|
130736
|
+
activeRunId: leaseOutcome.activeRunId,
|
|
130737
|
+
leaseExpiresAt: leaseOutcome.leaseExpiresAt,
|
|
130738
|
+
message: "Another indexing run is active for this project. Poll get_index_status(activeRunId)."
|
|
130739
|
+
}
|
|
130740
|
+
};
|
|
130741
|
+
}
|
|
130742
|
+
if (leaseOutcome.status === "failed") {
|
|
130649
130743
|
return {
|
|
130650
130744
|
success: false,
|
|
130651
|
-
error: `Failed to acquire indexing lease: ${
|
|
130745
|
+
error: `Failed to acquire indexing lease: ${leaseOutcome.message}`
|
|
130652
130746
|
};
|
|
130653
130747
|
}
|
|
130654
|
-
|
|
130748
|
+
const lease = leaseOutcome.lease;
|
|
130749
|
+
executeIndexing({
|
|
130750
|
+
jobId: job.jobId,
|
|
130751
|
+
projectId: finalProjectId,
|
|
130752
|
+
projectPath: canonicalProjectPath,
|
|
130753
|
+
forceReindex,
|
|
130754
|
+
warmCache,
|
|
130755
|
+
warmupQueries,
|
|
130756
|
+
include_tests,
|
|
130757
|
+
managedRunLease: lease,
|
|
130758
|
+
warmupCache: this.contextualSearch.warmupCache.bind(this.contextualSearch)
|
|
130759
|
+
}).catch((error51) => {
|
|
130655
130760
|
logger.error("Background indexing failed", error51, {
|
|
130656
130761
|
jobId: job.jobId
|
|
130657
130762
|
});
|
|
@@ -130678,77 +130783,16 @@ class IndexProjectTool {
|
|
|
130678
130783
|
};
|
|
130679
130784
|
}
|
|
130680
130785
|
}
|
|
130681
|
-
async executeIndexing(jobId, projectId, projectPath, forceReindex, warmCache, warmupQueries, include_tests = false, managedRunLease) {
|
|
130682
|
-
const startTime = Date.now();
|
|
130683
|
-
try {
|
|
130684
|
-
indexJobTracker.updateStatus(jobId, "running");
|
|
130685
|
-
logger.info("Starting project indexing via ETL Pipeline", {
|
|
130686
|
-
jobId,
|
|
130687
|
-
projectPath,
|
|
130688
|
-
projectId,
|
|
130689
|
-
forceReindex,
|
|
130690
|
-
warmCache,
|
|
130691
|
-
include_tests
|
|
130692
|
-
});
|
|
130693
|
-
const etlResult = await EtlPipeline.getInstance().run({
|
|
130694
|
-
projectId,
|
|
130695
|
-
projectPath,
|
|
130696
|
-
jobId,
|
|
130697
|
-
forceReindex,
|
|
130698
|
-
include_tests,
|
|
130699
|
-
managedRunLease
|
|
130700
|
-
});
|
|
130701
|
-
const duration3 = Date.now() - startTime;
|
|
130702
|
-
logger.info("ETL Pipeline completed", {
|
|
130703
|
-
jobId,
|
|
130704
|
-
projectId,
|
|
130705
|
-
duration: duration3,
|
|
130706
|
-
filesIndexed: etlResult.filesIndexed,
|
|
130707
|
-
filesSkipped: etlResult.filesSkipped,
|
|
130708
|
-
chunksIndexed: etlResult.chunksIndexed,
|
|
130709
|
-
symbolsIndexed: etlResult.symbolsIndexed,
|
|
130710
|
-
errors: etlResult.errors,
|
|
130711
|
-
stageTimings: etlResult.stageTimings
|
|
130712
|
-
});
|
|
130713
|
-
if (warmCache) {
|
|
130714
|
-
logger.info("Starting cache warmup", { jobId, projectId });
|
|
130715
|
-
const warmupStats = await this.contextualSearch.warmupCache(projectId, projectPath, warmupQueries);
|
|
130716
|
-
logger.info("Cache warmup completed", { jobId, projectId, ...warmupStats });
|
|
130717
|
-
}
|
|
130718
|
-
indexJobTracker.updateProgress(jobId, etlResult.filesIndexed, etlResult.filesIndexed);
|
|
130719
|
-
await indexJobTracker.setResultAndFlush(jobId, {
|
|
130720
|
-
filesIndexed: etlResult.filesIndexed,
|
|
130721
|
-
chunksIndexed: etlResult.chunksIndexed,
|
|
130722
|
-
errors: etlResult.errors,
|
|
130723
|
-
duration: duration3,
|
|
130724
|
-
activatedGraphGenerationId: etlResult.activatedGraphGenerationId,
|
|
130725
|
-
parserDiagnostics: etlResult.parserDiagnostics
|
|
130726
|
-
});
|
|
130727
|
-
} catch (error51) {
|
|
130728
|
-
const duration3 = Date.now() - startTime;
|
|
130729
|
-
logger.error("Project indexing failed", error51, {
|
|
130730
|
-
jobId,
|
|
130731
|
-
projectPath,
|
|
130732
|
-
projectId,
|
|
130733
|
-
duration: duration3
|
|
130734
|
-
});
|
|
130735
|
-
indexJobTracker.setResult(jobId, {
|
|
130736
|
-
filesIndexed: 0,
|
|
130737
|
-
chunksIndexed: 0,
|
|
130738
|
-
errors: 1,
|
|
130739
|
-
duration: duration3
|
|
130740
|
-
}, error51.message);
|
|
130741
|
-
}
|
|
130742
|
-
}
|
|
130743
130786
|
}
|
|
130744
130787
|
var init_index_project = __esm(() => {
|
|
130745
130788
|
init_contextual_search_rlm();
|
|
130746
130789
|
init_dist();
|
|
130747
130790
|
init_index_job_tracker();
|
|
130748
|
-
|
|
130791
|
+
init_execute_indexing();
|
|
130792
|
+
init_acquire_indexing_lease();
|
|
130793
|
+
init_project_root_identity();
|
|
130749
130794
|
init_workspace_manager();
|
|
130750
130795
|
init_parser_readiness();
|
|
130751
|
-
init_managed_run_repository_pg();
|
|
130752
130796
|
});
|
|
130753
130797
|
|
|
130754
130798
|
// ../../packages/core/dist/tools/get_index_status.js
|
|
@@ -131216,17 +131260,17 @@ function applyReplacer(root, replacer) {
|
|
|
131216
131260
|
return transformChildren(root, replacer, []);
|
|
131217
131261
|
return transformChildren(normalizeValue(replacedRoot), replacer, []);
|
|
131218
131262
|
}
|
|
131219
|
-
function transformChildren(value, replacer,
|
|
131263
|
+
function transformChildren(value, replacer, path20) {
|
|
131220
131264
|
if (isJsonObject(value))
|
|
131221
|
-
return transformObject(value, replacer,
|
|
131265
|
+
return transformObject(value, replacer, path20);
|
|
131222
131266
|
if (isJsonArray(value))
|
|
131223
|
-
return transformArray(value, replacer,
|
|
131267
|
+
return transformArray(value, replacer, path20);
|
|
131224
131268
|
return value;
|
|
131225
131269
|
}
|
|
131226
|
-
function transformObject(obj, replacer,
|
|
131270
|
+
function transformObject(obj, replacer, path20) {
|
|
131227
131271
|
const result = {};
|
|
131228
131272
|
for (const [key, value] of Object.entries(obj)) {
|
|
131229
|
-
const childPath = [...
|
|
131273
|
+
const childPath = [...path20, key];
|
|
131230
131274
|
const replacedValue = replacer(key, value, childPath);
|
|
131231
131275
|
if (replacedValue === undefined)
|
|
131232
131276
|
continue;
|
|
@@ -131234,11 +131278,11 @@ function transformObject(obj, replacer, path19) {
|
|
|
131234
131278
|
}
|
|
131235
131279
|
return result;
|
|
131236
131280
|
}
|
|
131237
|
-
function transformArray(arr, replacer,
|
|
131281
|
+
function transformArray(arr, replacer, path20) {
|
|
131238
131282
|
const result = [];
|
|
131239
131283
|
for (let i = 0;i < arr.length; i++) {
|
|
131240
131284
|
const value = arr[i];
|
|
131241
|
-
const childPath = [...
|
|
131285
|
+
const childPath = [...path20, i];
|
|
131242
131286
|
const replacedValue = replacer(String(i), value, childPath);
|
|
131243
131287
|
if (replacedValue === undefined)
|
|
131244
131288
|
continue;
|
|
@@ -131961,7 +132005,7 @@ var init_memory_service = __esm(() => {
|
|
|
131961
132005
|
init_decay();
|
|
131962
132006
|
});
|
|
131963
132007
|
|
|
131964
|
-
// ../../packages/core/dist/services/graph/relation-extractor.js
|
|
132008
|
+
// ../../packages/core/dist/services/memory-graph/relation-extractor.js
|
|
131965
132009
|
class RelationExtractor {
|
|
131966
132010
|
graphStore;
|
|
131967
132011
|
constructor(graphStore) {
|
|
@@ -132199,7 +132243,7 @@ var init_relation_extractor = __esm(() => {
|
|
|
132199
132243
|
];
|
|
132200
132244
|
});
|
|
132201
132245
|
|
|
132202
|
-
// ../../packages/core/dist/services/graph/graph-queries.js
|
|
132246
|
+
// ../../packages/core/dist/services/memory-graph/graph-queries.js
|
|
132203
132247
|
class GraphQueries {
|
|
132204
132248
|
graphStore;
|
|
132205
132249
|
constructor(graphStore) {
|
|
@@ -132419,7 +132463,7 @@ var init_graph_queries = __esm(() => {
|
|
|
132419
132463
|
};
|
|
132420
132464
|
});
|
|
132421
132465
|
|
|
132422
|
-
// ../../packages/core/dist/services/graph/memory-graph.service.js
|
|
132466
|
+
// ../../packages/core/dist/services/memory-graph/memory-graph.service.js
|
|
132423
132467
|
class MemoryGraphService {
|
|
132424
132468
|
static instance = null;
|
|
132425
132469
|
store;
|
|
@@ -136306,7 +136350,7 @@ var init_session_pin_store = __esm(() => {
|
|
|
136306
136350
|
// ../../packages/core/dist/services/hooks/attribution-resolver.js
|
|
136307
136351
|
import fs9 from "fs";
|
|
136308
136352
|
import os3 from "os";
|
|
136309
|
-
import
|
|
136353
|
+
import path20 from "path";
|
|
136310
136354
|
|
|
136311
136355
|
class PgWorkspaceRootProvider {
|
|
136312
136356
|
cache = null;
|
|
@@ -136358,7 +136402,7 @@ class AttributionResolver {
|
|
|
136358
136402
|
this.pins = options.pins ?? new SessionPinStore;
|
|
136359
136403
|
this.canonicalize = options.canonicalize ?? defaultCanonicalize;
|
|
136360
136404
|
this.homedir = options.homedir ?? os3.homedir;
|
|
136361
|
-
this.fsRoot = options.fsRoot ?? (() =>
|
|
136405
|
+
this.fsRoot = options.fsRoot ?? (() => path20.parse(path20.sep).root);
|
|
136362
136406
|
}
|
|
136363
136407
|
async resolve(input) {
|
|
136364
136408
|
const caller = input.callerProjectId;
|
|
@@ -136411,7 +136455,7 @@ class AttributionResolver {
|
|
|
136411
136455
|
}
|
|
136412
136456
|
let bestPath = null;
|
|
136413
136457
|
for (const candidate2 of byPath.keys()) {
|
|
136414
|
-
if (canonicalCwd === candidate2 || canonicalCwd.startsWith(candidate2.endsWith(
|
|
136458
|
+
if (canonicalCwd === candidate2 || canonicalCwd.startsWith(candidate2.endsWith(path20.sep) ? candidate2 : candidate2 + path20.sep)) {
|
|
136415
136459
|
if (bestPath === null || candidate2.length > bestPath.length) {
|
|
136416
136460
|
bestPath = candidate2;
|
|
136417
136461
|
}
|
|
@@ -136434,7 +136478,7 @@ class AttributionResolver {
|
|
|
136434
136478
|
return projectPath2;
|
|
136435
136479
|
const fsRoot = this.fsRoot();
|
|
136436
136480
|
let normalized = projectPath2;
|
|
136437
|
-
while (normalized.length > fsRoot.length && normalized.endsWith(
|
|
136481
|
+
while (normalized.length > fsRoot.length && normalized.endsWith(path20.sep)) {
|
|
136438
136482
|
normalized = normalized.slice(0, -1);
|
|
136439
136483
|
}
|
|
136440
136484
|
return normalized;
|
|
@@ -136445,7 +136489,7 @@ function defaultCanonicalize(cwd) {
|
|
|
136445
136489
|
return fs9.realpathSync(cwd);
|
|
136446
136490
|
} catch {
|
|
136447
136491
|
try {
|
|
136448
|
-
return
|
|
136492
|
+
return path20.resolve(cwd);
|
|
136449
136493
|
} catch {
|
|
136450
136494
|
return;
|
|
136451
136495
|
}
|
|
@@ -137184,31 +137228,31 @@ class TracePathService {
|
|
|
137184
137228
|
const chains = [];
|
|
137185
137229
|
const seen = new Set;
|
|
137186
137230
|
let walks = 0;
|
|
137187
|
-
const walk = (fqn,
|
|
137231
|
+
const walk = (fqn, path21) => {
|
|
137188
137232
|
if (chains.length >= CHAIN_CAP)
|
|
137189
137233
|
return;
|
|
137190
137234
|
if (walks >= MAX_WALKS)
|
|
137191
137235
|
return;
|
|
137192
137236
|
walks++;
|
|
137193
|
-
const key =
|
|
137237
|
+
const key = path21.join("\u2192");
|
|
137194
137238
|
if (seen.has(key))
|
|
137195
137239
|
return;
|
|
137196
137240
|
seen.add(key);
|
|
137197
137241
|
const next = adj.get(fqn);
|
|
137198
137242
|
if (!next || next.length === 0 || !whoHasChild.has(fqn)) {
|
|
137199
|
-
if (
|
|
137200
|
-
chains.push(
|
|
137243
|
+
if (path21.length > 1)
|
|
137244
|
+
chains.push(path21.map((n) => this.fqnToName(n)).join(" \u2192 "));
|
|
137201
137245
|
return;
|
|
137202
137246
|
}
|
|
137203
137247
|
for (const child of next) {
|
|
137204
137248
|
if (chains.length >= CHAIN_CAP || walks >= MAX_WALKS)
|
|
137205
137249
|
return;
|
|
137206
|
-
if (
|
|
137207
|
-
const cycled = [...
|
|
137250
|
+
if (path21.includes(child)) {
|
|
137251
|
+
const cycled = [...path21, `${this.fqnToName(child)}\u21BA`];
|
|
137208
137252
|
chains.push(cycled.map((n) => n).join(" \u2192 "));
|
|
137209
137253
|
continue;
|
|
137210
137254
|
}
|
|
137211
|
-
walk(child, [...
|
|
137255
|
+
walk(child, [...path21, child]);
|
|
137212
137256
|
}
|
|
137213
137257
|
};
|
|
137214
137258
|
for (const seed of seeds) {
|
|
@@ -138040,216 +138084,231 @@ var init_get_architecture = __esm(() => {
|
|
|
138040
138084
|
init_architecture();
|
|
138041
138085
|
});
|
|
138042
138086
|
|
|
138043
|
-
// ../../packages/core/dist/
|
|
138087
|
+
// ../../packages/core/dist/services/file-read/file-content-cache.js
|
|
138044
138088
|
import fs10 from "fs/promises";
|
|
138045
|
-
import path20 from "path";
|
|
138046
138089
|
|
|
138047
|
-
class
|
|
138048
|
-
|
|
138049
|
-
description = "Read file with automatic compression, caching, and symbol metadata. " + "Use with search results for 60% token savings.";
|
|
138050
|
-
inputSchema = {
|
|
138051
|
-
type: "object",
|
|
138052
|
-
properties: {
|
|
138053
|
-
filePath: {
|
|
138054
|
-
type: "string",
|
|
138055
|
-
description: "File path (absolute or relative to project root)"
|
|
138056
|
-
},
|
|
138057
|
-
projectId: {
|
|
138058
|
-
type: "string",
|
|
138059
|
-
description: "Project ID for symbol metadata (optional)"
|
|
138060
|
-
},
|
|
138061
|
-
offset: {
|
|
138062
|
-
type: "number",
|
|
138063
|
-
description: "Start line number (1-indexed)"
|
|
138064
|
-
},
|
|
138065
|
-
limit: {
|
|
138066
|
-
type: "number",
|
|
138067
|
-
description: "Number of lines to read"
|
|
138068
|
-
},
|
|
138069
|
-
lineStart: {
|
|
138070
|
-
type: "number",
|
|
138071
|
-
description: "Start line (alternative to offset)"
|
|
138072
|
-
},
|
|
138073
|
-
lineEnd: {
|
|
138074
|
-
type: "number",
|
|
138075
|
-
description: "End line (alternative to limit)"
|
|
138076
|
-
},
|
|
138077
|
-
compress: {
|
|
138078
|
-
type: "boolean",
|
|
138079
|
-
description: "Auto-compress content > 100 lines (default: true)",
|
|
138080
|
-
default: true
|
|
138081
|
-
},
|
|
138082
|
-
targetRatio: {
|
|
138083
|
-
type: "number",
|
|
138084
|
-
description: "Compression target ratio (0.3 = 70% reduction)",
|
|
138085
|
-
default: 0.3
|
|
138086
|
-
},
|
|
138087
|
-
format: {
|
|
138088
|
-
type: "string",
|
|
138089
|
-
enum: ["json", "toon"],
|
|
138090
|
-
description: "Output format",
|
|
138091
|
-
default: "json"
|
|
138092
|
-
},
|
|
138093
|
-
fields: {
|
|
138094
|
-
type: "array",
|
|
138095
|
-
items: { type: "string" },
|
|
138096
|
-
description: "Projection \u2014 keep only these keys (dotted paths supported, e.g. ['nodes.symbol']). Absent/empty \u2192 full data."
|
|
138097
|
-
},
|
|
138098
|
-
includeSymbols: {
|
|
138099
|
-
type: "boolean",
|
|
138100
|
-
description: "Include symbol metadata from graph (default: true)",
|
|
138101
|
-
default: true
|
|
138102
|
-
},
|
|
138103
|
-
includeImports: {
|
|
138104
|
-
type: "boolean",
|
|
138105
|
-
description: "Extract and show import statements (default: true)",
|
|
138106
|
-
default: true
|
|
138107
|
-
}
|
|
138108
|
-
},
|
|
138109
|
-
required: ["filePath"]
|
|
138110
|
-
};
|
|
138111
|
-
compressor;
|
|
138112
|
-
symbolGraph;
|
|
138090
|
+
class FileContentCache {
|
|
138091
|
+
extractMetadata;
|
|
138113
138092
|
fileCache = new Map;
|
|
138114
|
-
projectRootCache = new Map;
|
|
138115
138093
|
CACHE_TTL = 60000;
|
|
138116
|
-
ROOT_CACHE_TTL = 300000;
|
|
138117
138094
|
FILE_CACHE_MAX_ENTRIES = 512;
|
|
138095
|
+
constructor(extractMetadata) {
|
|
138096
|
+
this.extractMetadata = extractMetadata;
|
|
138097
|
+
}
|
|
138098
|
+
async readFileWithCache(filePath, options) {
|
|
138099
|
+
const cacheKey = JSON.stringify({
|
|
138100
|
+
filePath,
|
|
138101
|
+
includeSymbols: options.includeSymbols ?? false,
|
|
138102
|
+
includeImports: options.includeImports ?? false,
|
|
138103
|
+
projectId: options.projectId ?? null,
|
|
138104
|
+
relativePath: options.relativePath ?? null
|
|
138105
|
+
});
|
|
138106
|
+
const cached2 = this.fileCache.get(cacheKey);
|
|
138107
|
+
if (cached2 && Date.now() - cached2.timestamp < this.CACHE_TTL) {
|
|
138108
|
+
logger.debug("File cache hit", { filePath });
|
|
138109
|
+
this.fileCache.delete(cacheKey);
|
|
138110
|
+
this.fileCache.set(cacheKey, cached2);
|
|
138111
|
+
if (!cached2.metadata) {
|
|
138112
|
+
const metadata2 = await this.extractMetadata(cached2.content, filePath, options);
|
|
138113
|
+
this.fileCache.set(cacheKey, { ...cached2, metadata: metadata2 });
|
|
138114
|
+
return { content: cached2.content, metadata: metadata2 };
|
|
138115
|
+
}
|
|
138116
|
+
return {
|
|
138117
|
+
content: cached2.content,
|
|
138118
|
+
metadata: cached2.metadata
|
|
138119
|
+
};
|
|
138120
|
+
}
|
|
138121
|
+
const content = await fs10.readFile(filePath, "utf-8");
|
|
138122
|
+
const metadata = await this.extractMetadata(content, filePath, options);
|
|
138123
|
+
evictOldest(this.fileCache, this.FILE_CACHE_MAX_ENTRIES - 1);
|
|
138124
|
+
this.fileCache.set(cacheKey, {
|
|
138125
|
+
content,
|
|
138126
|
+
timestamp: Date.now(),
|
|
138127
|
+
metadata
|
|
138128
|
+
});
|
|
138129
|
+
logger.debug("File read and cached", { filePath });
|
|
138130
|
+
return { content, metadata };
|
|
138131
|
+
}
|
|
138132
|
+
}
|
|
138133
|
+
var init_file_content_cache = __esm(() => {
|
|
138134
|
+
init_dist();
|
|
138135
|
+
});
|
|
138136
|
+
|
|
138137
|
+
// ../../packages/core/dist/services/file-read/file-metadata.js
|
|
138138
|
+
import path21 from "path";
|
|
138139
|
+
|
|
138140
|
+
class FileMetadataExtractor {
|
|
138141
|
+
symbolGraph;
|
|
138118
138142
|
constructor(symbolGraph) {
|
|
138119
|
-
this.compressor = new CodeCompressor;
|
|
138120
138143
|
this.symbolGraph = symbolGraph;
|
|
138121
|
-
eventBus.subscribe("indexing:started", ({ projectId, projectPath: projectPath2 }) => {
|
|
138122
|
-
this.projectRootCache.delete(projectId);
|
|
138123
|
-
this.evictOldest(this.projectRootCache);
|
|
138124
|
-
this.projectRootCache.set(projectId, projectPath2);
|
|
138125
|
-
});
|
|
138126
138144
|
}
|
|
138127
|
-
async
|
|
138128
|
-
const
|
|
138129
|
-
|
|
138130
|
-
const
|
|
138131
|
-
const
|
|
138132
|
-
|
|
138133
|
-
|
|
138134
|
-
|
|
138135
|
-
|
|
138136
|
-
|
|
138137
|
-
|
|
138138
|
-
|
|
138139
|
-
|
|
138140
|
-
|
|
138145
|
+
async extractMetadata(content, filePath, options) {
|
|
138146
|
+
const lines = content.split(`
|
|
138147
|
+
`);
|
|
138148
|
+
const language = this.detectLanguage(filePath);
|
|
138149
|
+
const metadata = {
|
|
138150
|
+
totalLines: lines.length,
|
|
138151
|
+
language
|
|
138152
|
+
};
|
|
138153
|
+
if (options.includeImports && language) {
|
|
138154
|
+
metadata.imports = this.extractImports(lines, language);
|
|
138155
|
+
}
|
|
138156
|
+
if (options.includeSymbols && this.symbolGraph && options.projectId) {
|
|
138157
|
+
try {
|
|
138158
|
+
const queryPath = options.relativePath || filePath;
|
|
138159
|
+
const { definitions } = await this.symbolGraph.listDefinitions(options.projectId, {
|
|
138160
|
+
file: queryPath,
|
|
138161
|
+
limit: 100
|
|
138162
|
+
});
|
|
138163
|
+
metadata.symbols = {
|
|
138164
|
+
definitions: definitions.length,
|
|
138165
|
+
references: 0
|
|
138141
138166
|
};
|
|
138167
|
+
} catch (error51) {
|
|
138168
|
+
logger.debug("Failed to get symbol metadata", { filePath, error: error51 });
|
|
138142
138169
|
}
|
|
138143
|
-
|
|
138144
|
-
|
|
138145
|
-
|
|
138146
|
-
|
|
138147
|
-
|
|
138148
|
-
|
|
138149
|
-
|
|
138170
|
+
}
|
|
138171
|
+
return metadata;
|
|
138172
|
+
}
|
|
138173
|
+
detectLanguage(filePath) {
|
|
138174
|
+
const ext2 = path21.extname(filePath).toLowerCase();
|
|
138175
|
+
const languageMap2 = {
|
|
138176
|
+
".ts": "TypeScript",
|
|
138177
|
+
".tsx": "TypeScript",
|
|
138178
|
+
".js": "JavaScript",
|
|
138179
|
+
".jsx": "JavaScript",
|
|
138180
|
+
".vue": "Vue",
|
|
138181
|
+
".py": "Python",
|
|
138182
|
+
".go": "Go",
|
|
138183
|
+
".rs": "Rust",
|
|
138184
|
+
".java": "Java",
|
|
138185
|
+
".cpp": "C++",
|
|
138186
|
+
".c": "C",
|
|
138187
|
+
".h": "C",
|
|
138188
|
+
".hpp": "C++",
|
|
138189
|
+
".cs": "C#",
|
|
138190
|
+
".rb": "Ruby",
|
|
138191
|
+
".php": "PHP",
|
|
138192
|
+
".swift": "Swift",
|
|
138193
|
+
".kt": "Kotlin",
|
|
138194
|
+
".kts": "Kotlin",
|
|
138195
|
+
".scala": "Scala",
|
|
138196
|
+
".md": "Markdown",
|
|
138197
|
+
".json": "JSON",
|
|
138198
|
+
".yaml": "YAML",
|
|
138199
|
+
".yml": "YAML",
|
|
138200
|
+
".xml": "XML",
|
|
138201
|
+
".html": "HTML",
|
|
138202
|
+
".css": "CSS",
|
|
138203
|
+
".scss": "SCSS",
|
|
138204
|
+
".sql": "SQL",
|
|
138205
|
+
".sh": "Shell",
|
|
138206
|
+
".bash": "Shell"
|
|
138207
|
+
};
|
|
138208
|
+
return languageMap2[ext2];
|
|
138209
|
+
}
|
|
138210
|
+
extractImports(lines, language) {
|
|
138211
|
+
const imports = [];
|
|
138212
|
+
const importPatterns = {
|
|
138213
|
+
TypeScript: /^(import\s+.*?from\s+['"]|import\s+['"])/,
|
|
138214
|
+
JavaScript: /^(import\s+.*?from\s+['"]|import\s+['"]|require\s*\(\s*['"])/,
|
|
138215
|
+
Python: /^(import\s+|from\s+\S+\s+import)/,
|
|
138216
|
+
Go: /^import\s+/,
|
|
138217
|
+
Java: /^import\s+/,
|
|
138218
|
+
Rust: /^use\s+/
|
|
138219
|
+
};
|
|
138220
|
+
const pattern = importPatterns[language];
|
|
138221
|
+
if (!pattern)
|
|
138222
|
+
return imports;
|
|
138223
|
+
for (const line of lines) {
|
|
138224
|
+
const trimmed = line.trim();
|
|
138225
|
+
if (pattern.test(trimmed)) {
|
|
138226
|
+
imports.push(trimmed);
|
|
138150
138227
|
}
|
|
138151
|
-
|
|
138152
|
-
|
|
138153
|
-
|
|
138154
|
-
|
|
138155
|
-
|
|
138156
|
-
|
|
138157
|
-
|
|
138158
|
-
|
|
138159
|
-
|
|
138228
|
+
}
|
|
138229
|
+
return imports;
|
|
138230
|
+
}
|
|
138231
|
+
}
|
|
138232
|
+
var init_file_metadata = __esm(() => {
|
|
138233
|
+
init_dist();
|
|
138234
|
+
});
|
|
138235
|
+
|
|
138236
|
+
// ../../packages/core/dist/services/file-read/line-range.js
|
|
138237
|
+
function calculateRange(params) {
|
|
138238
|
+
if (params.lineStart !== undefined && params.lineEnd !== undefined) {
|
|
138239
|
+
return {
|
|
138240
|
+
start: Math.max(1, params.lineStart),
|
|
138241
|
+
end: params.lineEnd
|
|
138242
|
+
};
|
|
138243
|
+
}
|
|
138244
|
+
if (params.offset !== undefined) {
|
|
138245
|
+
const offset = Math.max(1, params.offset);
|
|
138246
|
+
const limit = params.limit || 1000;
|
|
138247
|
+
return {
|
|
138248
|
+
start: offset,
|
|
138249
|
+
end: offset + limit - 1
|
|
138250
|
+
};
|
|
138251
|
+
}
|
|
138252
|
+
return {
|
|
138253
|
+
start: 1,
|
|
138254
|
+
end: Infinity
|
|
138255
|
+
};
|
|
138256
|
+
}
|
|
138257
|
+
function adjustRange(range, totalLines) {
|
|
138258
|
+
const start = Math.max(1, Math.min(range.start, totalLines));
|
|
138259
|
+
const end = range.end === Infinity ? totalLines : Math.min(range.end, totalLines);
|
|
138260
|
+
return { start, end };
|
|
138261
|
+
}
|
|
138262
|
+
function extractLines(lines, range) {
|
|
138263
|
+
const start = range.start - 1;
|
|
138264
|
+
const end = range.end;
|
|
138265
|
+
const selectedLines = lines.slice(start, end);
|
|
138266
|
+
return selectedLines.map((line, index) => {
|
|
138267
|
+
const lineNum = start + index + 1;
|
|
138268
|
+
return `${lineNum.toString().padStart(6, " ")}: ${line}`;
|
|
138269
|
+
}).join(`
|
|
138160
138270
|
`);
|
|
138161
|
-
|
|
138162
|
-
|
|
138163
|
-
|
|
138164
|
-
|
|
138271
|
+
}
|
|
138272
|
+
function selectLines(lines, range) {
|
|
138273
|
+
let content = extractLines(lines, range);
|
|
138274
|
+
let lineCount = content.split(`
|
|
138165
138275
|
`).length;
|
|
138166
|
-
|
|
138167
|
-
|
|
138168
|
-
|
|
138169
|
-
|
|
138276
|
+
let clipped = false;
|
|
138277
|
+
if (lineCount > MASSA_AI_READ_FILE_MAX_LINES) {
|
|
138278
|
+
const cappedLines = lines.slice(range.start - 1, range.start - 1 + MASSA_AI_READ_FILE_MAX_LINES);
|
|
138279
|
+
content = cappedLines.join(`
|
|
138170
138280
|
`);
|
|
138171
|
-
|
|
138281
|
+
lineCount = content.split(`
|
|
138172
138282
|
`).length;
|
|
138173
|
-
|
|
138174
|
-
|
|
138175
|
-
|
|
138176
|
-
|
|
138177
|
-
|
|
138178
|
-
|
|
138179
|
-
|
|
138180
|
-
|
|
138181
|
-
|
|
138182
|
-
|
|
138183
|
-
|
|
138184
|
-
|
|
138185
|
-
|
|
138186
|
-
|
|
138187
|
-
|
|
138188
|
-
|
|
138189
|
-
|
|
138190
|
-
|
|
138191
|
-
|
|
138192
|
-
metadata: {
|
|
138193
|
-
totalLines,
|
|
138194
|
-
language: metadata.language,
|
|
138195
|
-
...metadata.symbols && { symbols: metadata.symbols },
|
|
138196
|
-
...metadata.imports && { imports: metadata.imports }
|
|
138197
|
-
},
|
|
138198
|
-
compressed: shouldAutoCompress,
|
|
138199
|
-
recommendations: []
|
|
138200
|
-
};
|
|
138201
|
-
if (shouldAutoCompress) {
|
|
138202
|
-
const compressed = await this.compressor.compress(selectedContent, "code_structure");
|
|
138203
|
-
const originalTokens = estimateTokens(selectedContent, "code");
|
|
138204
|
-
const compressedTokens = estimateTokens(compressed.compressed, "code");
|
|
138205
|
-
const actualRatio = compressedTokens / originalTokens;
|
|
138206
|
-
result.content = compressed.compressed;
|
|
138207
|
-
result.tokens = {
|
|
138208
|
-
original: originalTokens,
|
|
138209
|
-
compressed: compressedTokens,
|
|
138210
|
-
saved: originalTokens - compressedTokens,
|
|
138211
|
-
savingsPercent: Math.round((1 - actualRatio) * 100)
|
|
138212
|
-
};
|
|
138213
|
-
result.compressionRatio = actualRatio;
|
|
138214
|
-
result.recommendations.push(`\u2713 Auto-compressed ${selectedLineCount} lines (${result.tokens.savingsPercent}% reduction)`);
|
|
138215
|
-
} else {
|
|
138216
|
-
result.content = selectedContent;
|
|
138217
|
-
result.tokens = {
|
|
138218
|
-
original: estimateTokens(selectedContent, "code"),
|
|
138219
|
-
compressed: estimateTokens(selectedContent, "code"),
|
|
138220
|
-
saved: 0,
|
|
138221
|
-
savingsPercent: 0
|
|
138222
|
-
};
|
|
138223
|
-
if (selectedLineCount > 100) {
|
|
138224
|
-
result.recommendations.push("\uD83D\uDCA1 Content > 100 lines. Consider compress=true for token savings");
|
|
138225
|
-
}
|
|
138226
|
-
}
|
|
138227
|
-
if (range.start === 1 && range.end === Infinity) {
|
|
138228
|
-
result.recommendations.push("\uD83D\uDCA1 Use lineStart/lineEnd or offset/limit to read specific sections (60% token savings)");
|
|
138229
|
-
}
|
|
138230
|
-
if (metadata.symbols && metadata.symbols.definitions > 0) {
|
|
138231
|
-
result.recommendations.push(`\uD83D\uDCA1 Use get_references() to find usages of ${metadata.symbols.definitions} symbols in this file`);
|
|
138232
|
-
}
|
|
138233
|
-
return serializeToolResponse(result, { format, fields });
|
|
138234
|
-
} catch (error51) {
|
|
138235
|
-
logger.error("Failed to read file", error51, {
|
|
138236
|
-
filePath: p.filePath
|
|
138237
|
-
});
|
|
138238
|
-
return {
|
|
138239
|
-
success: false,
|
|
138240
|
-
error: `Failed to read file: ${error51.message}`
|
|
138241
|
-
};
|
|
138242
|
-
}
|
|
138283
|
+
clipped = true;
|
|
138284
|
+
}
|
|
138285
|
+
return { content, lineCount, clipped };
|
|
138286
|
+
}
|
|
138287
|
+
var MASSA_AI_READ_FILE_MAX_LINES;
|
|
138288
|
+
var init_line_range = __esm(() => {
|
|
138289
|
+
MASSA_AI_READ_FILE_MAX_LINES = (() => {
|
|
138290
|
+
const v = Number(process.env.MASSA_AI_READ_FILE_MAX_LINES);
|
|
138291
|
+
return Number.isFinite(v) && v > 0 ? Math.floor(v) : 500;
|
|
138292
|
+
})();
|
|
138293
|
+
});
|
|
138294
|
+
|
|
138295
|
+
// ../../packages/core/dist/services/file-read/path-containment.js
|
|
138296
|
+
import path22 from "path";
|
|
138297
|
+
|
|
138298
|
+
class PathContainment {
|
|
138299
|
+
projectRoots;
|
|
138300
|
+
constructor(projectRoots) {
|
|
138301
|
+
this.projectRoots = projectRoots;
|
|
138243
138302
|
}
|
|
138244
138303
|
async resolveFilePath(filePath, projectId) {
|
|
138245
|
-
if (
|
|
138246
|
-
return
|
|
138304
|
+
if (path22.isAbsolute(filePath)) {
|
|
138305
|
+
return path22.resolve(filePath);
|
|
138247
138306
|
}
|
|
138248
138307
|
if (projectId) {
|
|
138249
|
-
const root = await this.getProjectRoot(projectId);
|
|
138308
|
+
const root = await this.projectRoots.getProjectRoot(projectId);
|
|
138250
138309
|
if (root) {
|
|
138251
138310
|
const cleaned = sanitizeFilePath(filePath);
|
|
138252
|
-
return
|
|
138311
|
+
return path22.resolve(root, cleaned);
|
|
138253
138312
|
}
|
|
138254
138313
|
return null;
|
|
138255
138314
|
}
|
|
@@ -138258,19 +138317,19 @@ class ReadFileTool {
|
|
|
138258
138317
|
async checkPathContainment(absoluteFilePath, projectId) {
|
|
138259
138318
|
const roots = [];
|
|
138260
138319
|
if (projectId) {
|
|
138261
|
-
const root = await this.getProjectRoot(projectId);
|
|
138320
|
+
const root = await this.projectRoots.getProjectRoot(projectId);
|
|
138262
138321
|
if (root)
|
|
138263
|
-
roots.push(
|
|
138322
|
+
roots.push(path22.resolve(root));
|
|
138264
138323
|
}
|
|
138265
|
-
roots.push(
|
|
138324
|
+
roots.push(path22.resolve(process.cwd()));
|
|
138266
138325
|
const envRoots = (process.env.MASSA_AI_READ_FILE_ROOTS ?? "").split(":").map((s) => s.trim()).filter((s) => s.length > 0);
|
|
138267
138326
|
for (const extra of envRoots) {
|
|
138268
|
-
roots.push(
|
|
138327
|
+
roots.push(path22.resolve(extra));
|
|
138269
138328
|
}
|
|
138270
|
-
const target =
|
|
138329
|
+
const target = path22.resolve(absoluteFilePath);
|
|
138271
138330
|
for (const root of roots) {
|
|
138272
|
-
const rel =
|
|
138273
|
-
if (rel !== "" && !rel.startsWith("..") && !
|
|
138331
|
+
const rel = path22.relative(root, target);
|
|
138332
|
+
if (rel !== "" && !rel.startsWith("..") && !path22.isAbsolute(rel)) {
|
|
138274
138333
|
return { allowed: true };
|
|
138275
138334
|
}
|
|
138276
138335
|
if (rel === "")
|
|
@@ -138286,6 +138345,23 @@ ${validRootsList}
|
|
|
138286
138345
|
` + `Provide a filePath that resolves under one of these roots.`
|
|
138287
138346
|
};
|
|
138288
138347
|
}
|
|
138348
|
+
}
|
|
138349
|
+
var init_path_containment = __esm(() => {
|
|
138350
|
+
init_dist();
|
|
138351
|
+
});
|
|
138352
|
+
|
|
138353
|
+
// ../../packages/core/dist/services/file-read/project-root-cache.js
|
|
138354
|
+
class ProjectRootCache {
|
|
138355
|
+
projectRootCache = new Map;
|
|
138356
|
+
ROOT_CACHE_TTL = 300000;
|
|
138357
|
+
PROJECT_ROOT_CACHE_MAX_ENTRIES = 512;
|
|
138358
|
+
constructor() {
|
|
138359
|
+
eventBus.subscribe("indexing:started", ({ projectId, projectPath: projectPath2 }) => {
|
|
138360
|
+
this.projectRootCache.delete(projectId);
|
|
138361
|
+
evictOldest(this.projectRootCache, this.PROJECT_ROOT_CACHE_MAX_ENTRIES - 1);
|
|
138362
|
+
this.projectRootCache.set(projectId, projectPath2);
|
|
138363
|
+
});
|
|
138364
|
+
}
|
|
138289
138365
|
async getProjectRoot(projectId) {
|
|
138290
138366
|
const cached2 = this.projectRootCache.get(projectId);
|
|
138291
138367
|
if (cached2 !== undefined) {
|
|
@@ -138296,7 +138372,7 @@ ${validRootsList}
|
|
|
138296
138372
|
try {
|
|
138297
138373
|
const workspace = await workspaceManager.getWorkspace(projectId);
|
|
138298
138374
|
if (workspace?.project_path) {
|
|
138299
|
-
|
|
138375
|
+
evictOldest(this.projectRootCache, this.PROJECT_ROOT_CACHE_MAX_ENTRIES - 1);
|
|
138300
138376
|
this.projectRootCache.set(projectId, workspace.project_path);
|
|
138301
138377
|
return workspace.project_path;
|
|
138302
138378
|
}
|
|
@@ -138305,182 +138381,236 @@ ${validRootsList}
|
|
|
138305
138381
|
}
|
|
138306
138382
|
return null;
|
|
138307
138383
|
}
|
|
138308
|
-
|
|
138309
|
-
|
|
138310
|
-
|
|
138311
|
-
|
|
138312
|
-
|
|
138313
|
-
|
|
138314
|
-
|
|
138315
|
-
|
|
138316
|
-
|
|
138317
|
-
|
|
138384
|
+
}
|
|
138385
|
+
var init_project_root_cache = __esm(() => {
|
|
138386
|
+
init_dist();
|
|
138387
|
+
init_event_bus();
|
|
138388
|
+
init_workspace_manager();
|
|
138389
|
+
});
|
|
138390
|
+
|
|
138391
|
+
// ../../packages/core/dist/services/file-read/read-file.service.js
|
|
138392
|
+
function readFileOptions(p) {
|
|
138393
|
+
const shouldCompress = p.compress !== false;
|
|
138394
|
+
const targetRatio = p.targetRatio || 0.3;
|
|
138395
|
+
const format = p.format || "json";
|
|
138396
|
+
const { fields } = p;
|
|
138397
|
+
const includeSymbols = p.includeSymbols !== false;
|
|
138398
|
+
const includeImports = p.includeImports !== false;
|
|
138399
|
+
return { shouldCompress, targetRatio, format, fields, includeSymbols, includeImports };
|
|
138400
|
+
}
|
|
138401
|
+
|
|
138402
|
+
class ReadFileService {
|
|
138403
|
+
compressor;
|
|
138404
|
+
symbolGraph;
|
|
138405
|
+
projectRoots;
|
|
138406
|
+
pathContainment;
|
|
138407
|
+
fileMetadata;
|
|
138408
|
+
fileContent;
|
|
138409
|
+
constructor(symbolGraph) {
|
|
138410
|
+
this.compressor = new CodeCompressor;
|
|
138411
|
+
this.symbolGraph = symbolGraph;
|
|
138412
|
+
this.projectRoots = new ProjectRootCache;
|
|
138413
|
+
this.pathContainment = new PathContainment(this.projectRoots);
|
|
138414
|
+
this.fileMetadata = new FileMetadataExtractor(symbolGraph);
|
|
138415
|
+
this.fileContent = new FileContentCache((content, filePath, options) => this.fileMetadata.extractMetadata(content, filePath, options));
|
|
138416
|
+
}
|
|
138417
|
+
async read(p, options) {
|
|
138418
|
+
const { shouldCompress, targetRatio, includeSymbols, includeImports } = options;
|
|
138419
|
+
const resolved = await this.pathContainment.resolveFilePath(p.filePath, p.projectId);
|
|
138420
|
+
if (resolved === null) {
|
|
138318
138421
|
return {
|
|
138319
|
-
|
|
138320
|
-
|
|
138422
|
+
ok: false,
|
|
138423
|
+
error: "Relative filePath requires a projectId (to resolve against the workspace) or an absolute path."
|
|
138321
138424
|
};
|
|
138322
138425
|
}
|
|
138323
|
-
|
|
138324
|
-
|
|
138325
|
-
|
|
138426
|
+
const filePath = resolved;
|
|
138427
|
+
const containment = await this.pathContainment.checkPathContainment(filePath, p.projectId);
|
|
138428
|
+
if (!containment.allowed) {
|
|
138326
138429
|
return {
|
|
138327
|
-
|
|
138328
|
-
|
|
138430
|
+
ok: false,
|
|
138431
|
+
error: containment.error
|
|
138329
138432
|
};
|
|
138330
138433
|
}
|
|
138331
|
-
|
|
138332
|
-
|
|
138333
|
-
|
|
138334
|
-
|
|
138335
|
-
|
|
138336
|
-
|
|
138337
|
-
|
|
138338
|
-
const end = range.end === Infinity ? totalLines : Math.min(range.end, totalLines);
|
|
138339
|
-
return { start, end };
|
|
138340
|
-
}
|
|
138341
|
-
async readFileWithCache(filePath, options) {
|
|
138342
|
-
const cacheKey = JSON.stringify({
|
|
138343
|
-
filePath,
|
|
138344
|
-
includeSymbols: options.includeSymbols ?? false,
|
|
138345
|
-
includeImports: options.includeImports ?? false,
|
|
138346
|
-
projectId: options.projectId ?? null,
|
|
138347
|
-
relativePath: options.relativePath ?? null
|
|
138348
|
-
});
|
|
138349
|
-
const cached2 = this.fileCache.get(cacheKey);
|
|
138350
|
-
if (cached2 && Date.now() - cached2.timestamp < this.CACHE_TTL) {
|
|
138351
|
-
logger.debug("File cache hit", { filePath });
|
|
138352
|
-
this.fileCache.delete(cacheKey);
|
|
138353
|
-
this.fileCache.set(cacheKey, cached2);
|
|
138354
|
-
if (!cached2.metadata) {
|
|
138355
|
-
const metadata2 = await this.extractMetadata(cached2.content, filePath, options);
|
|
138356
|
-
this.fileCache.set(cacheKey, { ...cached2, metadata: metadata2 });
|
|
138357
|
-
return { content: cached2.content, metadata: metadata2 };
|
|
138358
|
-
}
|
|
138359
|
-
return {
|
|
138360
|
-
content: cached2.content,
|
|
138361
|
-
metadata: cached2.metadata
|
|
138362
|
-
};
|
|
138363
|
-
}
|
|
138364
|
-
const content = await fs10.readFile(filePath, "utf-8");
|
|
138365
|
-
const metadata = await this.extractMetadata(content, filePath, options);
|
|
138366
|
-
this.evictOldest(this.fileCache);
|
|
138367
|
-
this.fileCache.set(cacheKey, {
|
|
138368
|
-
content,
|
|
138369
|
-
timestamp: Date.now(),
|
|
138370
|
-
metadata
|
|
138434
|
+
const relativePath = p.filePath;
|
|
138435
|
+
const range = calculateRange(p);
|
|
138436
|
+
const { content, metadata } = await this.fileContent.readFileWithCache(filePath, {
|
|
138437
|
+
includeSymbols,
|
|
138438
|
+
includeImports,
|
|
138439
|
+
projectId: p.projectId,
|
|
138440
|
+
relativePath
|
|
138371
138441
|
});
|
|
138372
|
-
logger.debug("File read and cached", { filePath });
|
|
138373
|
-
return { content, metadata };
|
|
138374
|
-
}
|
|
138375
|
-
async extractMetadata(content, filePath, options) {
|
|
138376
138442
|
const lines = content.split(`
|
|
138377
138443
|
`);
|
|
138378
|
-
const
|
|
138379
|
-
const
|
|
138380
|
-
|
|
138381
|
-
|
|
138444
|
+
const totalLines = lines.length;
|
|
138445
|
+
const adjustedRange = adjustRange(range, totalLines);
|
|
138446
|
+
const { content: selectedContent, lineCount: selectedLineCount, clipped: source_clipped } = selectLines(lines, adjustedRange);
|
|
138447
|
+
const shouldAutoCompress = shouldCompress && selectedLineCount > 100 && targetRatio < 1;
|
|
138448
|
+
const result = {
|
|
138449
|
+
filePath: p.filePath,
|
|
138450
|
+
absolutePath: filePath,
|
|
138451
|
+
lineRange: {
|
|
138452
|
+
requested: {
|
|
138453
|
+
start: range.start,
|
|
138454
|
+
end: range.end === Infinity ? null : range.end
|
|
138455
|
+
},
|
|
138456
|
+
actual: {
|
|
138457
|
+
start: adjustedRange.start,
|
|
138458
|
+
end: source_clipped ? adjustedRange.start + selectedLineCount - 1 : adjustedRange.end,
|
|
138459
|
+
total: totalLines
|
|
138460
|
+
},
|
|
138461
|
+
selected: selectedLineCount
|
|
138462
|
+
},
|
|
138463
|
+
source_clipped,
|
|
138464
|
+
metadata: {
|
|
138465
|
+
totalLines,
|
|
138466
|
+
language: metadata.language,
|
|
138467
|
+
...metadata.symbols && { symbols: metadata.symbols },
|
|
138468
|
+
...metadata.imports && { imports: metadata.imports }
|
|
138469
|
+
},
|
|
138470
|
+
compressed: shouldAutoCompress,
|
|
138471
|
+
recommendations: []
|
|
138382
138472
|
};
|
|
138383
|
-
if (
|
|
138384
|
-
|
|
138385
|
-
|
|
138386
|
-
|
|
138387
|
-
|
|
138388
|
-
|
|
138389
|
-
|
|
138390
|
-
|
|
138391
|
-
|
|
138392
|
-
|
|
138393
|
-
|
|
138394
|
-
|
|
138395
|
-
|
|
138396
|
-
|
|
138397
|
-
|
|
138398
|
-
|
|
138473
|
+
if (shouldAutoCompress) {
|
|
138474
|
+
const compressed = await this.compressor.compress(selectedContent, "code_structure");
|
|
138475
|
+
const originalTokens = estimateTokens(selectedContent, "code");
|
|
138476
|
+
const compressedTokens = estimateTokens(compressed.compressed, "code");
|
|
138477
|
+
const actualRatio = compressedTokens / originalTokens;
|
|
138478
|
+
result.content = compressed.compressed;
|
|
138479
|
+
result.tokens = {
|
|
138480
|
+
original: originalTokens,
|
|
138481
|
+
compressed: compressedTokens,
|
|
138482
|
+
saved: originalTokens - compressedTokens,
|
|
138483
|
+
savingsPercent: Math.round((1 - actualRatio) * 100)
|
|
138484
|
+
};
|
|
138485
|
+
result.compressionRatio = actualRatio;
|
|
138486
|
+
result.recommendations.push(`\u2713 Auto-compressed ${selectedLineCount} lines (${result.tokens.savingsPercent}% reduction)`);
|
|
138487
|
+
} else {
|
|
138488
|
+
result.content = selectedContent;
|
|
138489
|
+
result.tokens = {
|
|
138490
|
+
original: estimateTokens(selectedContent, "code"),
|
|
138491
|
+
compressed: estimateTokens(selectedContent, "code"),
|
|
138492
|
+
saved: 0,
|
|
138493
|
+
savingsPercent: 0
|
|
138494
|
+
};
|
|
138495
|
+
if (selectedLineCount > 100) {
|
|
138496
|
+
result.recommendations.push("\uD83D\uDCA1 Content > 100 lines. Consider compress=true for token savings");
|
|
138399
138497
|
}
|
|
138400
138498
|
}
|
|
138401
|
-
|
|
138402
|
-
|
|
138403
|
-
|
|
138404
|
-
|
|
138405
|
-
|
|
138406
|
-
|
|
138407
|
-
return
|
|
138408
|
-
const lineNum = start + index + 1;
|
|
138409
|
-
return `${lineNum.toString().padStart(6, " ")}: ${line}`;
|
|
138410
|
-
}).join(`
|
|
138411
|
-
`);
|
|
138499
|
+
if (range.start === 1 && range.end === Infinity) {
|
|
138500
|
+
result.recommendations.push("\uD83D\uDCA1 Use lineStart/lineEnd or offset/limit to read specific sections (60% token savings)");
|
|
138501
|
+
}
|
|
138502
|
+
if (metadata.symbols && metadata.symbols.definitions > 0) {
|
|
138503
|
+
result.recommendations.push(`\uD83D\uDCA1 Use get_references() to find usages of ${metadata.symbols.definitions} symbols in this file`);
|
|
138504
|
+
}
|
|
138505
|
+
return { ok: true, data: result };
|
|
138412
138506
|
}
|
|
138413
|
-
|
|
138414
|
-
|
|
138415
|
-
|
|
138416
|
-
|
|
138417
|
-
|
|
138418
|
-
|
|
138419
|
-
|
|
138420
|
-
|
|
138421
|
-
|
|
138422
|
-
|
|
138423
|
-
|
|
138424
|
-
|
|
138425
|
-
|
|
138426
|
-
|
|
138427
|
-
|
|
138428
|
-
|
|
138429
|
-
|
|
138430
|
-
|
|
138431
|
-
|
|
138432
|
-
|
|
138433
|
-
|
|
138434
|
-
|
|
138435
|
-
|
|
138436
|
-
|
|
138437
|
-
|
|
138438
|
-
|
|
138439
|
-
|
|
138440
|
-
|
|
138441
|
-
|
|
138442
|
-
|
|
138443
|
-
|
|
138444
|
-
|
|
138445
|
-
|
|
138446
|
-
|
|
138447
|
-
|
|
138448
|
-
|
|
138507
|
+
}
|
|
138508
|
+
var init_read_file_service = __esm(() => {
|
|
138509
|
+
init_dist();
|
|
138510
|
+
init_code_compressor();
|
|
138511
|
+
init_file_content_cache();
|
|
138512
|
+
init_file_metadata();
|
|
138513
|
+
init_line_range();
|
|
138514
|
+
init_path_containment();
|
|
138515
|
+
init_project_root_cache();
|
|
138516
|
+
});
|
|
138517
|
+
|
|
138518
|
+
// ../../packages/core/dist/tools/read_file.js
|
|
138519
|
+
class ReadFileTool {
|
|
138520
|
+
name = "read_file";
|
|
138521
|
+
description = "Read file with automatic compression, caching, and symbol metadata. " + "Use with search results for 60% token savings.";
|
|
138522
|
+
inputSchema = {
|
|
138523
|
+
type: "object",
|
|
138524
|
+
properties: {
|
|
138525
|
+
filePath: {
|
|
138526
|
+
type: "string",
|
|
138527
|
+
description: "File path (absolute or relative to project root)"
|
|
138528
|
+
},
|
|
138529
|
+
projectId: {
|
|
138530
|
+
type: "string",
|
|
138531
|
+
description: "Project ID for symbol metadata (optional)"
|
|
138532
|
+
},
|
|
138533
|
+
offset: {
|
|
138534
|
+
type: "number",
|
|
138535
|
+
description: "Start line number (1-indexed)"
|
|
138536
|
+
},
|
|
138537
|
+
limit: {
|
|
138538
|
+
type: "number",
|
|
138539
|
+
description: "Number of lines to read"
|
|
138540
|
+
},
|
|
138541
|
+
lineStart: {
|
|
138542
|
+
type: "number",
|
|
138543
|
+
description: "Start line (alternative to offset)"
|
|
138544
|
+
},
|
|
138545
|
+
lineEnd: {
|
|
138546
|
+
type: "number",
|
|
138547
|
+
description: "End line (alternative to limit)"
|
|
138548
|
+
},
|
|
138549
|
+
compress: {
|
|
138550
|
+
type: "boolean",
|
|
138551
|
+
description: "Auto-compress content > 100 lines (default: true)",
|
|
138552
|
+
default: true
|
|
138553
|
+
},
|
|
138554
|
+
targetRatio: {
|
|
138555
|
+
type: "number",
|
|
138556
|
+
description: "Compression target ratio (0.3 = 70% reduction)",
|
|
138557
|
+
default: 0.3
|
|
138558
|
+
},
|
|
138559
|
+
format: {
|
|
138560
|
+
type: "string",
|
|
138561
|
+
enum: ["json", "toon"],
|
|
138562
|
+
description: "Output format",
|
|
138563
|
+
default: "json"
|
|
138564
|
+
},
|
|
138565
|
+
fields: {
|
|
138566
|
+
type: "array",
|
|
138567
|
+
items: { type: "string" },
|
|
138568
|
+
description: "Projection \u2014 keep only these keys (dotted paths supported, e.g. ['nodes.symbol']). Absent/empty \u2192 full data."
|
|
138569
|
+
},
|
|
138570
|
+
includeSymbols: {
|
|
138571
|
+
type: "boolean",
|
|
138572
|
+
description: "Include symbol metadata from graph (default: true)",
|
|
138573
|
+
default: true
|
|
138574
|
+
},
|
|
138575
|
+
includeImports: {
|
|
138576
|
+
type: "boolean",
|
|
138577
|
+
description: "Extract and show import statements (default: true)",
|
|
138578
|
+
default: true
|
|
138579
|
+
}
|
|
138580
|
+
},
|
|
138581
|
+
required: ["filePath"]
|
|
138582
|
+
};
|
|
138583
|
+
service;
|
|
138584
|
+
constructor(symbolGraph) {
|
|
138585
|
+
this.service = new ReadFileService(symbolGraph);
|
|
138449
138586
|
}
|
|
138450
|
-
|
|
138451
|
-
const
|
|
138452
|
-
const
|
|
138453
|
-
|
|
138454
|
-
|
|
138455
|
-
|
|
138456
|
-
|
|
138457
|
-
Java: /^import\s+/,
|
|
138458
|
-
Rust: /^use\s+/
|
|
138459
|
-
};
|
|
138460
|
-
const pattern = importPatterns[language];
|
|
138461
|
-
if (!pattern)
|
|
138462
|
-
return imports;
|
|
138463
|
-
for (const line of lines) {
|
|
138464
|
-
const trimmed = line.trim();
|
|
138465
|
-
if (pattern.test(trimmed)) {
|
|
138466
|
-
imports.push(trimmed);
|
|
138587
|
+
async handle(params) {
|
|
138588
|
+
const p = params;
|
|
138589
|
+
const options = readFileOptions(p);
|
|
138590
|
+
try {
|
|
138591
|
+
const outcome2 = await this.service.read(p, options);
|
|
138592
|
+
if (!outcome2.ok) {
|
|
138593
|
+
return { success: false, error: outcome2.error };
|
|
138467
138594
|
}
|
|
138595
|
+
return serializeToolResponse(outcome2.data, {
|
|
138596
|
+
format: options.format,
|
|
138597
|
+
fields: options.fields
|
|
138598
|
+
});
|
|
138599
|
+
} catch (error51) {
|
|
138600
|
+
logger.error("Failed to read file", error51, {
|
|
138601
|
+
filePath: p.filePath
|
|
138602
|
+
});
|
|
138603
|
+
return {
|
|
138604
|
+
success: false,
|
|
138605
|
+
error: `Failed to read file: ${error51.message}`
|
|
138606
|
+
};
|
|
138468
138607
|
}
|
|
138469
|
-
return imports;
|
|
138470
138608
|
}
|
|
138471
138609
|
}
|
|
138472
|
-
var MASSA_AI_READ_FILE_MAX_LINES;
|
|
138473
138610
|
var init_read_file = __esm(() => {
|
|
138474
138611
|
init_dist();
|
|
138475
|
-
init_dist();
|
|
138476
|
-
init_code_compressor();
|
|
138477
138612
|
init_serialize();
|
|
138478
|
-
|
|
138479
|
-
init_workspace_manager();
|
|
138480
|
-
MASSA_AI_READ_FILE_MAX_LINES = (() => {
|
|
138481
|
-
const v = Number(process.env.MASSA_AI_READ_FILE_MAX_LINES);
|
|
138482
|
-
return Number.isFinite(v) && v > 0 ? Math.floor(v) : 500;
|
|
138483
|
-
})();
|
|
138613
|
+
init_read_file_service();
|
|
138484
138614
|
});
|
|
138485
138615
|
|
|
138486
138616
|
// ../../packages/core/dist/tools/execute.js
|
|
@@ -141415,7 +141545,7 @@ var init_l1_memory_cache = __esm(() => {
|
|
|
141415
141545
|
// ../../packages/core/dist/services/health/local-health-checker.js
|
|
141416
141546
|
import fs11 from "fs/promises";
|
|
141417
141547
|
import { existsSync as existsSync3 } from "fs";
|
|
141418
|
-
import
|
|
141548
|
+
import path23 from "path";
|
|
141419
141549
|
|
|
141420
141550
|
class LocalHealthChecker {
|
|
141421
141551
|
ollamaBaseUrl = process.env.OLLAMA_BASE_URL || "http://localhost:11434";
|
|
@@ -141450,7 +141580,7 @@ class LocalHealthChecker {
|
|
|
141450
141580
|
try {
|
|
141451
141581
|
if (!existsSync3(this.dataDir))
|
|
141452
141582
|
await fs11.mkdir(this.dataDir, { recursive: true });
|
|
141453
|
-
const probe2 =
|
|
141583
|
+
const probe2 = path23.join(this.dataDir, ".health-check-test");
|
|
141454
141584
|
await fs11.writeFile(probe2, "ok");
|
|
141455
141585
|
await fs11.unlink(probe2);
|
|
141456
141586
|
return { available: true, latency: Date.now() - start, details: { path: this.dataDir, writable: true } };
|
|
@@ -143393,7 +143523,7 @@ var init_scheduler2 = __esm(() => {
|
|
|
143393
143523
|
// ../../packages/core/dist/services/pricing/models-dev-client.js
|
|
143394
143524
|
import fs12 from "fs/promises";
|
|
143395
143525
|
import { existsSync as existsSync4 } from "fs";
|
|
143396
|
-
import
|
|
143526
|
+
import path24 from "path";
|
|
143397
143527
|
function getModelsDevClient() {
|
|
143398
143528
|
if (!clientInstance) {
|
|
143399
143529
|
clientInstance = new ModelsDevClient;
|
|
@@ -143413,7 +143543,7 @@ var init_models_dev_client = __esm(() => {
|
|
|
143413
143543
|
memoryCacheTimestamp = 0;
|
|
143414
143544
|
getLocalCachePath() {
|
|
143415
143545
|
const dataDir = config2.get("dataDir");
|
|
143416
|
-
return
|
|
143546
|
+
return path24.join(dataDir, ModelsDevClient.LOCAL_CACHE_FILE);
|
|
143417
143547
|
}
|
|
143418
143548
|
async loadLocalCache() {
|
|
143419
143549
|
const cachePath = this.getLocalCachePath();
|
|
@@ -143448,7 +143578,7 @@ var init_models_dev_client = __esm(() => {
|
|
|
143448
143578
|
async saveLocalCache(models) {
|
|
143449
143579
|
const cachePath = this.getLocalCachePath();
|
|
143450
143580
|
try {
|
|
143451
|
-
const dir =
|
|
143581
|
+
const dir = path24.dirname(cachePath);
|
|
143452
143582
|
await fs12.mkdir(dir, { recursive: true });
|
|
143453
143583
|
const data = {
|
|
143454
143584
|
timestamp: Date.now(),
|
|
@@ -149339,33 +149469,33 @@ var require_URL = __commonJS((exports, module) => {
|
|
|
149339
149469
|
else
|
|
149340
149470
|
return basepath.substring(0, lastslash + 1) + refpath;
|
|
149341
149471
|
}
|
|
149342
|
-
function remove_dot_segments(
|
|
149343
|
-
if (!
|
|
149344
|
-
return
|
|
149472
|
+
function remove_dot_segments(path25) {
|
|
149473
|
+
if (!path25)
|
|
149474
|
+
return path25;
|
|
149345
149475
|
var output = "";
|
|
149346
|
-
while (
|
|
149347
|
-
if (
|
|
149348
|
-
|
|
149476
|
+
while (path25.length > 0) {
|
|
149477
|
+
if (path25 === "." || path25 === "..") {
|
|
149478
|
+
path25 = "";
|
|
149349
149479
|
break;
|
|
149350
149480
|
}
|
|
149351
|
-
var twochars =
|
|
149352
|
-
var threechars =
|
|
149353
|
-
var fourchars =
|
|
149481
|
+
var twochars = path25.substring(0, 2);
|
|
149482
|
+
var threechars = path25.substring(0, 3);
|
|
149483
|
+
var fourchars = path25.substring(0, 4);
|
|
149354
149484
|
if (threechars === "../") {
|
|
149355
|
-
|
|
149485
|
+
path25 = path25.substring(3);
|
|
149356
149486
|
} else if (twochars === "./") {
|
|
149357
|
-
|
|
149487
|
+
path25 = path25.substring(2);
|
|
149358
149488
|
} else if (threechars === "/./") {
|
|
149359
|
-
|
|
149360
|
-
} else if (twochars === "/." &&
|
|
149361
|
-
|
|
149362
|
-
} else if (fourchars === "/../" || threechars === "/.." &&
|
|
149363
|
-
|
|
149489
|
+
path25 = "/" + path25.substring(3);
|
|
149490
|
+
} else if (twochars === "/." && path25.length === 2) {
|
|
149491
|
+
path25 = "/";
|
|
149492
|
+
} else if (fourchars === "/../" || threechars === "/.." && path25.length === 3) {
|
|
149493
|
+
path25 = "/" + path25.substring(4);
|
|
149364
149494
|
output = output.replace(/\/?[^\/]*$/, "");
|
|
149365
149495
|
} else {
|
|
149366
|
-
var segment =
|
|
149496
|
+
var segment = path25.match(/(\/?([^\/]*))/)[0];
|
|
149367
149497
|
output += segment;
|
|
149368
|
-
|
|
149498
|
+
path25 = path25.substring(segment.length);
|
|
149369
149499
|
}
|
|
149370
149500
|
}
|
|
149371
149501
|
return output;
|
|
@@ -161435,21 +161565,21 @@ function jsonToKeyPathChunks(value, label = "$") {
|
|
|
161435
161565
|
walk(value, label, out);
|
|
161436
161566
|
return out;
|
|
161437
161567
|
}
|
|
161438
|
-
function walk(val,
|
|
161568
|
+
function walk(val, path25, out) {
|
|
161439
161569
|
if (val === null || val === undefined)
|
|
161440
161570
|
return;
|
|
161441
161571
|
if (Array.isArray(val)) {
|
|
161442
161572
|
if (val.length === 0) {
|
|
161443
|
-
out.push({ path:
|
|
161573
|
+
out.push({ path: path25, content: `**${path25}** = _[]_` });
|
|
161444
161574
|
return;
|
|
161445
161575
|
}
|
|
161446
161576
|
if (val.every((v) => v !== null && typeof v === "object")) {
|
|
161447
|
-
val.forEach((v, i) => walk(v, `${
|
|
161577
|
+
val.forEach((v, i) => walk(v, `${path25}[${i}]`, out));
|
|
161448
161578
|
return;
|
|
161449
161579
|
}
|
|
161450
161580
|
const items = val.map((v) => `- \`${String(v)}\``).join(`
|
|
161451
161581
|
`);
|
|
161452
|
-
out.push({ path:
|
|
161582
|
+
out.push({ path: path25, content: `**${path25}**
|
|
161453
161583
|
|
|
161454
161584
|
${items}` });
|
|
161455
161585
|
return;
|
|
@@ -161457,16 +161587,16 @@ ${items}` });
|
|
|
161457
161587
|
if (typeof val === "object") {
|
|
161458
161588
|
const entries = Object.entries(val);
|
|
161459
161589
|
if (entries.length === 0) {
|
|
161460
|
-
out.push({ path:
|
|
161590
|
+
out.push({ path: path25, content: `**${path25}** = _{}_` });
|
|
161461
161591
|
return;
|
|
161462
161592
|
}
|
|
161463
161593
|
for (const [k, v] of entries) {
|
|
161464
161594
|
const safeKey = /^[A-Za-z_$][\w$]*$/.test(k) ? k : JSON.stringify(k);
|
|
161465
|
-
walk(v, `${
|
|
161595
|
+
walk(v, `${path25}.${safeKey}`, out);
|
|
161466
161596
|
}
|
|
161467
161597
|
return;
|
|
161468
161598
|
}
|
|
161469
|
-
out.push({ path:
|
|
161599
|
+
out.push({ path: path25, content: `**${path25}** = \`${String(val)}\`` });
|
|
161470
161600
|
}
|
|
161471
161601
|
var gfm, STRIP_SELECTORS, tdCache = null;
|
|
161472
161602
|
var init_html_to_md = __esm(() => {
|
|
@@ -161732,12 +161862,7 @@ class WebController {
|
|
|
161732
161862
|
markIndexed: (key, ts) => {
|
|
161733
161863
|
this.cache.delete(key);
|
|
161734
161864
|
this.cache.set(key, ts);
|
|
161735
|
-
|
|
161736
|
-
const oldest = this.cache.keys().next().value;
|
|
161737
|
-
if (oldest === undefined)
|
|
161738
|
-
break;
|
|
161739
|
-
this.cache.delete(oldest);
|
|
161740
|
-
}
|
|
161865
|
+
evictOldest(this.cache, WEB_CACHE_MAX_ENTRIES);
|
|
161741
161866
|
}
|
|
161742
161867
|
};
|
|
161743
161868
|
}
|
|
@@ -162225,7 +162350,7 @@ var init_hook_service = __esm(() => {
|
|
|
162225
162350
|
// ../../packages/core/dist/services/bootstrap/bootstrap-service.js
|
|
162226
162351
|
import { randomUUID as randomUUID9 } from "crypto";
|
|
162227
162352
|
import fs13 from "fs";
|
|
162228
|
-
import
|
|
162353
|
+
import path25 from "path";
|
|
162229
162354
|
import { spawn as spawn2 } from "child_process";
|
|
162230
162355
|
function readBootstrapConfig() {
|
|
162231
162356
|
try {
|
|
@@ -162385,7 +162510,7 @@ async function scanSignals(_projectId, projectRoot, caps, symbolGraph, gitRunner
|
|
|
162385
162510
|
}
|
|
162386
162511
|
try {
|
|
162387
162512
|
for (const name26 of README_CANDIDATES) {
|
|
162388
|
-
const p =
|
|
162513
|
+
const p = path25.join(projectRoot, name26);
|
|
162389
162514
|
if (fs13.existsSync(p) && fs13.statSync(p).isFile()) {
|
|
162390
162515
|
const buf = fs13.readFileSync(p);
|
|
162391
162516
|
signals.readme = buf.slice(0, MAX_README_BYTES).toString("utf8");
|
|
@@ -162396,14 +162521,14 @@ async function scanSignals(_projectId, projectRoot, caps, symbolGraph, gitRunner
|
|
|
162396
162521
|
logger.debug("bootstrap scan: README read failed", { error: e.message });
|
|
162397
162522
|
}
|
|
162398
162523
|
try {
|
|
162399
|
-
const docsDir =
|
|
162524
|
+
const docsDir = path25.join(projectRoot, "docs");
|
|
162400
162525
|
if (fs13.existsSync(docsDir) && fs13.statSync(docsDir).isDirectory()) {
|
|
162401
162526
|
const entries = walkMarkdown(docsDir).slice(0, MAX_DOCS);
|
|
162402
162527
|
for (const rel of entries) {
|
|
162403
162528
|
try {
|
|
162404
162529
|
const buf = fs13.readFileSync(rel);
|
|
162405
162530
|
signals.docs.push({
|
|
162406
|
-
path:
|
|
162531
|
+
path: path25.relative(projectRoot, rel),
|
|
162407
162532
|
snippet: buf.slice(0, MAX_DOC_BYTES).toString("utf8")
|
|
162408
162533
|
});
|
|
162409
162534
|
} catch {}
|
|
@@ -162414,7 +162539,7 @@ async function scanSignals(_projectId, projectRoot, caps, symbolGraph, gitRunner
|
|
|
162414
162539
|
}
|
|
162415
162540
|
try {
|
|
162416
162541
|
for (const name26 of MANIFEST_FILES) {
|
|
162417
|
-
const p =
|
|
162542
|
+
const p = path25.join(projectRoot, name26);
|
|
162418
162543
|
if (!fs13.existsSync(p) || !fs13.statSync(p).isFile())
|
|
162419
162544
|
continue;
|
|
162420
162545
|
const raw2 = fs13.readFileSync(p).slice(0, MAX_MANIFEST_BYTES).toString("utf8");
|
|
@@ -162462,7 +162587,7 @@ function walkMarkdown(dir) {
|
|
|
162462
162587
|
continue;
|
|
162463
162588
|
}
|
|
162464
162589
|
for (const e of entries) {
|
|
162465
|
-
const full =
|
|
162590
|
+
const full = path25.join(cur, e.name);
|
|
162466
162591
|
if (e.isDirectory()) {
|
|
162467
162592
|
if (e.name === "node_modules" || e.name.startsWith("."))
|
|
162468
162593
|
continue;
|
|
@@ -165980,7 +166105,7 @@ init_dist();
|
|
|
165980
166105
|
init_dist15();
|
|
165981
166106
|
init_dist();
|
|
165982
166107
|
import fs14 from "fs/promises";
|
|
165983
|
-
import
|
|
166108
|
+
import path26 from "path";
|
|
165984
166109
|
var _indexProjectTool = null;
|
|
165985
166110
|
function indexProjectTool() {
|
|
165986
166111
|
if (!_indexProjectTool)
|
|
@@ -166250,7 +166375,7 @@ class EmbeddedApiClient {
|
|
|
166250
166375
|
} else {
|
|
166251
166376
|
end = start + 20;
|
|
166252
166377
|
}
|
|
166253
|
-
const absolutePath =
|
|
166378
|
+
const absolutePath = path26.join(workspace.project_path, file2);
|
|
166254
166379
|
const content = await fs14.readFile(absolutePath, "utf-8");
|
|
166255
166380
|
const lines = content.split(/\r?\n/);
|
|
166256
166381
|
const slice = lines.slice(start - 1, Math.min(lines.length, end));
|
|
@@ -166474,21 +166599,21 @@ class EmbeddedApiClient {
|
|
|
166474
166599
|
async uploadAndIndex(params) {
|
|
166475
166600
|
const rawBase = params.projectId || params.projectPath.replace(/\\/g, "/").split("/").filter(Boolean).pop() || "default";
|
|
166476
166601
|
const finalProjectId = rawBase.replace(/[^a-zA-Z0-9_.-]/g, "_").slice(0, 128);
|
|
166477
|
-
const uploadRoot = process.env.MASSA_AI_UPLOAD_DIR ||
|
|
166478
|
-
const stagingDir =
|
|
166602
|
+
const uploadRoot = process.env.MASSA_AI_UPLOAD_DIR || path26.join(getGlobalDataDir(), "uploads");
|
|
166603
|
+
const stagingDir = path26.resolve(uploadRoot, finalProjectId);
|
|
166479
166604
|
await fs14.rm(stagingDir, { recursive: true, force: true });
|
|
166480
166605
|
await fs14.mkdir(stagingDir, { recursive: true });
|
|
166481
166606
|
const WRITE_BATCH = 20;
|
|
166482
166607
|
for (let i = 0;i < params.files.length; i += WRITE_BATCH) {
|
|
166483
166608
|
await Promise.all(params.files.slice(i, i + WRITE_BATCH).map(async (file2) => {
|
|
166484
|
-
if (
|
|
166609
|
+
if (path26.isAbsolute(file2.relativePath) || file2.relativePath.includes("..")) {
|
|
166485
166610
|
throw new Error(`Invalid file path: ${file2.relativePath}`);
|
|
166486
166611
|
}
|
|
166487
|
-
const dest =
|
|
166488
|
-
if (!dest.startsWith(stagingDir +
|
|
166612
|
+
const dest = path26.resolve(stagingDir, file2.relativePath.replace(/\//g, path26.sep));
|
|
166613
|
+
if (!dest.startsWith(stagingDir + path26.sep)) {
|
|
166489
166614
|
throw new Error(`Path escapes staging directory: ${file2.relativePath}`);
|
|
166490
166615
|
}
|
|
166491
|
-
await fs14.mkdir(
|
|
166616
|
+
await fs14.mkdir(path26.dirname(dest), { recursive: true });
|
|
166492
166617
|
await fs14.writeFile(dest, file2.content, "utf-8");
|
|
166493
166618
|
}));
|
|
166494
166619
|
}
|
|
@@ -166822,7 +166947,7 @@ class EmbeddedApiClient {
|
|
|
166822
166947
|
// src/file-collector.ts
|
|
166823
166948
|
init_config();
|
|
166824
166949
|
import fs15 from "fs/promises";
|
|
166825
|
-
import
|
|
166950
|
+
import path27 from "path";
|
|
166826
166951
|
var SKIP_DIRS = new Set([
|
|
166827
166952
|
"node_modules",
|
|
166828
166953
|
".git",
|
|
@@ -166872,13 +166997,13 @@ async function walk2(root2, dir, files, state, allowed) {
|
|
|
166872
166997
|
break;
|
|
166873
166998
|
if (entry2.isDirectory()) {
|
|
166874
166999
|
if (!SKIP_DIRS.has(entry2.name) && !entry2.name.startsWith(".")) {
|
|
166875
|
-
await walk2(root2,
|
|
167000
|
+
await walk2(root2, path27.join(dir, entry2.name), files, state, allowed);
|
|
166876
167001
|
}
|
|
166877
167002
|
} else if (entry2.isFile()) {
|
|
166878
|
-
const ext2 =
|
|
167003
|
+
const ext2 = path27.extname(entry2.name).toLowerCase();
|
|
166879
167004
|
if (!allowed.has(ext2))
|
|
166880
167005
|
continue;
|
|
166881
|
-
const fullPath =
|
|
167006
|
+
const fullPath = path27.join(dir, entry2.name);
|
|
166882
167007
|
try {
|
|
166883
167008
|
const stat = await fs15.stat(fullPath);
|
|
166884
167009
|
if (stat.size > MAX_FILE_BYTES)
|
|
@@ -166887,7 +167012,7 @@ async function walk2(root2, dir, files, state, allowed) {
|
|
|
166887
167012
|
continue;
|
|
166888
167013
|
const content = await fs15.readFile(fullPath, "utf-8");
|
|
166889
167014
|
state.totalBytes += stat.size;
|
|
166890
|
-
const relativePath =
|
|
167015
|
+
const relativePath = path27.relative(root2, fullPath).split(path27.sep).join("/");
|
|
166891
167016
|
files.push({ relativePath, content });
|
|
166892
167017
|
} catch {}
|
|
166893
167018
|
}
|