@massa-ai/mcp-client 1.17.0 → 1.19.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 +787 -580
- 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
|
}
|
|
@@ -136464,6 +136508,72 @@ var init_attribution_resolver = __esm(() => {
|
|
|
136464
136508
|
init_session_pin_store();
|
|
136465
136509
|
});
|
|
136466
136510
|
|
|
136511
|
+
// ../../packages/core/dist/kernel/sanitize/credential-scrub.js
|
|
136512
|
+
function markerFor(id) {
|
|
136513
|
+
return `[REDACTED:${id}]`;
|
|
136514
|
+
}
|
|
136515
|
+
function fullMatchRule(id, pattern) {
|
|
136516
|
+
const marker26 = markerFor(id);
|
|
136517
|
+
return {
|
|
136518
|
+
id,
|
|
136519
|
+
replace(text3) {
|
|
136520
|
+
let count = 0;
|
|
136521
|
+
const replaced = text3.replace(pattern, () => {
|
|
136522
|
+
count++;
|
|
136523
|
+
return marker26;
|
|
136524
|
+
});
|
|
136525
|
+
return { text: replaced, count };
|
|
136526
|
+
}
|
|
136527
|
+
};
|
|
136528
|
+
}
|
|
136529
|
+
function scrubCredentials(payloadJson) {
|
|
136530
|
+
const redactions = {};
|
|
136531
|
+
for (const id of RULE_IDS)
|
|
136532
|
+
redactions[id] = 0;
|
|
136533
|
+
let text3 = payloadJson;
|
|
136534
|
+
for (const rule of RULES) {
|
|
136535
|
+
const { text: next, count } = rule.replace(text3);
|
|
136536
|
+
text3 = next;
|
|
136537
|
+
redactions[rule.id] += count;
|
|
136538
|
+
}
|
|
136539
|
+
const total = Object.values(redactions).reduce((sum, n) => sum + n, 0);
|
|
136540
|
+
return {
|
|
136541
|
+
sanitized: text3,
|
|
136542
|
+
redactions,
|
|
136543
|
+
total
|
|
136544
|
+
};
|
|
136545
|
+
}
|
|
136546
|
+
var PEM_PATTERN, JWT_PATTERN, AWS_KEY_PATTERN, SK_KEY_PATTERN, GITHUB_TOKEN_PATTERN, SLACK_TOKEN_PATTERN, BEARER_PATTERN, RULES, RULE_IDS;
|
|
136547
|
+
var init_credential_scrub = __esm(() => {
|
|
136548
|
+
PEM_PATTERN = /-----BEGIN [A-Z ]{0,32}PRIVATE KEY-----[\s\S]{0,8192}?-----END [A-Z ]{0,32}PRIVATE KEY-----/g;
|
|
136549
|
+
JWT_PATTERN = /\beyJ[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}\b/g;
|
|
136550
|
+
AWS_KEY_PATTERN = /\b(?:AKIA|ASIA|ABIA|ACCA)[A-Z0-9]{16}\b/g;
|
|
136551
|
+
SK_KEY_PATTERN = /\bsk-[A-Za-z0-9_-]{20,}\b/g;
|
|
136552
|
+
GITHUB_TOKEN_PATTERN = /\bgh[pousr]_[A-Za-z0-9]{36,}\b|\bgithub_pat_[A-Za-z0-9_]{22,}\b/g;
|
|
136553
|
+
SLACK_TOKEN_PATTERN = /\bxox[baprs]-[A-Za-z0-9-]{18,}\b/g;
|
|
136554
|
+
BEARER_PATTERN = /(Bearer\s+)([A-Za-z0-9._~+/=-]{20,})/g;
|
|
136555
|
+
RULES = [
|
|
136556
|
+
fullMatchRule("pem", PEM_PATTERN),
|
|
136557
|
+
fullMatchRule("jwt", JWT_PATTERN),
|
|
136558
|
+
fullMatchRule("aws-key", AWS_KEY_PATTERN),
|
|
136559
|
+
fullMatchRule("sk-key", SK_KEY_PATTERN),
|
|
136560
|
+
fullMatchRule("github-token", GITHUB_TOKEN_PATTERN),
|
|
136561
|
+
fullMatchRule("slack-token", SLACK_TOKEN_PATTERN),
|
|
136562
|
+
{
|
|
136563
|
+
id: "bearer",
|
|
136564
|
+
replace(text3) {
|
|
136565
|
+
let count = 0;
|
|
136566
|
+
const replaced = text3.replace(BEARER_PATTERN, (_m, prefix) => {
|
|
136567
|
+
count++;
|
|
136568
|
+
return `${prefix}${markerFor("bearer")}`;
|
|
136569
|
+
});
|
|
136570
|
+
return { text: replaced, count };
|
|
136571
|
+
}
|
|
136572
|
+
}
|
|
136573
|
+
];
|
|
136574
|
+
RULE_IDS = RULES.map((r) => r.id);
|
|
136575
|
+
});
|
|
136576
|
+
|
|
136467
136577
|
// ../../packages/core/dist/tools/compact_snapshot.js
|
|
136468
136578
|
class CompactSnapshotTool {
|
|
136469
136579
|
name = "compact_snapshot";
|
|
@@ -136515,19 +136625,26 @@ class CompactSnapshotTool {
|
|
|
136515
136625
|
persistedId = newObservationId();
|
|
136516
136626
|
try {
|
|
136517
136627
|
const attribution = await (this.resolverOverride ?? getAttributionResolver()).resolve({ callerProjectId: projectId, sessionId, cwd });
|
|
136628
|
+
const scrub = scrubCredentials(JSON.stringify({
|
|
136629
|
+
snapshot: snapshot.xml,
|
|
136630
|
+
eventCount: snapshot.eventCount,
|
|
136631
|
+
compactCount: snapshot.compactCount,
|
|
136632
|
+
generatedAt: snapshot.generatedAt,
|
|
136633
|
+
sectionCount: snapshot.sections.length
|
|
136634
|
+
}));
|
|
136635
|
+
if (scrub.total > 0) {
|
|
136636
|
+
logger.debug("compact_snapshot payload redacted before persist", {
|
|
136637
|
+
redactions: scrub.redactions,
|
|
136638
|
+
total: scrub.total
|
|
136639
|
+
});
|
|
136640
|
+
}
|
|
136518
136641
|
store4.insert({
|
|
136519
136642
|
id: persistedId,
|
|
136520
136643
|
projectId: attribution.projectId,
|
|
136521
136644
|
sessionId,
|
|
136522
136645
|
source: "pre-compact",
|
|
136523
136646
|
category: "compaction-snapshots",
|
|
136524
|
-
payloadJson:
|
|
136525
|
-
snapshot: snapshot.xml,
|
|
136526
|
-
eventCount: snapshot.eventCount,
|
|
136527
|
-
compactCount: snapshot.compactCount,
|
|
136528
|
-
generatedAt: snapshot.generatedAt,
|
|
136529
|
-
sectionCount: snapshot.sections.length
|
|
136530
|
-
}),
|
|
136647
|
+
payloadJson: scrub.sanitized,
|
|
136531
136648
|
importance: 0.8,
|
|
136532
136649
|
createdAt: Date.now(),
|
|
136533
136650
|
attributionSource: attribution.source
|
|
@@ -136579,6 +136696,7 @@ var init_compact_snapshot = __esm(() => {
|
|
|
136579
136696
|
init_observation_repository();
|
|
136580
136697
|
init_compaction_snapshot_service();
|
|
136581
136698
|
init_attribution_resolver();
|
|
136699
|
+
init_credential_scrub();
|
|
136582
136700
|
});
|
|
136583
136701
|
|
|
136584
136702
|
// ../../packages/core/dist/tools/list_projects.js
|
|
@@ -137184,31 +137302,31 @@ class TracePathService {
|
|
|
137184
137302
|
const chains = [];
|
|
137185
137303
|
const seen = new Set;
|
|
137186
137304
|
let walks = 0;
|
|
137187
|
-
const walk = (fqn,
|
|
137305
|
+
const walk = (fqn, path21) => {
|
|
137188
137306
|
if (chains.length >= CHAIN_CAP)
|
|
137189
137307
|
return;
|
|
137190
137308
|
if (walks >= MAX_WALKS)
|
|
137191
137309
|
return;
|
|
137192
137310
|
walks++;
|
|
137193
|
-
const key =
|
|
137311
|
+
const key = path21.join("\u2192");
|
|
137194
137312
|
if (seen.has(key))
|
|
137195
137313
|
return;
|
|
137196
137314
|
seen.add(key);
|
|
137197
137315
|
const next = adj.get(fqn);
|
|
137198
137316
|
if (!next || next.length === 0 || !whoHasChild.has(fqn)) {
|
|
137199
|
-
if (
|
|
137200
|
-
chains.push(
|
|
137317
|
+
if (path21.length > 1)
|
|
137318
|
+
chains.push(path21.map((n) => this.fqnToName(n)).join(" \u2192 "));
|
|
137201
137319
|
return;
|
|
137202
137320
|
}
|
|
137203
137321
|
for (const child of next) {
|
|
137204
137322
|
if (chains.length >= CHAIN_CAP || walks >= MAX_WALKS)
|
|
137205
137323
|
return;
|
|
137206
|
-
if (
|
|
137207
|
-
const cycled = [...
|
|
137324
|
+
if (path21.includes(child)) {
|
|
137325
|
+
const cycled = [...path21, `${this.fqnToName(child)}\u21BA`];
|
|
137208
137326
|
chains.push(cycled.map((n) => n).join(" \u2192 "));
|
|
137209
137327
|
continue;
|
|
137210
137328
|
}
|
|
137211
|
-
walk(child, [...
|
|
137329
|
+
walk(child, [...path21, child]);
|
|
137212
137330
|
}
|
|
137213
137331
|
};
|
|
137214
137332
|
for (const seed of seeds) {
|
|
@@ -138040,216 +138158,231 @@ var init_get_architecture = __esm(() => {
|
|
|
138040
138158
|
init_architecture();
|
|
138041
138159
|
});
|
|
138042
138160
|
|
|
138043
|
-
// ../../packages/core/dist/
|
|
138161
|
+
// ../../packages/core/dist/services/file-read/file-content-cache.js
|
|
138044
138162
|
import fs10 from "fs/promises";
|
|
138045
|
-
import path20 from "path";
|
|
138046
138163
|
|
|
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;
|
|
138164
|
+
class FileContentCache {
|
|
138165
|
+
extractMetadata;
|
|
138113
138166
|
fileCache = new Map;
|
|
138114
|
-
projectRootCache = new Map;
|
|
138115
138167
|
CACHE_TTL = 60000;
|
|
138116
|
-
ROOT_CACHE_TTL = 300000;
|
|
138117
138168
|
FILE_CACHE_MAX_ENTRIES = 512;
|
|
138169
|
+
constructor(extractMetadata) {
|
|
138170
|
+
this.extractMetadata = extractMetadata;
|
|
138171
|
+
}
|
|
138172
|
+
async readFileWithCache(filePath, options) {
|
|
138173
|
+
const cacheKey = JSON.stringify({
|
|
138174
|
+
filePath,
|
|
138175
|
+
includeSymbols: options.includeSymbols ?? false,
|
|
138176
|
+
includeImports: options.includeImports ?? false,
|
|
138177
|
+
projectId: options.projectId ?? null,
|
|
138178
|
+
relativePath: options.relativePath ?? null
|
|
138179
|
+
});
|
|
138180
|
+
const cached2 = this.fileCache.get(cacheKey);
|
|
138181
|
+
if (cached2 && Date.now() - cached2.timestamp < this.CACHE_TTL) {
|
|
138182
|
+
logger.debug("File cache hit", { filePath });
|
|
138183
|
+
this.fileCache.delete(cacheKey);
|
|
138184
|
+
this.fileCache.set(cacheKey, cached2);
|
|
138185
|
+
if (!cached2.metadata) {
|
|
138186
|
+
const metadata2 = await this.extractMetadata(cached2.content, filePath, options);
|
|
138187
|
+
this.fileCache.set(cacheKey, { ...cached2, metadata: metadata2 });
|
|
138188
|
+
return { content: cached2.content, metadata: metadata2 };
|
|
138189
|
+
}
|
|
138190
|
+
return {
|
|
138191
|
+
content: cached2.content,
|
|
138192
|
+
metadata: cached2.metadata
|
|
138193
|
+
};
|
|
138194
|
+
}
|
|
138195
|
+
const content = await fs10.readFile(filePath, "utf-8");
|
|
138196
|
+
const metadata = await this.extractMetadata(content, filePath, options);
|
|
138197
|
+
evictOldest(this.fileCache, this.FILE_CACHE_MAX_ENTRIES - 1);
|
|
138198
|
+
this.fileCache.set(cacheKey, {
|
|
138199
|
+
content,
|
|
138200
|
+
timestamp: Date.now(),
|
|
138201
|
+
metadata
|
|
138202
|
+
});
|
|
138203
|
+
logger.debug("File read and cached", { filePath });
|
|
138204
|
+
return { content, metadata };
|
|
138205
|
+
}
|
|
138206
|
+
}
|
|
138207
|
+
var init_file_content_cache = __esm(() => {
|
|
138208
|
+
init_dist();
|
|
138209
|
+
});
|
|
138210
|
+
|
|
138211
|
+
// ../../packages/core/dist/services/file-read/file-metadata.js
|
|
138212
|
+
import path21 from "path";
|
|
138213
|
+
|
|
138214
|
+
class FileMetadataExtractor {
|
|
138215
|
+
symbolGraph;
|
|
138118
138216
|
constructor(symbolGraph) {
|
|
138119
|
-
this.compressor = new CodeCompressor;
|
|
138120
138217
|
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
138218
|
}
|
|
138127
|
-
async
|
|
138128
|
-
const
|
|
138129
|
-
|
|
138130
|
-
const
|
|
138131
|
-
const
|
|
138132
|
-
|
|
138133
|
-
|
|
138134
|
-
|
|
138135
|
-
|
|
138136
|
-
|
|
138137
|
-
|
|
138138
|
-
|
|
138139
|
-
|
|
138140
|
-
|
|
138219
|
+
async extractMetadata(content, filePath, options) {
|
|
138220
|
+
const lines = content.split(`
|
|
138221
|
+
`);
|
|
138222
|
+
const language = this.detectLanguage(filePath);
|
|
138223
|
+
const metadata = {
|
|
138224
|
+
totalLines: lines.length,
|
|
138225
|
+
language
|
|
138226
|
+
};
|
|
138227
|
+
if (options.includeImports && language) {
|
|
138228
|
+
metadata.imports = this.extractImports(lines, language);
|
|
138229
|
+
}
|
|
138230
|
+
if (options.includeSymbols && this.symbolGraph && options.projectId) {
|
|
138231
|
+
try {
|
|
138232
|
+
const queryPath = options.relativePath || filePath;
|
|
138233
|
+
const { definitions } = await this.symbolGraph.listDefinitions(options.projectId, {
|
|
138234
|
+
file: queryPath,
|
|
138235
|
+
limit: 100
|
|
138236
|
+
});
|
|
138237
|
+
metadata.symbols = {
|
|
138238
|
+
definitions: definitions.length,
|
|
138239
|
+
references: 0
|
|
138141
138240
|
};
|
|
138241
|
+
} catch (error51) {
|
|
138242
|
+
logger.debug("Failed to get symbol metadata", { filePath, error: error51 });
|
|
138142
138243
|
}
|
|
138143
|
-
|
|
138144
|
-
|
|
138145
|
-
|
|
138146
|
-
|
|
138147
|
-
|
|
138148
|
-
|
|
138149
|
-
|
|
138244
|
+
}
|
|
138245
|
+
return metadata;
|
|
138246
|
+
}
|
|
138247
|
+
detectLanguage(filePath) {
|
|
138248
|
+
const ext2 = path21.extname(filePath).toLowerCase();
|
|
138249
|
+
const languageMap2 = {
|
|
138250
|
+
".ts": "TypeScript",
|
|
138251
|
+
".tsx": "TypeScript",
|
|
138252
|
+
".js": "JavaScript",
|
|
138253
|
+
".jsx": "JavaScript",
|
|
138254
|
+
".vue": "Vue",
|
|
138255
|
+
".py": "Python",
|
|
138256
|
+
".go": "Go",
|
|
138257
|
+
".rs": "Rust",
|
|
138258
|
+
".java": "Java",
|
|
138259
|
+
".cpp": "C++",
|
|
138260
|
+
".c": "C",
|
|
138261
|
+
".h": "C",
|
|
138262
|
+
".hpp": "C++",
|
|
138263
|
+
".cs": "C#",
|
|
138264
|
+
".rb": "Ruby",
|
|
138265
|
+
".php": "PHP",
|
|
138266
|
+
".swift": "Swift",
|
|
138267
|
+
".kt": "Kotlin",
|
|
138268
|
+
".kts": "Kotlin",
|
|
138269
|
+
".scala": "Scala",
|
|
138270
|
+
".md": "Markdown",
|
|
138271
|
+
".json": "JSON",
|
|
138272
|
+
".yaml": "YAML",
|
|
138273
|
+
".yml": "YAML",
|
|
138274
|
+
".xml": "XML",
|
|
138275
|
+
".html": "HTML",
|
|
138276
|
+
".css": "CSS",
|
|
138277
|
+
".scss": "SCSS",
|
|
138278
|
+
".sql": "SQL",
|
|
138279
|
+
".sh": "Shell",
|
|
138280
|
+
".bash": "Shell"
|
|
138281
|
+
};
|
|
138282
|
+
return languageMap2[ext2];
|
|
138283
|
+
}
|
|
138284
|
+
extractImports(lines, language) {
|
|
138285
|
+
const imports = [];
|
|
138286
|
+
const importPatterns = {
|
|
138287
|
+
TypeScript: /^(import\s+.*?from\s+['"]|import\s+['"])/,
|
|
138288
|
+
JavaScript: /^(import\s+.*?from\s+['"]|import\s+['"]|require\s*\(\s*['"])/,
|
|
138289
|
+
Python: /^(import\s+|from\s+\S+\s+import)/,
|
|
138290
|
+
Go: /^import\s+/,
|
|
138291
|
+
Java: /^import\s+/,
|
|
138292
|
+
Rust: /^use\s+/
|
|
138293
|
+
};
|
|
138294
|
+
const pattern = importPatterns[language];
|
|
138295
|
+
if (!pattern)
|
|
138296
|
+
return imports;
|
|
138297
|
+
for (const line of lines) {
|
|
138298
|
+
const trimmed = line.trim();
|
|
138299
|
+
if (pattern.test(trimmed)) {
|
|
138300
|
+
imports.push(trimmed);
|
|
138150
138301
|
}
|
|
138151
|
-
|
|
138152
|
-
|
|
138153
|
-
|
|
138154
|
-
|
|
138155
|
-
|
|
138156
|
-
|
|
138157
|
-
|
|
138158
|
-
|
|
138159
|
-
|
|
138302
|
+
}
|
|
138303
|
+
return imports;
|
|
138304
|
+
}
|
|
138305
|
+
}
|
|
138306
|
+
var init_file_metadata = __esm(() => {
|
|
138307
|
+
init_dist();
|
|
138308
|
+
});
|
|
138309
|
+
|
|
138310
|
+
// ../../packages/core/dist/services/file-read/line-range.js
|
|
138311
|
+
function calculateRange(params) {
|
|
138312
|
+
if (params.lineStart !== undefined && params.lineEnd !== undefined) {
|
|
138313
|
+
return {
|
|
138314
|
+
start: Math.max(1, params.lineStart),
|
|
138315
|
+
end: params.lineEnd
|
|
138316
|
+
};
|
|
138317
|
+
}
|
|
138318
|
+
if (params.offset !== undefined) {
|
|
138319
|
+
const offset = Math.max(1, params.offset);
|
|
138320
|
+
const limit = params.limit || 1000;
|
|
138321
|
+
return {
|
|
138322
|
+
start: offset,
|
|
138323
|
+
end: offset + limit - 1
|
|
138324
|
+
};
|
|
138325
|
+
}
|
|
138326
|
+
return {
|
|
138327
|
+
start: 1,
|
|
138328
|
+
end: Infinity
|
|
138329
|
+
};
|
|
138330
|
+
}
|
|
138331
|
+
function adjustRange(range, totalLines) {
|
|
138332
|
+
const start = Math.max(1, Math.min(range.start, totalLines));
|
|
138333
|
+
const end = range.end === Infinity ? totalLines : Math.min(range.end, totalLines);
|
|
138334
|
+
return { start, end };
|
|
138335
|
+
}
|
|
138336
|
+
function extractLines(lines, range) {
|
|
138337
|
+
const start = range.start - 1;
|
|
138338
|
+
const end = range.end;
|
|
138339
|
+
const selectedLines = lines.slice(start, end);
|
|
138340
|
+
return selectedLines.map((line, index) => {
|
|
138341
|
+
const lineNum = start + index + 1;
|
|
138342
|
+
return `${lineNum.toString().padStart(6, " ")}: ${line}`;
|
|
138343
|
+
}).join(`
|
|
138160
138344
|
`);
|
|
138161
|
-
|
|
138162
|
-
|
|
138163
|
-
|
|
138164
|
-
|
|
138345
|
+
}
|
|
138346
|
+
function selectLines(lines, range) {
|
|
138347
|
+
let content = extractLines(lines, range);
|
|
138348
|
+
let lineCount = content.split(`
|
|
138165
138349
|
`).length;
|
|
138166
|
-
|
|
138167
|
-
|
|
138168
|
-
|
|
138169
|
-
|
|
138350
|
+
let clipped = false;
|
|
138351
|
+
if (lineCount > MASSA_AI_READ_FILE_MAX_LINES) {
|
|
138352
|
+
const cappedLines = lines.slice(range.start - 1, range.start - 1 + MASSA_AI_READ_FILE_MAX_LINES);
|
|
138353
|
+
content = cappedLines.join(`
|
|
138170
138354
|
`);
|
|
138171
|
-
|
|
138355
|
+
lineCount = content.split(`
|
|
138172
138356
|
`).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
|
-
}
|
|
138357
|
+
clipped = true;
|
|
138358
|
+
}
|
|
138359
|
+
return { content, lineCount, clipped };
|
|
138360
|
+
}
|
|
138361
|
+
var MASSA_AI_READ_FILE_MAX_LINES;
|
|
138362
|
+
var init_line_range = __esm(() => {
|
|
138363
|
+
MASSA_AI_READ_FILE_MAX_LINES = (() => {
|
|
138364
|
+
const v = Number(process.env.MASSA_AI_READ_FILE_MAX_LINES);
|
|
138365
|
+
return Number.isFinite(v) && v > 0 ? Math.floor(v) : 500;
|
|
138366
|
+
})();
|
|
138367
|
+
});
|
|
138368
|
+
|
|
138369
|
+
// ../../packages/core/dist/services/file-read/path-containment.js
|
|
138370
|
+
import path22 from "path";
|
|
138371
|
+
|
|
138372
|
+
class PathContainment {
|
|
138373
|
+
projectRoots;
|
|
138374
|
+
constructor(projectRoots) {
|
|
138375
|
+
this.projectRoots = projectRoots;
|
|
138243
138376
|
}
|
|
138244
138377
|
async resolveFilePath(filePath, projectId) {
|
|
138245
|
-
if (
|
|
138246
|
-
return
|
|
138378
|
+
if (path22.isAbsolute(filePath)) {
|
|
138379
|
+
return path22.resolve(filePath);
|
|
138247
138380
|
}
|
|
138248
138381
|
if (projectId) {
|
|
138249
|
-
const root = await this.getProjectRoot(projectId);
|
|
138382
|
+
const root = await this.projectRoots.getProjectRoot(projectId);
|
|
138250
138383
|
if (root) {
|
|
138251
138384
|
const cleaned = sanitizeFilePath(filePath);
|
|
138252
|
-
return
|
|
138385
|
+
return path22.resolve(root, cleaned);
|
|
138253
138386
|
}
|
|
138254
138387
|
return null;
|
|
138255
138388
|
}
|
|
@@ -138258,19 +138391,19 @@ class ReadFileTool {
|
|
|
138258
138391
|
async checkPathContainment(absoluteFilePath, projectId) {
|
|
138259
138392
|
const roots = [];
|
|
138260
138393
|
if (projectId) {
|
|
138261
|
-
const root = await this.getProjectRoot(projectId);
|
|
138394
|
+
const root = await this.projectRoots.getProjectRoot(projectId);
|
|
138262
138395
|
if (root)
|
|
138263
|
-
roots.push(
|
|
138396
|
+
roots.push(path22.resolve(root));
|
|
138264
138397
|
}
|
|
138265
|
-
roots.push(
|
|
138398
|
+
roots.push(path22.resolve(process.cwd()));
|
|
138266
138399
|
const envRoots = (process.env.MASSA_AI_READ_FILE_ROOTS ?? "").split(":").map((s) => s.trim()).filter((s) => s.length > 0);
|
|
138267
138400
|
for (const extra of envRoots) {
|
|
138268
|
-
roots.push(
|
|
138401
|
+
roots.push(path22.resolve(extra));
|
|
138269
138402
|
}
|
|
138270
|
-
const target =
|
|
138403
|
+
const target = path22.resolve(absoluteFilePath);
|
|
138271
138404
|
for (const root of roots) {
|
|
138272
|
-
const rel =
|
|
138273
|
-
if (rel !== "" && !rel.startsWith("..") && !
|
|
138405
|
+
const rel = path22.relative(root, target);
|
|
138406
|
+
if (rel !== "" && !rel.startsWith("..") && !path22.isAbsolute(rel)) {
|
|
138274
138407
|
return { allowed: true };
|
|
138275
138408
|
}
|
|
138276
138409
|
if (rel === "")
|
|
@@ -138286,6 +138419,23 @@ ${validRootsList}
|
|
|
138286
138419
|
` + `Provide a filePath that resolves under one of these roots.`
|
|
138287
138420
|
};
|
|
138288
138421
|
}
|
|
138422
|
+
}
|
|
138423
|
+
var init_path_containment = __esm(() => {
|
|
138424
|
+
init_dist();
|
|
138425
|
+
});
|
|
138426
|
+
|
|
138427
|
+
// ../../packages/core/dist/services/file-read/project-root-cache.js
|
|
138428
|
+
class ProjectRootCache {
|
|
138429
|
+
projectRootCache = new Map;
|
|
138430
|
+
ROOT_CACHE_TTL = 300000;
|
|
138431
|
+
PROJECT_ROOT_CACHE_MAX_ENTRIES = 512;
|
|
138432
|
+
constructor() {
|
|
138433
|
+
eventBus.subscribe("indexing:started", ({ projectId, projectPath: projectPath2 }) => {
|
|
138434
|
+
this.projectRootCache.delete(projectId);
|
|
138435
|
+
evictOldest(this.projectRootCache, this.PROJECT_ROOT_CACHE_MAX_ENTRIES - 1);
|
|
138436
|
+
this.projectRootCache.set(projectId, projectPath2);
|
|
138437
|
+
});
|
|
138438
|
+
}
|
|
138289
138439
|
async getProjectRoot(projectId) {
|
|
138290
138440
|
const cached2 = this.projectRootCache.get(projectId);
|
|
138291
138441
|
if (cached2 !== undefined) {
|
|
@@ -138296,7 +138446,7 @@ ${validRootsList}
|
|
|
138296
138446
|
try {
|
|
138297
138447
|
const workspace = await workspaceManager.getWorkspace(projectId);
|
|
138298
138448
|
if (workspace?.project_path) {
|
|
138299
|
-
|
|
138449
|
+
evictOldest(this.projectRootCache, this.PROJECT_ROOT_CACHE_MAX_ENTRIES - 1);
|
|
138300
138450
|
this.projectRootCache.set(projectId, workspace.project_path);
|
|
138301
138451
|
return workspace.project_path;
|
|
138302
138452
|
}
|
|
@@ -138305,182 +138455,236 @@ ${validRootsList}
|
|
|
138305
138455
|
}
|
|
138306
138456
|
return null;
|
|
138307
138457
|
}
|
|
138308
|
-
|
|
138309
|
-
|
|
138310
|
-
|
|
138311
|
-
|
|
138312
|
-
|
|
138313
|
-
|
|
138314
|
-
|
|
138315
|
-
|
|
138316
|
-
|
|
138317
|
-
|
|
138458
|
+
}
|
|
138459
|
+
var init_project_root_cache = __esm(() => {
|
|
138460
|
+
init_dist();
|
|
138461
|
+
init_event_bus();
|
|
138462
|
+
init_workspace_manager();
|
|
138463
|
+
});
|
|
138464
|
+
|
|
138465
|
+
// ../../packages/core/dist/services/file-read/read-file.service.js
|
|
138466
|
+
function readFileOptions(p) {
|
|
138467
|
+
const shouldCompress = p.compress !== false;
|
|
138468
|
+
const targetRatio = p.targetRatio || 0.3;
|
|
138469
|
+
const format = p.format || "json";
|
|
138470
|
+
const { fields } = p;
|
|
138471
|
+
const includeSymbols = p.includeSymbols !== false;
|
|
138472
|
+
const includeImports = p.includeImports !== false;
|
|
138473
|
+
return { shouldCompress, targetRatio, format, fields, includeSymbols, includeImports };
|
|
138474
|
+
}
|
|
138475
|
+
|
|
138476
|
+
class ReadFileService {
|
|
138477
|
+
compressor;
|
|
138478
|
+
symbolGraph;
|
|
138479
|
+
projectRoots;
|
|
138480
|
+
pathContainment;
|
|
138481
|
+
fileMetadata;
|
|
138482
|
+
fileContent;
|
|
138483
|
+
constructor(symbolGraph) {
|
|
138484
|
+
this.compressor = new CodeCompressor;
|
|
138485
|
+
this.symbolGraph = symbolGraph;
|
|
138486
|
+
this.projectRoots = new ProjectRootCache;
|
|
138487
|
+
this.pathContainment = new PathContainment(this.projectRoots);
|
|
138488
|
+
this.fileMetadata = new FileMetadataExtractor(symbolGraph);
|
|
138489
|
+
this.fileContent = new FileContentCache((content, filePath, options) => this.fileMetadata.extractMetadata(content, filePath, options));
|
|
138490
|
+
}
|
|
138491
|
+
async read(p, options) {
|
|
138492
|
+
const { shouldCompress, targetRatio, includeSymbols, includeImports } = options;
|
|
138493
|
+
const resolved = await this.pathContainment.resolveFilePath(p.filePath, p.projectId);
|
|
138494
|
+
if (resolved === null) {
|
|
138318
138495
|
return {
|
|
138319
|
-
|
|
138320
|
-
|
|
138496
|
+
ok: false,
|
|
138497
|
+
error: "Relative filePath requires a projectId (to resolve against the workspace) or an absolute path."
|
|
138321
138498
|
};
|
|
138322
138499
|
}
|
|
138323
|
-
|
|
138324
|
-
|
|
138325
|
-
|
|
138500
|
+
const filePath = resolved;
|
|
138501
|
+
const containment = await this.pathContainment.checkPathContainment(filePath, p.projectId);
|
|
138502
|
+
if (!containment.allowed) {
|
|
138326
138503
|
return {
|
|
138327
|
-
|
|
138328
|
-
|
|
138504
|
+
ok: false,
|
|
138505
|
+
error: containment.error
|
|
138329
138506
|
};
|
|
138330
138507
|
}
|
|
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
|
|
138508
|
+
const relativePath = p.filePath;
|
|
138509
|
+
const range = calculateRange(p);
|
|
138510
|
+
const { content, metadata } = await this.fileContent.readFileWithCache(filePath, {
|
|
138511
|
+
includeSymbols,
|
|
138512
|
+
includeImports,
|
|
138513
|
+
projectId: p.projectId,
|
|
138514
|
+
relativePath
|
|
138371
138515
|
});
|
|
138372
|
-
logger.debug("File read and cached", { filePath });
|
|
138373
|
-
return { content, metadata };
|
|
138374
|
-
}
|
|
138375
|
-
async extractMetadata(content, filePath, options) {
|
|
138376
138516
|
const lines = content.split(`
|
|
138377
138517
|
`);
|
|
138378
|
-
const
|
|
138379
|
-
const
|
|
138380
|
-
|
|
138381
|
-
|
|
138518
|
+
const totalLines = lines.length;
|
|
138519
|
+
const adjustedRange = adjustRange(range, totalLines);
|
|
138520
|
+
const { content: selectedContent, lineCount: selectedLineCount, clipped: source_clipped } = selectLines(lines, adjustedRange);
|
|
138521
|
+
const shouldAutoCompress = shouldCompress && selectedLineCount > 100 && targetRatio < 1;
|
|
138522
|
+
const result = {
|
|
138523
|
+
filePath: p.filePath,
|
|
138524
|
+
absolutePath: filePath,
|
|
138525
|
+
lineRange: {
|
|
138526
|
+
requested: {
|
|
138527
|
+
start: range.start,
|
|
138528
|
+
end: range.end === Infinity ? null : range.end
|
|
138529
|
+
},
|
|
138530
|
+
actual: {
|
|
138531
|
+
start: adjustedRange.start,
|
|
138532
|
+
end: source_clipped ? adjustedRange.start + selectedLineCount - 1 : adjustedRange.end,
|
|
138533
|
+
total: totalLines
|
|
138534
|
+
},
|
|
138535
|
+
selected: selectedLineCount
|
|
138536
|
+
},
|
|
138537
|
+
source_clipped,
|
|
138538
|
+
metadata: {
|
|
138539
|
+
totalLines,
|
|
138540
|
+
language: metadata.language,
|
|
138541
|
+
...metadata.symbols && { symbols: metadata.symbols },
|
|
138542
|
+
...metadata.imports && { imports: metadata.imports }
|
|
138543
|
+
},
|
|
138544
|
+
compressed: shouldAutoCompress,
|
|
138545
|
+
recommendations: []
|
|
138382
138546
|
};
|
|
138383
|
-
if (
|
|
138384
|
-
|
|
138385
|
-
|
|
138386
|
-
|
|
138387
|
-
|
|
138388
|
-
|
|
138389
|
-
|
|
138390
|
-
|
|
138391
|
-
|
|
138392
|
-
|
|
138393
|
-
|
|
138394
|
-
|
|
138395
|
-
|
|
138396
|
-
|
|
138397
|
-
|
|
138398
|
-
|
|
138547
|
+
if (shouldAutoCompress) {
|
|
138548
|
+
const compressed = await this.compressor.compress(selectedContent, "code_structure");
|
|
138549
|
+
const originalTokens = estimateTokens(selectedContent, "code");
|
|
138550
|
+
const compressedTokens = estimateTokens(compressed.compressed, "code");
|
|
138551
|
+
const actualRatio = compressedTokens / originalTokens;
|
|
138552
|
+
result.content = compressed.compressed;
|
|
138553
|
+
result.tokens = {
|
|
138554
|
+
original: originalTokens,
|
|
138555
|
+
compressed: compressedTokens,
|
|
138556
|
+
saved: originalTokens - compressedTokens,
|
|
138557
|
+
savingsPercent: Math.round((1 - actualRatio) * 100)
|
|
138558
|
+
};
|
|
138559
|
+
result.compressionRatio = actualRatio;
|
|
138560
|
+
result.recommendations.push(`\u2713 Auto-compressed ${selectedLineCount} lines (${result.tokens.savingsPercent}% reduction)`);
|
|
138561
|
+
} else {
|
|
138562
|
+
result.content = selectedContent;
|
|
138563
|
+
result.tokens = {
|
|
138564
|
+
original: estimateTokens(selectedContent, "code"),
|
|
138565
|
+
compressed: estimateTokens(selectedContent, "code"),
|
|
138566
|
+
saved: 0,
|
|
138567
|
+
savingsPercent: 0
|
|
138568
|
+
};
|
|
138569
|
+
if (selectedLineCount > 100) {
|
|
138570
|
+
result.recommendations.push("\uD83D\uDCA1 Content > 100 lines. Consider compress=true for token savings");
|
|
138399
138571
|
}
|
|
138400
138572
|
}
|
|
138401
|
-
|
|
138402
|
-
|
|
138403
|
-
|
|
138404
|
-
|
|
138405
|
-
|
|
138406
|
-
|
|
138407
|
-
return
|
|
138408
|
-
const lineNum = start + index + 1;
|
|
138409
|
-
return `${lineNum.toString().padStart(6, " ")}: ${line}`;
|
|
138410
|
-
}).join(`
|
|
138411
|
-
`);
|
|
138573
|
+
if (range.start === 1 && range.end === Infinity) {
|
|
138574
|
+
result.recommendations.push("\uD83D\uDCA1 Use lineStart/lineEnd or offset/limit to read specific sections (60% token savings)");
|
|
138575
|
+
}
|
|
138576
|
+
if (metadata.symbols && metadata.symbols.definitions > 0) {
|
|
138577
|
+
result.recommendations.push(`\uD83D\uDCA1 Use get_references() to find usages of ${metadata.symbols.definitions} symbols in this file`);
|
|
138578
|
+
}
|
|
138579
|
+
return { ok: true, data: result };
|
|
138412
138580
|
}
|
|
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
|
-
|
|
138581
|
+
}
|
|
138582
|
+
var init_read_file_service = __esm(() => {
|
|
138583
|
+
init_dist();
|
|
138584
|
+
init_code_compressor();
|
|
138585
|
+
init_file_content_cache();
|
|
138586
|
+
init_file_metadata();
|
|
138587
|
+
init_line_range();
|
|
138588
|
+
init_path_containment();
|
|
138589
|
+
init_project_root_cache();
|
|
138590
|
+
});
|
|
138591
|
+
|
|
138592
|
+
// ../../packages/core/dist/tools/read_file.js
|
|
138593
|
+
class ReadFileTool {
|
|
138594
|
+
name = "read_file";
|
|
138595
|
+
description = "Read file with automatic compression, caching, and symbol metadata. " + "Use with search results for 60% token savings.";
|
|
138596
|
+
inputSchema = {
|
|
138597
|
+
type: "object",
|
|
138598
|
+
properties: {
|
|
138599
|
+
filePath: {
|
|
138600
|
+
type: "string",
|
|
138601
|
+
description: "File path (absolute or relative to project root)"
|
|
138602
|
+
},
|
|
138603
|
+
projectId: {
|
|
138604
|
+
type: "string",
|
|
138605
|
+
description: "Project ID for symbol metadata (optional)"
|
|
138606
|
+
},
|
|
138607
|
+
offset: {
|
|
138608
|
+
type: "number",
|
|
138609
|
+
description: "Start line number (1-indexed)"
|
|
138610
|
+
},
|
|
138611
|
+
limit: {
|
|
138612
|
+
type: "number",
|
|
138613
|
+
description: "Number of lines to read"
|
|
138614
|
+
},
|
|
138615
|
+
lineStart: {
|
|
138616
|
+
type: "number",
|
|
138617
|
+
description: "Start line (alternative to offset)"
|
|
138618
|
+
},
|
|
138619
|
+
lineEnd: {
|
|
138620
|
+
type: "number",
|
|
138621
|
+
description: "End line (alternative to limit)"
|
|
138622
|
+
},
|
|
138623
|
+
compress: {
|
|
138624
|
+
type: "boolean",
|
|
138625
|
+
description: "Auto-compress content > 100 lines (default: true)",
|
|
138626
|
+
default: true
|
|
138627
|
+
},
|
|
138628
|
+
targetRatio: {
|
|
138629
|
+
type: "number",
|
|
138630
|
+
description: "Compression target ratio (0.3 = 70% reduction)",
|
|
138631
|
+
default: 0.3
|
|
138632
|
+
},
|
|
138633
|
+
format: {
|
|
138634
|
+
type: "string",
|
|
138635
|
+
enum: ["json", "toon"],
|
|
138636
|
+
description: "Output format",
|
|
138637
|
+
default: "json"
|
|
138638
|
+
},
|
|
138639
|
+
fields: {
|
|
138640
|
+
type: "array",
|
|
138641
|
+
items: { type: "string" },
|
|
138642
|
+
description: "Projection \u2014 keep only these keys (dotted paths supported, e.g. ['nodes.symbol']). Absent/empty \u2192 full data."
|
|
138643
|
+
},
|
|
138644
|
+
includeSymbols: {
|
|
138645
|
+
type: "boolean",
|
|
138646
|
+
description: "Include symbol metadata from graph (default: true)",
|
|
138647
|
+
default: true
|
|
138648
|
+
},
|
|
138649
|
+
includeImports: {
|
|
138650
|
+
type: "boolean",
|
|
138651
|
+
description: "Extract and show import statements (default: true)",
|
|
138652
|
+
default: true
|
|
138653
|
+
}
|
|
138654
|
+
},
|
|
138655
|
+
required: ["filePath"]
|
|
138656
|
+
};
|
|
138657
|
+
service;
|
|
138658
|
+
constructor(symbolGraph) {
|
|
138659
|
+
this.service = new ReadFileService(symbolGraph);
|
|
138449
138660
|
}
|
|
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);
|
|
138661
|
+
async handle(params) {
|
|
138662
|
+
const p = params;
|
|
138663
|
+
const options = readFileOptions(p);
|
|
138664
|
+
try {
|
|
138665
|
+
const outcome2 = await this.service.read(p, options);
|
|
138666
|
+
if (!outcome2.ok) {
|
|
138667
|
+
return { success: false, error: outcome2.error };
|
|
138467
138668
|
}
|
|
138669
|
+
return serializeToolResponse(outcome2.data, {
|
|
138670
|
+
format: options.format,
|
|
138671
|
+
fields: options.fields
|
|
138672
|
+
});
|
|
138673
|
+
} catch (error51) {
|
|
138674
|
+
logger.error("Failed to read file", error51, {
|
|
138675
|
+
filePath: p.filePath
|
|
138676
|
+
});
|
|
138677
|
+
return {
|
|
138678
|
+
success: false,
|
|
138679
|
+
error: `Failed to read file: ${error51.message}`
|
|
138680
|
+
};
|
|
138468
138681
|
}
|
|
138469
|
-
return imports;
|
|
138470
138682
|
}
|
|
138471
138683
|
}
|
|
138472
|
-
var MASSA_AI_READ_FILE_MAX_LINES;
|
|
138473
138684
|
var init_read_file = __esm(() => {
|
|
138474
138685
|
init_dist();
|
|
138475
|
-
init_dist();
|
|
138476
|
-
init_code_compressor();
|
|
138477
138686
|
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
|
-
})();
|
|
138687
|
+
init_read_file_service();
|
|
138484
138688
|
});
|
|
138485
138689
|
|
|
138486
138690
|
// ../../packages/core/dist/tools/execute.js
|
|
@@ -141415,7 +141619,7 @@ var init_l1_memory_cache = __esm(() => {
|
|
|
141415
141619
|
// ../../packages/core/dist/services/health/local-health-checker.js
|
|
141416
141620
|
import fs11 from "fs/promises";
|
|
141417
141621
|
import { existsSync as existsSync3 } from "fs";
|
|
141418
|
-
import
|
|
141622
|
+
import path23 from "path";
|
|
141419
141623
|
|
|
141420
141624
|
class LocalHealthChecker {
|
|
141421
141625
|
ollamaBaseUrl = process.env.OLLAMA_BASE_URL || "http://localhost:11434";
|
|
@@ -141450,7 +141654,7 @@ class LocalHealthChecker {
|
|
|
141450
141654
|
try {
|
|
141451
141655
|
if (!existsSync3(this.dataDir))
|
|
141452
141656
|
await fs11.mkdir(this.dataDir, { recursive: true });
|
|
141453
|
-
const probe2 =
|
|
141657
|
+
const probe2 = path23.join(this.dataDir, ".health-check-test");
|
|
141454
141658
|
await fs11.writeFile(probe2, "ok");
|
|
141455
141659
|
await fs11.unlink(probe2);
|
|
141456
141660
|
return { available: true, latency: Date.now() - start, details: { path: this.dataDir, writable: true } };
|
|
@@ -143393,7 +143597,7 @@ var init_scheduler2 = __esm(() => {
|
|
|
143393
143597
|
// ../../packages/core/dist/services/pricing/models-dev-client.js
|
|
143394
143598
|
import fs12 from "fs/promises";
|
|
143395
143599
|
import { existsSync as existsSync4 } from "fs";
|
|
143396
|
-
import
|
|
143600
|
+
import path24 from "path";
|
|
143397
143601
|
function getModelsDevClient() {
|
|
143398
143602
|
if (!clientInstance) {
|
|
143399
143603
|
clientInstance = new ModelsDevClient;
|
|
@@ -143413,7 +143617,7 @@ var init_models_dev_client = __esm(() => {
|
|
|
143413
143617
|
memoryCacheTimestamp = 0;
|
|
143414
143618
|
getLocalCachePath() {
|
|
143415
143619
|
const dataDir = config2.get("dataDir");
|
|
143416
|
-
return
|
|
143620
|
+
return path24.join(dataDir, ModelsDevClient.LOCAL_CACHE_FILE);
|
|
143417
143621
|
}
|
|
143418
143622
|
async loadLocalCache() {
|
|
143419
143623
|
const cachePath = this.getLocalCachePath();
|
|
@@ -143448,7 +143652,7 @@ var init_models_dev_client = __esm(() => {
|
|
|
143448
143652
|
async saveLocalCache(models) {
|
|
143449
143653
|
const cachePath = this.getLocalCachePath();
|
|
143450
143654
|
try {
|
|
143451
|
-
const dir =
|
|
143655
|
+
const dir = path24.dirname(cachePath);
|
|
143452
143656
|
await fs12.mkdir(dir, { recursive: true });
|
|
143453
143657
|
const data = {
|
|
143454
143658
|
timestamp: Date.now(),
|
|
@@ -149339,33 +149543,33 @@ var require_URL = __commonJS((exports, module) => {
|
|
|
149339
149543
|
else
|
|
149340
149544
|
return basepath.substring(0, lastslash + 1) + refpath;
|
|
149341
149545
|
}
|
|
149342
|
-
function remove_dot_segments(
|
|
149343
|
-
if (!
|
|
149344
|
-
return
|
|
149546
|
+
function remove_dot_segments(path25) {
|
|
149547
|
+
if (!path25)
|
|
149548
|
+
return path25;
|
|
149345
149549
|
var output = "";
|
|
149346
|
-
while (
|
|
149347
|
-
if (
|
|
149348
|
-
|
|
149550
|
+
while (path25.length > 0) {
|
|
149551
|
+
if (path25 === "." || path25 === "..") {
|
|
149552
|
+
path25 = "";
|
|
149349
149553
|
break;
|
|
149350
149554
|
}
|
|
149351
|
-
var twochars =
|
|
149352
|
-
var threechars =
|
|
149353
|
-
var fourchars =
|
|
149555
|
+
var twochars = path25.substring(0, 2);
|
|
149556
|
+
var threechars = path25.substring(0, 3);
|
|
149557
|
+
var fourchars = path25.substring(0, 4);
|
|
149354
149558
|
if (threechars === "../") {
|
|
149355
|
-
|
|
149559
|
+
path25 = path25.substring(3);
|
|
149356
149560
|
} else if (twochars === "./") {
|
|
149357
|
-
|
|
149561
|
+
path25 = path25.substring(2);
|
|
149358
149562
|
} else if (threechars === "/./") {
|
|
149359
|
-
|
|
149360
|
-
} else if (twochars === "/." &&
|
|
149361
|
-
|
|
149362
|
-
} else if (fourchars === "/../" || threechars === "/.." &&
|
|
149363
|
-
|
|
149563
|
+
path25 = "/" + path25.substring(3);
|
|
149564
|
+
} else if (twochars === "/." && path25.length === 2) {
|
|
149565
|
+
path25 = "/";
|
|
149566
|
+
} else if (fourchars === "/../" || threechars === "/.." && path25.length === 3) {
|
|
149567
|
+
path25 = "/" + path25.substring(4);
|
|
149364
149568
|
output = output.replace(/\/?[^\/]*$/, "");
|
|
149365
149569
|
} else {
|
|
149366
|
-
var segment =
|
|
149570
|
+
var segment = path25.match(/(\/?([^\/]*))/)[0];
|
|
149367
149571
|
output += segment;
|
|
149368
|
-
|
|
149572
|
+
path25 = path25.substring(segment.length);
|
|
149369
149573
|
}
|
|
149370
149574
|
}
|
|
149371
149575
|
return output;
|
|
@@ -161435,21 +161639,21 @@ function jsonToKeyPathChunks(value, label = "$") {
|
|
|
161435
161639
|
walk(value, label, out);
|
|
161436
161640
|
return out;
|
|
161437
161641
|
}
|
|
161438
|
-
function walk(val,
|
|
161642
|
+
function walk(val, path25, out) {
|
|
161439
161643
|
if (val === null || val === undefined)
|
|
161440
161644
|
return;
|
|
161441
161645
|
if (Array.isArray(val)) {
|
|
161442
161646
|
if (val.length === 0) {
|
|
161443
|
-
out.push({ path:
|
|
161647
|
+
out.push({ path: path25, content: `**${path25}** = _[]_` });
|
|
161444
161648
|
return;
|
|
161445
161649
|
}
|
|
161446
161650
|
if (val.every((v) => v !== null && typeof v === "object")) {
|
|
161447
|
-
val.forEach((v, i) => walk(v, `${
|
|
161651
|
+
val.forEach((v, i) => walk(v, `${path25}[${i}]`, out));
|
|
161448
161652
|
return;
|
|
161449
161653
|
}
|
|
161450
161654
|
const items = val.map((v) => `- \`${String(v)}\``).join(`
|
|
161451
161655
|
`);
|
|
161452
|
-
out.push({ path:
|
|
161656
|
+
out.push({ path: path25, content: `**${path25}**
|
|
161453
161657
|
|
|
161454
161658
|
${items}` });
|
|
161455
161659
|
return;
|
|
@@ -161457,16 +161661,16 @@ ${items}` });
|
|
|
161457
161661
|
if (typeof val === "object") {
|
|
161458
161662
|
const entries = Object.entries(val);
|
|
161459
161663
|
if (entries.length === 0) {
|
|
161460
|
-
out.push({ path:
|
|
161664
|
+
out.push({ path: path25, content: `**${path25}** = _{}_` });
|
|
161461
161665
|
return;
|
|
161462
161666
|
}
|
|
161463
161667
|
for (const [k, v] of entries) {
|
|
161464
161668
|
const safeKey = /^[A-Za-z_$][\w$]*$/.test(k) ? k : JSON.stringify(k);
|
|
161465
|
-
walk(v, `${
|
|
161669
|
+
walk(v, `${path25}.${safeKey}`, out);
|
|
161466
161670
|
}
|
|
161467
161671
|
return;
|
|
161468
161672
|
}
|
|
161469
|
-
out.push({ path:
|
|
161673
|
+
out.push({ path: path25, content: `**${path25}** = \`${String(val)}\`` });
|
|
161470
161674
|
}
|
|
161471
161675
|
var gfm, STRIP_SELECTORS, tdCache = null;
|
|
161472
161676
|
var init_html_to_md = __esm(() => {
|
|
@@ -161732,12 +161936,7 @@ class WebController {
|
|
|
161732
161936
|
markIndexed: (key, ts) => {
|
|
161733
161937
|
this.cache.delete(key);
|
|
161734
161938
|
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
|
-
}
|
|
161939
|
+
evictOldest(this.cache, WEB_CACHE_MAX_ENTRIES);
|
|
161741
161940
|
}
|
|
161742
161941
|
};
|
|
161743
161942
|
}
|
|
@@ -162134,13 +162333,20 @@ class HookService {
|
|
|
162134
162333
|
});
|
|
162135
162334
|
const id = this.idFactory();
|
|
162136
162335
|
this.queue.enqueue(async () => {
|
|
162336
|
+
const scrub = scrubCredentials(JSON.stringify(ev.payload));
|
|
162337
|
+
if (scrub.total > 0) {
|
|
162338
|
+
logger.debug("hook payload redacted before persist", {
|
|
162339
|
+
redactions: scrub.redactions,
|
|
162340
|
+
total: scrub.total
|
|
162341
|
+
});
|
|
162342
|
+
}
|
|
162137
162343
|
const obs = {
|
|
162138
162344
|
id,
|
|
162139
162345
|
projectId: attribution.projectId,
|
|
162140
162346
|
sessionId: ev.sessionId,
|
|
162141
162347
|
source: ev.event,
|
|
162142
162348
|
category: extractCategory(ev.event, ev.payload),
|
|
162143
|
-
payloadJson:
|
|
162349
|
+
payloadJson: scrub.sanitized,
|
|
162144
162350
|
importance: ev.importance,
|
|
162145
162351
|
createdAt: ev.ts,
|
|
162146
162352
|
agentId: ev.agentId,
|
|
@@ -162201,6 +162407,7 @@ var init_hook_service = __esm(() => {
|
|
|
162201
162407
|
init_observation_extractor();
|
|
162202
162408
|
init_observation_consolidation_job();
|
|
162203
162409
|
init_attribution_resolver();
|
|
162410
|
+
init_credential_scrub();
|
|
162204
162411
|
ValidationError = class ValidationError extends Error {
|
|
162205
162412
|
code;
|
|
162206
162413
|
constructor(code, message) {
|
|
@@ -162225,7 +162432,7 @@ var init_hook_service = __esm(() => {
|
|
|
162225
162432
|
// ../../packages/core/dist/services/bootstrap/bootstrap-service.js
|
|
162226
162433
|
import { randomUUID as randomUUID9 } from "crypto";
|
|
162227
162434
|
import fs13 from "fs";
|
|
162228
|
-
import
|
|
162435
|
+
import path25 from "path";
|
|
162229
162436
|
import { spawn as spawn2 } from "child_process";
|
|
162230
162437
|
function readBootstrapConfig() {
|
|
162231
162438
|
try {
|
|
@@ -162385,7 +162592,7 @@ async function scanSignals(_projectId, projectRoot, caps, symbolGraph, gitRunner
|
|
|
162385
162592
|
}
|
|
162386
162593
|
try {
|
|
162387
162594
|
for (const name26 of README_CANDIDATES) {
|
|
162388
|
-
const p =
|
|
162595
|
+
const p = path25.join(projectRoot, name26);
|
|
162389
162596
|
if (fs13.existsSync(p) && fs13.statSync(p).isFile()) {
|
|
162390
162597
|
const buf = fs13.readFileSync(p);
|
|
162391
162598
|
signals.readme = buf.slice(0, MAX_README_BYTES).toString("utf8");
|
|
@@ -162396,14 +162603,14 @@ async function scanSignals(_projectId, projectRoot, caps, symbolGraph, gitRunner
|
|
|
162396
162603
|
logger.debug("bootstrap scan: README read failed", { error: e.message });
|
|
162397
162604
|
}
|
|
162398
162605
|
try {
|
|
162399
|
-
const docsDir =
|
|
162606
|
+
const docsDir = path25.join(projectRoot, "docs");
|
|
162400
162607
|
if (fs13.existsSync(docsDir) && fs13.statSync(docsDir).isDirectory()) {
|
|
162401
162608
|
const entries = walkMarkdown(docsDir).slice(0, MAX_DOCS);
|
|
162402
162609
|
for (const rel of entries) {
|
|
162403
162610
|
try {
|
|
162404
162611
|
const buf = fs13.readFileSync(rel);
|
|
162405
162612
|
signals.docs.push({
|
|
162406
|
-
path:
|
|
162613
|
+
path: path25.relative(projectRoot, rel),
|
|
162407
162614
|
snippet: buf.slice(0, MAX_DOC_BYTES).toString("utf8")
|
|
162408
162615
|
});
|
|
162409
162616
|
} catch {}
|
|
@@ -162414,7 +162621,7 @@ async function scanSignals(_projectId, projectRoot, caps, symbolGraph, gitRunner
|
|
|
162414
162621
|
}
|
|
162415
162622
|
try {
|
|
162416
162623
|
for (const name26 of MANIFEST_FILES) {
|
|
162417
|
-
const p =
|
|
162624
|
+
const p = path25.join(projectRoot, name26);
|
|
162418
162625
|
if (!fs13.existsSync(p) || !fs13.statSync(p).isFile())
|
|
162419
162626
|
continue;
|
|
162420
162627
|
const raw2 = fs13.readFileSync(p).slice(0, MAX_MANIFEST_BYTES).toString("utf8");
|
|
@@ -162462,7 +162669,7 @@ function walkMarkdown(dir) {
|
|
|
162462
162669
|
continue;
|
|
162463
162670
|
}
|
|
162464
162671
|
for (const e of entries) {
|
|
162465
|
-
const full =
|
|
162672
|
+
const full = path25.join(cur, e.name);
|
|
162466
162673
|
if (e.isDirectory()) {
|
|
162467
162674
|
if (e.name === "node_modules" || e.name.startsWith("."))
|
|
162468
162675
|
continue;
|
|
@@ -165980,7 +166187,7 @@ init_dist();
|
|
|
165980
166187
|
init_dist15();
|
|
165981
166188
|
init_dist();
|
|
165982
166189
|
import fs14 from "fs/promises";
|
|
165983
|
-
import
|
|
166190
|
+
import path26 from "path";
|
|
165984
166191
|
var _indexProjectTool = null;
|
|
165985
166192
|
function indexProjectTool() {
|
|
165986
166193
|
if (!_indexProjectTool)
|
|
@@ -166250,7 +166457,7 @@ class EmbeddedApiClient {
|
|
|
166250
166457
|
} else {
|
|
166251
166458
|
end = start + 20;
|
|
166252
166459
|
}
|
|
166253
|
-
const absolutePath =
|
|
166460
|
+
const absolutePath = path26.join(workspace.project_path, file2);
|
|
166254
166461
|
const content = await fs14.readFile(absolutePath, "utf-8");
|
|
166255
166462
|
const lines = content.split(/\r?\n/);
|
|
166256
166463
|
const slice = lines.slice(start - 1, Math.min(lines.length, end));
|
|
@@ -166474,21 +166681,21 @@ class EmbeddedApiClient {
|
|
|
166474
166681
|
async uploadAndIndex(params) {
|
|
166475
166682
|
const rawBase = params.projectId || params.projectPath.replace(/\\/g, "/").split("/").filter(Boolean).pop() || "default";
|
|
166476
166683
|
const finalProjectId = rawBase.replace(/[^a-zA-Z0-9_.-]/g, "_").slice(0, 128);
|
|
166477
|
-
const uploadRoot = process.env.MASSA_AI_UPLOAD_DIR ||
|
|
166478
|
-
const stagingDir =
|
|
166684
|
+
const uploadRoot = process.env.MASSA_AI_UPLOAD_DIR || path26.join(getGlobalDataDir(), "uploads");
|
|
166685
|
+
const stagingDir = path26.resolve(uploadRoot, finalProjectId);
|
|
166479
166686
|
await fs14.rm(stagingDir, { recursive: true, force: true });
|
|
166480
166687
|
await fs14.mkdir(stagingDir, { recursive: true });
|
|
166481
166688
|
const WRITE_BATCH = 20;
|
|
166482
166689
|
for (let i = 0;i < params.files.length; i += WRITE_BATCH) {
|
|
166483
166690
|
await Promise.all(params.files.slice(i, i + WRITE_BATCH).map(async (file2) => {
|
|
166484
|
-
if (
|
|
166691
|
+
if (path26.isAbsolute(file2.relativePath) || file2.relativePath.includes("..")) {
|
|
166485
166692
|
throw new Error(`Invalid file path: ${file2.relativePath}`);
|
|
166486
166693
|
}
|
|
166487
|
-
const dest =
|
|
166488
|
-
if (!dest.startsWith(stagingDir +
|
|
166694
|
+
const dest = path26.resolve(stagingDir, file2.relativePath.replace(/\//g, path26.sep));
|
|
166695
|
+
if (!dest.startsWith(stagingDir + path26.sep)) {
|
|
166489
166696
|
throw new Error(`Path escapes staging directory: ${file2.relativePath}`);
|
|
166490
166697
|
}
|
|
166491
|
-
await fs14.mkdir(
|
|
166698
|
+
await fs14.mkdir(path26.dirname(dest), { recursive: true });
|
|
166492
166699
|
await fs14.writeFile(dest, file2.content, "utf-8");
|
|
166493
166700
|
}));
|
|
166494
166701
|
}
|
|
@@ -166822,7 +167029,7 @@ class EmbeddedApiClient {
|
|
|
166822
167029
|
// src/file-collector.ts
|
|
166823
167030
|
init_config();
|
|
166824
167031
|
import fs15 from "fs/promises";
|
|
166825
|
-
import
|
|
167032
|
+
import path27 from "path";
|
|
166826
167033
|
var SKIP_DIRS = new Set([
|
|
166827
167034
|
"node_modules",
|
|
166828
167035
|
".git",
|
|
@@ -166872,13 +167079,13 @@ async function walk2(root2, dir, files, state, allowed) {
|
|
|
166872
167079
|
break;
|
|
166873
167080
|
if (entry2.isDirectory()) {
|
|
166874
167081
|
if (!SKIP_DIRS.has(entry2.name) && !entry2.name.startsWith(".")) {
|
|
166875
|
-
await walk2(root2,
|
|
167082
|
+
await walk2(root2, path27.join(dir, entry2.name), files, state, allowed);
|
|
166876
167083
|
}
|
|
166877
167084
|
} else if (entry2.isFile()) {
|
|
166878
|
-
const ext2 =
|
|
167085
|
+
const ext2 = path27.extname(entry2.name).toLowerCase();
|
|
166879
167086
|
if (!allowed.has(ext2))
|
|
166880
167087
|
continue;
|
|
166881
|
-
const fullPath =
|
|
167088
|
+
const fullPath = path27.join(dir, entry2.name);
|
|
166882
167089
|
try {
|
|
166883
167090
|
const stat = await fs15.stat(fullPath);
|
|
166884
167091
|
if (stat.size > MAX_FILE_BYTES)
|
|
@@ -166887,7 +167094,7 @@ async function walk2(root2, dir, files, state, allowed) {
|
|
|
166887
167094
|
continue;
|
|
166888
167095
|
const content = await fs15.readFile(fullPath, "utf-8");
|
|
166889
167096
|
state.totalBytes += stat.size;
|
|
166890
|
-
const relativePath =
|
|
167097
|
+
const relativePath = path27.relative(root2, fullPath).split(path27.sep).join("/");
|
|
166891
167098
|
files.push({ relativePath, content });
|
|
166892
167099
|
} catch {}
|
|
166893
167100
|
}
|