@massa-ai/mcp-client 1.64.0 → 1.66.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 +408 -165
- package/dist/index.js +1104 -835
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -35187,7 +35187,8 @@ var init_ignore_patterns = __esm(() => {
|
|
|
35187
35187
|
"**/pnpm-lock.yaml",
|
|
35188
35188
|
"**/package-lock.json",
|
|
35189
35189
|
"**/bun.lockb",
|
|
35190
|
-
"**/yarn.lock"
|
|
35190
|
+
"**/yarn.lock",
|
|
35191
|
+
"**/Pods/**"
|
|
35191
35192
|
];
|
|
35192
35193
|
});
|
|
35193
35194
|
|
|
@@ -124305,6 +124306,33 @@ class ManagedRunRepositoryPg {
|
|
|
124305
124306
|
`;
|
|
124306
124307
|
return rows[0] ? toActive(rows[0]) : null;
|
|
124307
124308
|
}
|
|
124309
|
+
async getAnyActive() {
|
|
124310
|
+
const rows = await getPrismaClient2().$queryRaw`
|
|
124311
|
+
SELECT id, project_id, run_kind, event_id, content_hash, file_cursor,
|
|
124312
|
+
status, lease_token, lease_expires_at, heartbeat_at,
|
|
124313
|
+
created_at, completed_at
|
|
124314
|
+
FROM managed_runs
|
|
124315
|
+
WHERE status = 'active'
|
|
124316
|
+
AND lease_expires_at > clock_timestamp()
|
|
124317
|
+
ORDER BY lease_expires_at DESC
|
|
124318
|
+
LIMIT 1
|
|
124319
|
+
`;
|
|
124320
|
+
return rows[0] ? toActive(rows[0]) : null;
|
|
124321
|
+
}
|
|
124322
|
+
async release(lease) {
|
|
124323
|
+
const leaseToken = boundedText(lease.leaseToken, "leaseToken", MAX_LEASE_TOKEN);
|
|
124324
|
+
const deleted = await getPrismaClient2().$queryRaw`
|
|
124325
|
+
DELETE FROM managed_runs
|
|
124326
|
+
WHERE id = ${BigInt(lease.runId)}
|
|
124327
|
+
AND project_id = ${lease.projectId}
|
|
124328
|
+
AND run_kind = ${lease.runKind}
|
|
124329
|
+
AND lease_token = ${leaseToken}
|
|
124330
|
+
RETURNING id
|
|
124331
|
+
`;
|
|
124332
|
+
if (!deleted[0])
|
|
124333
|
+
return { status: "lease_lost" };
|
|
124334
|
+
return { status: "aborted", runId: deleted[0].id.toString() };
|
|
124335
|
+
}
|
|
124308
124336
|
}
|
|
124309
124337
|
var DEFAULT_LEASE_TTL_MS = 90000, MIN_LEASE_TTL_MS = 1000, MAX_LEASE_TTL_MS = 300000, HEARTBEAT_TTL_MS = 90000, MAX_PROJECT_ID = 512, MAX_EVENT_ID = 2000, MAX_CONTENT_HASH = 2000, MAX_LEASE_TOKEN = 512;
|
|
124310
124338
|
var init_managed_run_repository_pg = __esm(() => {
|
|
@@ -124342,10 +124370,111 @@ var init_embedding_freshness = __esm(() => {
|
|
|
124342
124370
|
};
|
|
124343
124371
|
});
|
|
124344
124372
|
|
|
124373
|
+
// ../../packages/core/dist/services/jobs/heavy-work-lease.js
|
|
124374
|
+
import { randomUUID as randomUUID3 } from "crypto";
|
|
124375
|
+
import { setTimeout as delay2 } from "timers/promises";
|
|
124376
|
+
function repository() {
|
|
124377
|
+
return repositoryOverride ?? ManagedRunRepositoryPg.getInstance();
|
|
124378
|
+
}
|
|
124379
|
+
async function withHeavyWorkLease(kind, label, fn) {
|
|
124380
|
+
let repo;
|
|
124381
|
+
let lease;
|
|
124382
|
+
try {
|
|
124383
|
+
repo = repository();
|
|
124384
|
+
const outcome = await repo.begin({
|
|
124385
|
+
projectId: `heavy-work:${label}:${randomUUID3()}`,
|
|
124386
|
+
runKind: kind,
|
|
124387
|
+
eventId: `heavy-work:${label}`
|
|
124388
|
+
});
|
|
124389
|
+
if (outcome.status === "acquired")
|
|
124390
|
+
lease = outcome.lease;
|
|
124391
|
+
} catch (error51) {
|
|
124392
|
+
logger.warn("heavy-work lease unavailable; running without it", { label, error: error51 });
|
|
124393
|
+
}
|
|
124394
|
+
if (!repo || !lease)
|
|
124395
|
+
return fn();
|
|
124396
|
+
const heldRepo = repo;
|
|
124397
|
+
const heldLease = lease;
|
|
124398
|
+
const heartbeatController = new AbortController;
|
|
124399
|
+
(async () => {
|
|
124400
|
+
while (true) {
|
|
124401
|
+
try {
|
|
124402
|
+
await delay2(HEARTBEAT_MS, undefined, { signal: heartbeatController.signal });
|
|
124403
|
+
} catch {
|
|
124404
|
+
return;
|
|
124405
|
+
}
|
|
124406
|
+
try {
|
|
124407
|
+
await heldRepo.heartbeat(heldLease);
|
|
124408
|
+
} catch {}
|
|
124409
|
+
}
|
|
124410
|
+
})();
|
|
124411
|
+
try {
|
|
124412
|
+
return await fn();
|
|
124413
|
+
} finally {
|
|
124414
|
+
heartbeatController.abort();
|
|
124415
|
+
try {
|
|
124416
|
+
await heldRepo.release(heldLease);
|
|
124417
|
+
} catch (error51) {
|
|
124418
|
+
logger.warn("heavy-work lease release failed; it expires on its own", { label, error: error51 });
|
|
124419
|
+
}
|
|
124420
|
+
}
|
|
124421
|
+
}
|
|
124422
|
+
async function probeHeavyWork() {
|
|
124423
|
+
let timer;
|
|
124424
|
+
const timeout = new Promise((_, reject) => {
|
|
124425
|
+
timer = setTimeout(() => reject(new Error(`heavy-work probe timed out after ${PROBE_TIMEOUT_MS}ms`)), PROBE_TIMEOUT_MS);
|
|
124426
|
+
});
|
|
124427
|
+
try {
|
|
124428
|
+
const active = await Promise.race([repository().getAnyActive(), timeout]);
|
|
124429
|
+
if (!active)
|
|
124430
|
+
return { busy: false };
|
|
124431
|
+
return { busy: true, reason: `${active.runKind} run ${active.runId} (${active.projectId})` };
|
|
124432
|
+
} finally {
|
|
124433
|
+
clearTimeout(timer);
|
|
124434
|
+
}
|
|
124435
|
+
}
|
|
124436
|
+
var HEARTBEAT_MS = 30000, PROBE_TIMEOUT_MS = 5000, repositoryOverride = null;
|
|
124437
|
+
var init_heavy_work_lease = __esm(() => {
|
|
124438
|
+
init_dist();
|
|
124439
|
+
init_managed_run_repository_pg();
|
|
124440
|
+
});
|
|
124441
|
+
|
|
124442
|
+
// ../../packages/core/dist/services/search/incremental-reindex.js
|
|
124443
|
+
import path21 from "path";
|
|
124444
|
+
function runIncrementalReindex(deps, projectId, projectPath, filesToReindex) {
|
|
124445
|
+
return withHeavyWorkLease("reindex", `incremental-reindex:${projectId}`, async () => {
|
|
124446
|
+
const centralityMap = await deps.symbolRepo.getCentrality(await getProjectIdentityAliasResolver().resolve(projectId));
|
|
124447
|
+
let filesIndexed = 0;
|
|
124448
|
+
let chunksIndexed = 0;
|
|
124449
|
+
let errors4 = 0;
|
|
124450
|
+
for (const relativeFilePath of filesToReindex) {
|
|
124451
|
+
try {
|
|
124452
|
+
const fullPath = path21.join(projectPath, relativeFilePath);
|
|
124453
|
+
const result = await deps.indexFile(fullPath, projectId, projectPath, centralityMap);
|
|
124454
|
+
filesIndexed++;
|
|
124455
|
+
chunksIndexed += result.chunks;
|
|
124456
|
+
} catch (error51) {
|
|
124457
|
+
logger.error("Failed to reindex file", error51, {
|
|
124458
|
+
file: relativeFilePath
|
|
124459
|
+
});
|
|
124460
|
+
errors4++;
|
|
124461
|
+
}
|
|
124462
|
+
}
|
|
124463
|
+
await deps.indexManager.updateIndexMetadata(projectId, projectPath, filesToReindex);
|
|
124464
|
+
await deps.searchCache.invalidateProject(projectId);
|
|
124465
|
+
return { filesIndexed, chunksIndexed, errors: errors4 };
|
|
124466
|
+
});
|
|
124467
|
+
}
|
|
124468
|
+
var init_incremental_reindex = __esm(() => {
|
|
124469
|
+
init_dist();
|
|
124470
|
+
init_alias_resolver();
|
|
124471
|
+
init_heavy_work_lease();
|
|
124472
|
+
});
|
|
124473
|
+
|
|
124345
124474
|
// ../../packages/core/dist/services/search/project-indexer.js
|
|
124346
124475
|
import fs15 from "fs/promises";
|
|
124347
|
-
import
|
|
124348
|
-
import { randomUUID as
|
|
124476
|
+
import path22 from "path";
|
|
124477
|
+
import { randomUUID as randomUUID4 } from "crypto";
|
|
124349
124478
|
async function runWithIndexLock(lockMap, projectId, work) {
|
|
124350
124479
|
const prevLock = lockMap.get(projectId);
|
|
124351
124480
|
const isQueued = prevLock !== undefined;
|
|
@@ -124387,7 +124516,7 @@ async function indexProjectInternal(deps, projectPath, projectId, options = {})
|
|
|
124387
124516
|
dot: false
|
|
124388
124517
|
});
|
|
124389
124518
|
const filteredFiles = files.filter((file2) => {
|
|
124390
|
-
const relativePath =
|
|
124519
|
+
const relativePath = path22.relative(projectPath, file2);
|
|
124391
124520
|
const shouldIgnore = ig.ignores(relativePath);
|
|
124392
124521
|
if (shouldIgnore) {
|
|
124393
124522
|
logger.debug("Ignoring file per .gitignore during indexing", {
|
|
@@ -124427,7 +124556,7 @@ async function indexProjectInternal(deps, projectPath, projectId, options = {})
|
|
|
124427
124556
|
});
|
|
124428
124557
|
}
|
|
124429
124558
|
}
|
|
124430
|
-
const indexedFilesList = filteredFiles.map((f) =>
|
|
124559
|
+
const indexedFilesList = filteredFiles.map((f) => path22.relative(projectPath, f));
|
|
124431
124560
|
await deps.indexManager.updateIndexMetadata(projectId, projectPath, indexedFilesList);
|
|
124432
124561
|
logger.info("Project indexing completed", {
|
|
124433
124562
|
projectId,
|
|
@@ -124498,7 +124627,7 @@ async function ensureFreshIndex(deps, projectId, projectPath, options = {}) {
|
|
|
124498
124627
|
if (needsFullReindex) {
|
|
124499
124628
|
logger.info("Performing full reindex", { projectId });
|
|
124500
124629
|
const managedRunRepo = ManagedRunRepositoryPg.getInstance();
|
|
124501
|
-
const eventId = `reindex:${projectId}:${
|
|
124630
|
+
const eventId = `reindex:${projectId}:${randomUUID4()}`;
|
|
124502
124631
|
const beginOutcome = await managedRunRepo.begin({
|
|
124503
124632
|
projectId,
|
|
124504
124633
|
runKind: "indexing",
|
|
@@ -124551,25 +124680,7 @@ async function ensureFreshIndex(deps, projectId, projectPath, options = {}) {
|
|
|
124551
124680
|
projectId,
|
|
124552
124681
|
fileCount: filesToReindex.length
|
|
124553
124682
|
});
|
|
124554
|
-
const
|
|
124555
|
-
let filesIndexed = 0;
|
|
124556
|
-
let chunksIndexed = 0;
|
|
124557
|
-
let errors4 = 0;
|
|
124558
|
-
for (const relativeFilePath of filesToReindex) {
|
|
124559
|
-
try {
|
|
124560
|
-
const fullPath = path21.join(projectPath, relativeFilePath);
|
|
124561
|
-
const result = await deps.indexFile(fullPath, projectId, projectPath, centralityMap);
|
|
124562
|
-
filesIndexed++;
|
|
124563
|
-
chunksIndexed += result.chunks;
|
|
124564
|
-
} catch (error51) {
|
|
124565
|
-
logger.error("Failed to reindex file", error51, {
|
|
124566
|
-
file: relativeFilePath
|
|
124567
|
-
});
|
|
124568
|
-
errors4++;
|
|
124569
|
-
}
|
|
124570
|
-
}
|
|
124571
|
-
await deps.indexManager.updateIndexMetadata(projectId, projectPath, filesToReindex);
|
|
124572
|
-
await deps.searchCache.invalidateProject(projectId);
|
|
124683
|
+
const { filesIndexed, chunksIndexed, errors: errors4 } = await runIncrementalReindex(deps, projectId, projectPath, filesToReindex);
|
|
124573
124684
|
logger.info("Incremental reindex completed", {
|
|
124574
124685
|
projectId,
|
|
124575
124686
|
filesIndexed,
|
|
@@ -124618,7 +124729,7 @@ async function checkSearchAdmission(deps, projectId, projectPath) {
|
|
|
124618
124729
|
async function indexFile(deps, filePath, projectId, projectRoot, centralityMap) {
|
|
124619
124730
|
projectId = await getProjectIdentityAliasResolver().resolve(projectId);
|
|
124620
124731
|
const content = await fs15.readFile(filePath, "utf-8");
|
|
124621
|
-
const relativePath =
|
|
124732
|
+
const relativePath = path22.relative(projectRoot, filePath);
|
|
124622
124733
|
const maxFileSize = config2.get("security").maxFileSize || 1024 * 1024;
|
|
124623
124734
|
if (content.length > maxFileSize) {
|
|
124624
124735
|
logger.warn("File too large, skipping", {
|
|
@@ -124638,7 +124749,7 @@ async function indexFile(deps, filePath, projectId, projectRoot, centralityMap)
|
|
|
124638
124749
|
chunkIndex: i,
|
|
124639
124750
|
totalChunks: chunks.length,
|
|
124640
124751
|
type: chunk.type,
|
|
124641
|
-
language:
|
|
124752
|
+
language: path22.extname(filePath).slice(1),
|
|
124642
124753
|
lineStart: chunk.lineStart,
|
|
124643
124754
|
lineEnd: chunk.lineEnd,
|
|
124644
124755
|
label: chunk.label,
|
|
@@ -124663,6 +124774,7 @@ var init_project_indexer = __esm(() => {
|
|
|
124663
124774
|
init_managed_run_repository_pg();
|
|
124664
124775
|
init_symbol_repo_workspace();
|
|
124665
124776
|
init_embedding_freshness();
|
|
124777
|
+
init_incremental_reindex();
|
|
124666
124778
|
globAsync2 = glob;
|
|
124667
124779
|
});
|
|
124668
124780
|
|
|
@@ -126482,7 +126594,7 @@ var init_index_job_store = __esm(() => {
|
|
|
126482
126594
|
});
|
|
126483
126595
|
|
|
126484
126596
|
// ../../packages/core/dist/services/jobs/index-job-tracker.js
|
|
126485
|
-
import { randomUUID as
|
|
126597
|
+
import { randomUUID as randomUUID5 } from "crypto";
|
|
126486
126598
|
|
|
126487
126599
|
class IndexJobTracker {
|
|
126488
126600
|
static instance;
|
|
@@ -126506,7 +126618,7 @@ class IndexJobTracker {
|
|
|
126506
126618
|
return IndexJobTracker.instance;
|
|
126507
126619
|
}
|
|
126508
126620
|
createJob(projectId, projectPath) {
|
|
126509
|
-
const jobId =
|
|
126621
|
+
const jobId = randomUUID5();
|
|
126510
126622
|
const job = {
|
|
126511
126623
|
jobId,
|
|
126512
126624
|
projectId,
|
|
@@ -126596,7 +126708,9 @@ class IndexJobTracker {
|
|
|
126596
126708
|
const cutoff = now2 - staleMs;
|
|
126597
126709
|
let reaped = 0;
|
|
126598
126710
|
for (const job of running) {
|
|
126599
|
-
const
|
|
126711
|
+
const live = this.jobs.get(job.jobId);
|
|
126712
|
+
const liveHb = live?.heartbeatAt?.getTime();
|
|
126713
|
+
const hbMs = liveHb ?? job.heartbeatAt?.getTime();
|
|
126600
126714
|
const startedMs = job.startedAt?.getTime();
|
|
126601
126715
|
const stale = hbMs != null && hbMs < cutoff || hbMs == null && startedMs != null && startedMs < cutoff;
|
|
126602
126716
|
if (!stale)
|
|
@@ -126710,7 +126824,7 @@ function stripNul(content) {
|
|
|
126710
126824
|
|
|
126711
126825
|
// ../../packages/core/dist/services/etl/stages/discover.js
|
|
126712
126826
|
import fs16 from "fs/promises";
|
|
126713
|
-
import
|
|
126827
|
+
import path23 from "path";
|
|
126714
126828
|
import { createHash as createHash5 } from "crypto";
|
|
126715
126829
|
|
|
126716
126830
|
class DiscoverStage {
|
|
@@ -126736,7 +126850,7 @@ class DiscoverStage {
|
|
|
126736
126850
|
dot: false,
|
|
126737
126851
|
absolute: false
|
|
126738
126852
|
});
|
|
126739
|
-
relPaths = found.map((p) =>
|
|
126853
|
+
relPaths = found.map((p) => path23.isAbsolute(p) ? path23.relative(ctx.projectPath, p) : p).filter((p) => !ig.ignores(p) && applyPolicy(p, policy) !== "Drop");
|
|
126740
126854
|
}
|
|
126741
126855
|
if (ctx.resumeCursor?.path) {
|
|
126742
126856
|
const cursorPath = ctx.resumeCursor.path;
|
|
@@ -126795,7 +126909,7 @@ class DiscoverStage {
|
|
|
126795
126909
|
return discovered;
|
|
126796
126910
|
}
|
|
126797
126911
|
async processFile(ctx, relativePath, forceReindex) {
|
|
126798
|
-
const absolutePath =
|
|
126912
|
+
const absolutePath = path23.join(ctx.projectPath, relativePath);
|
|
126799
126913
|
try {
|
|
126800
126914
|
const stat = await fs16.stat(absolutePath);
|
|
126801
126915
|
const content = stripNul(await fs16.readFile(absolutePath, "utf-8"));
|
|
@@ -126842,7 +126956,7 @@ class DiscoverStage {
|
|
|
126842
126956
|
ig.add(pattern);
|
|
126843
126957
|
}
|
|
126844
126958
|
try {
|
|
126845
|
-
const gitignorePath =
|
|
126959
|
+
const gitignorePath = path23.join(projectPath, ".gitignore");
|
|
126846
126960
|
const gitignoreContent = await fs16.readFile(gitignorePath, "utf8");
|
|
126847
126961
|
const rules = gitignoreContent.split(`
|
|
126848
126962
|
`).map((line) => line.trim()).filter((line) => line && !line.startsWith("#"));
|
|
@@ -128198,8 +128312,8 @@ function rustUseLeaves(node, source, prefix = []) {
|
|
|
128198
128312
|
}
|
|
128199
128313
|
if (node.type === "use_wildcard")
|
|
128200
128314
|
return [{ path: [...prefix, "*"], glob: true }];
|
|
128201
|
-
const
|
|
128202
|
-
return
|
|
128315
|
+
const path24 = rustPathSegments(node, source);
|
|
128316
|
+
return path24.length ? [{ path: [...prefix, ...path24] }] : [];
|
|
128203
128317
|
}
|
|
128204
128318
|
function functionalCaptures(captures, source, family) {
|
|
128205
128319
|
if (family !== "clojure")
|
|
@@ -129171,7 +129285,7 @@ var init_structural_runtime = __esm(() => {
|
|
|
129171
129285
|
});
|
|
129172
129286
|
|
|
129173
129287
|
// ../../packages/core/dist/services/etl/stages/parse.js
|
|
129174
|
-
import
|
|
129288
|
+
import path24 from "path";
|
|
129175
129289
|
import fs17 from "fs/promises";
|
|
129176
129290
|
function resolveChunkerMaxChars() {
|
|
129177
129291
|
const global2 = Number(process.env.EMBEDDING_MAX_CHARS);
|
|
@@ -129200,8 +129314,8 @@ class ParseStage {
|
|
|
129200
129314
|
const results = new Map;
|
|
129201
129315
|
let processed = 0;
|
|
129202
129316
|
const phases = [
|
|
129203
|
-
files.filter((file2) =>
|
|
129204
|
-
files.filter((file2) =>
|
|
129317
|
+
files.filter((file2) => path24.extname(file2.relativePath).toLowerCase() !== ".h"),
|
|
129318
|
+
files.filter((file2) => path24.extname(file2.relativePath).toLowerCase() === ".h")
|
|
129205
129319
|
];
|
|
129206
129320
|
const batches = phases.flatMap((phase) => Array.from({ length: Math.ceil(phase.length / BATCH_SIZE) }, (_, index) => phase.slice(index * BATCH_SIZE, (index + 1) * BATCH_SIZE)));
|
|
129207
129321
|
for (const batch of batches) {
|
|
@@ -129239,19 +129353,19 @@ class ParseStage {
|
|
|
129239
129353
|
return files.map((file2) => results.get(file2.relativePath));
|
|
129240
129354
|
}
|
|
129241
129355
|
recordHeaderImporterEvidence(ctx, files, parsedFiles) {
|
|
129242
|
-
const knownHeaders = new Set(files.filter((file2) =>
|
|
129356
|
+
const knownHeaders = new Set(files.filter((file2) => path24.extname(file2.relativePath).toLowerCase() === ".h").map((file2) => path24.posix.normalize(file2.relativePath)));
|
|
129243
129357
|
const mutable = {
|
|
129244
129358
|
...ctx.structuralHeaderEvidenceByFile
|
|
129245
129359
|
};
|
|
129246
129360
|
for (const parsed of parsedFiles) {
|
|
129247
|
-
const extension =
|
|
129361
|
+
const extension = path24.extname(parsed.file.relativePath).toLowerCase();
|
|
129248
129362
|
const key = extension === ".c" ? "cImporters" : [".cpp", ".hpp"].includes(extension) ? "cppImporters" : undefined;
|
|
129249
129363
|
if (!key)
|
|
129250
129364
|
continue;
|
|
129251
129365
|
for (const imported of parsed.rawImports) {
|
|
129252
129366
|
if (!["c_include", "cpp_include"].includes(imported.form) || imported.specifier.startsWith("<"))
|
|
129253
129367
|
continue;
|
|
129254
|
-
const header =
|
|
129368
|
+
const header = path24.posix.normalize(path24.posix.join(path24.posix.dirname(parsed.file.relativePath), imported.specifier));
|
|
129255
129369
|
if (!knownHeaders.has(header))
|
|
129256
129370
|
continue;
|
|
129257
129371
|
const existing = mutable[header] ?? {};
|
|
@@ -129262,7 +129376,7 @@ class ParseStage {
|
|
|
129262
129376
|
}
|
|
129263
129377
|
async parseFile(ctx, file2) {
|
|
129264
129378
|
if (!file2.needsReparse) {
|
|
129265
|
-
const extension =
|
|
129379
|
+
const extension = path24.extname(file2.relativePath).toLowerCase();
|
|
129266
129380
|
if ([".c", ".cpp", ".hpp"].includes(extension)) {
|
|
129267
129381
|
const content = file2.snapshotContent ?? await fs17.readFile(file2.absolutePath, "utf8");
|
|
129268
129382
|
const outcome = await this.runtime.parse({ extension, source: Buffer.from(content) });
|
|
@@ -129277,7 +129391,7 @@ class ParseStage {
|
|
|
129277
129391
|
}
|
|
129278
129392
|
try {
|
|
129279
129393
|
const content = file2.snapshotContent ?? await fs17.readFile(file2.absolutePath, "utf-8");
|
|
129280
|
-
const ext2 =
|
|
129394
|
+
const ext2 = path24.extname(file2.relativePath).toLowerCase();
|
|
129281
129395
|
const chunkerMaxChars = resolveChunkerMaxChars();
|
|
129282
129396
|
const chunks = smartChunk(content, file2.relativePath, chunkerMaxChars ? { maxChunkChars: chunkerMaxChars } : {});
|
|
129283
129397
|
let symbols;
|
|
@@ -129832,7 +129946,7 @@ var init_resolver = __esm(() => {
|
|
|
129832
129946
|
});
|
|
129833
129947
|
|
|
129834
129948
|
// ../../packages/core/dist/services/structural/resolvers/typescript.js
|
|
129835
|
-
import
|
|
129949
|
+
import path25 from "path";
|
|
129836
129950
|
function candidates(identities) {
|
|
129837
129951
|
return Object.freeze(identities.map((identity) => Object.freeze({
|
|
129838
129952
|
fqn: identity.fqn,
|
|
@@ -129927,7 +130041,7 @@ function probe(base, known, dialect = "typescript") {
|
|
|
129927
130041
|
const bases = /\.[cm]?jsx?$/u.test(base) ? [base.replace(/\.[cm]?jsx?$/u, ".ts"), base.replace(/\.[cm]?jsx?$/u, ".tsx"), base] : [base];
|
|
129928
130042
|
for (const candidateBase of bases)
|
|
129929
130043
|
for (const suffix of DIALECT_PROBES[dialect] ?? [""]) {
|
|
129930
|
-
const value =
|
|
130044
|
+
const value = path25.posix.normalize(`${candidateBase}${suffix}`);
|
|
129931
130045
|
if (!value.startsWith("../") && value !== ".." && known.has(value))
|
|
129932
130046
|
return value;
|
|
129933
130047
|
}
|
|
@@ -129936,7 +130050,7 @@ function probe(base, known, dialect = "typescript") {
|
|
|
129936
130050
|
function resolveStructuralSpecifier(specifier, fromFile, build, dialect = "typescript") {
|
|
129937
130051
|
const known = new Set(build.knownFiles.map(normalizeStructuralFile));
|
|
129938
130052
|
if (specifier.startsWith("./") || specifier.startsWith("../")) {
|
|
129939
|
-
return probe(
|
|
130053
|
+
return probe(path25.posix.join(path25.posix.dirname(fromFile), specifier), known, dialect);
|
|
129940
130054
|
}
|
|
129941
130055
|
const aliases = build.pathAliasesByFile?.[normalizeStructuralFile(fromFile)] ?? build.pathAliases ?? [];
|
|
129942
130056
|
for (const alias of aliases) {
|
|
@@ -130200,7 +130314,7 @@ var init_scripting2 = __esm(() => {
|
|
|
130200
130314
|
});
|
|
130201
130315
|
|
|
130202
130316
|
// ../../packages/core/dist/services/structural/resolvers/systems.js
|
|
130203
|
-
import
|
|
130317
|
+
import path26 from "path";
|
|
130204
130318
|
var DIALECTS, SYSTEMS_LANGUAGE_RESOLVER;
|
|
130205
130319
|
var init_systems2 = __esm(() => {
|
|
130206
130320
|
init_typescript2();
|
|
@@ -130219,7 +130333,7 @@ var init_systems2 = __esm(() => {
|
|
|
130219
130333
|
const bindings = item.bindings.map((binding) => binding.imported === "*" && binding.local === "*" && unresolvedTarget && !unresolvedTarget.qualifier ? { ...binding, imported: unresolvedTarget.name, local: unresolvedTarget.name } : binding);
|
|
130220
130334
|
if (item.specifier === "crate" || item.specifier.startsWith("crate/")) {
|
|
130221
130335
|
const crateRoot = file2.file.startsWith("src/") ? "src" : "";
|
|
130222
|
-
return { ...item, bindings, specifier: `./${
|
|
130336
|
+
return { ...item, bindings, specifier: `./${path26.posix.relative(path26.posix.dirname(file2.file), path26.posix.join(crateRoot, item.specifier.replace(/^crate\/?/u, "")))}` };
|
|
130223
130337
|
}
|
|
130224
130338
|
if (item.specifier === "self" || item.specifier.startsWith("self/"))
|
|
130225
130339
|
return { ...item, bindings, specifier: `./${item.specifier.replace(/^self\/?/u, "")}` };
|
|
@@ -130317,7 +130431,7 @@ var init_data_document2 = __esm(() => {
|
|
|
130317
130431
|
});
|
|
130318
130432
|
|
|
130319
130433
|
// ../../packages/core/dist/services/etl/stages/resolve.js
|
|
130320
|
-
import
|
|
130434
|
+
import path27 from "path";
|
|
130321
130435
|
import fs18 from "fs";
|
|
130322
130436
|
|
|
130323
130437
|
class ResolveStage {
|
|
@@ -130342,7 +130456,7 @@ class ResolveStage {
|
|
|
130342
130456
|
const structuralDocuments = files.flatMap((file2) => {
|
|
130343
130457
|
if (!file2.structure)
|
|
130344
130458
|
return [];
|
|
130345
|
-
const language = resolveStructuralLanguage(
|
|
130459
|
+
const language = resolveStructuralLanguage(path27.extname(file2.file.relativePath));
|
|
130346
130460
|
if (language.status !== "supported")
|
|
130347
130461
|
throw new Error(`structural_manifest_missing:${file2.file.relativePath}`);
|
|
130348
130462
|
return [{
|
|
@@ -130354,13 +130468,13 @@ class ResolveStage {
|
|
|
130354
130468
|
}];
|
|
130355
130469
|
});
|
|
130356
130470
|
const currentStructuralFiles = new Set(structuralDocuments.map((document2) => document2.file));
|
|
130357
|
-
const skippedStructuralFiles = new Set(files.filter((item) => !item.file.needsReparse && STRUCTURAL_SEED_EXTENSIONS.has(
|
|
130471
|
+
const skippedStructuralFiles = new Set(files.filter((item) => !item.file.needsReparse && STRUCTURAL_SEED_EXTENSIONS.has(path27.extname(item.file.relativePath).toLowerCase())).map((item) => item.file.relativePath));
|
|
130358
130472
|
const pathAliasesByFile = Object.fromEntries([...knownRelPaths].map((file2) => [
|
|
130359
130473
|
file2,
|
|
130360
130474
|
this.structuralAliasesFor(file2, rootAliases, monorepoPackages)
|
|
130361
130475
|
]));
|
|
130362
130476
|
const buildMetadata = { knownFiles: [...knownRelPaths], pathAliasesByFile };
|
|
130363
|
-
const seedRows = repositoryDefinitions.filter((definition) => STRUCTURAL_SEED_EXTENSIONS.has(
|
|
130477
|
+
const seedRows = repositoryDefinitions.filter((definition) => STRUCTURAL_SEED_EXTENSIONS.has(path27.extname(definition.file_path).toLowerCase())).filter((definition) => knownRelPaths.has(definition.file_path) && skippedStructuralFiles.has(definition.file_path)).filter((definition) => !currentStructuralFiles.has(definition.file_path));
|
|
130364
130478
|
const seedIds = new Set;
|
|
130365
130479
|
for (const definition of seedRows) {
|
|
130366
130480
|
if (seedIds.has(definition.id))
|
|
@@ -130457,7 +130571,7 @@ class ResolveStage {
|
|
|
130457
130571
|
if (parsed.file !== definition.file_path) {
|
|
130458
130572
|
throw new Error(`structural_repository_seed_file_mismatch:${definition.id}`);
|
|
130459
130573
|
}
|
|
130460
|
-
const language = resolveStructuralLanguage(
|
|
130574
|
+
const language = resolveStructuralLanguage(path27.extname(definition.file_path));
|
|
130461
130575
|
if (language.status !== "supported")
|
|
130462
130576
|
throw new Error(`structural_repository_seed_language:${definition.id}`);
|
|
130463
130577
|
let identity;
|
|
@@ -130509,7 +130623,7 @@ class ResolveStage {
|
|
|
130509
130623
|
});
|
|
130510
130624
|
}
|
|
130511
130625
|
resolveFile(parsed, projectPath, knownRelPaths, rootAliases, monorepoPackages, symbolIndex, knownFqns) {
|
|
130512
|
-
const fromDir =
|
|
130626
|
+
const fromDir = path27.dirname(path27.join(projectPath, parsed.file.relativePath));
|
|
130513
130627
|
const packageAliases = this.getPackageAliases(parsed.file.relativePath, monorepoPackages);
|
|
130514
130628
|
const allAliases = [...packageAliases, ...rootAliases];
|
|
130515
130629
|
const resolvedImports = parsed.rawImports.map((raw2) => {
|
|
@@ -130580,7 +130694,7 @@ class ResolveStage {
|
|
|
130580
130694
|
index.set(def.name, `${def.file_path}#${def.name}`);
|
|
130581
130695
|
}
|
|
130582
130696
|
} catch (err) {
|
|
130583
|
-
const skippedStructural = files.some((file2) => !file2.file.needsReparse && STRUCTURAL_SEED_EXTENSIONS.has(
|
|
130697
|
+
const skippedStructural = files.some((file2) => !file2.file.needsReparse && STRUCTURAL_SEED_EXTENSIONS.has(path27.extname(file2.file.relativePath).toLowerCase()));
|
|
130584
130698
|
if (skippedStructural)
|
|
130585
130699
|
throw new Error("structural_repository_seed_failed", { cause: err });
|
|
130586
130700
|
logger.warn("buildSymbolIndex: repo seed failed, in-batch only", {
|
|
@@ -130604,7 +130718,7 @@ class ResolveStage {
|
|
|
130604
130718
|
}
|
|
130605
130719
|
resolveSpecifier(specifier, fromDir, projectPath, knownRelPaths, aliases) {
|
|
130606
130720
|
if (specifier.startsWith("./") || specifier.startsWith("../")) {
|
|
130607
|
-
const resolved = this.probeExtensions(
|
|
130721
|
+
const resolved = this.probeExtensions(path27.resolve(fromDir, specifier), projectPath, knownRelPaths);
|
|
130608
130722
|
return { resolvedPath: resolved, external: false };
|
|
130609
130723
|
}
|
|
130610
130724
|
for (const alias of aliases) {
|
|
@@ -130612,8 +130726,8 @@ class ResolveStage {
|
|
|
130612
130726
|
const suffix = specifier.slice(alias.prefix.length);
|
|
130613
130727
|
for (const target of alias.targets) {
|
|
130614
130728
|
const cleanTarget = target.replace(/\/\*$/, "");
|
|
130615
|
-
const basePath = alias.packagePath ?
|
|
130616
|
-
const absPath =
|
|
130729
|
+
const basePath = alias.packagePath ? path27.join(projectPath, alias.packagePath) : projectPath;
|
|
130730
|
+
const absPath = path27.join(basePath, cleanTarget + suffix);
|
|
130617
130731
|
const resolved = this.probeExtensions(absPath, projectPath, knownRelPaths);
|
|
130618
130732
|
if (resolved)
|
|
130619
130733
|
return { resolvedPath: resolved, external: false };
|
|
@@ -130629,7 +130743,7 @@ class ResolveStage {
|
|
|
130629
130743
|
...TS_EXTENSIONS.map((ext2) => absPath.replace(/\.[^.]+$/, ext2))
|
|
130630
130744
|
];
|
|
130631
130745
|
for (const candidate2 of candidates2) {
|
|
130632
|
-
const rel =
|
|
130746
|
+
const rel = path27.relative(projectPath, candidate2).replace(/\\/g, "/");
|
|
130633
130747
|
if (knownRelPaths.has(rel))
|
|
130634
130748
|
return rel;
|
|
130635
130749
|
}
|
|
@@ -130637,7 +130751,7 @@ class ResolveStage {
|
|
|
130637
130751
|
}
|
|
130638
130752
|
loadTsConfigPaths(projectPath, packageBase) {
|
|
130639
130753
|
const aliases = [];
|
|
130640
|
-
const tsconfigPath =
|
|
130754
|
+
const tsconfigPath = path27.join(projectPath, "tsconfig.json");
|
|
130641
130755
|
try {
|
|
130642
130756
|
const raw2 = fs18.readFileSync(tsconfigPath, "utf-8");
|
|
130643
130757
|
const stripped = raw2.replace(/\/\/[^\n]*/g, "").replace(/\/\*[\s\S]*?\*\//g, "");
|
|
@@ -130668,7 +130782,7 @@ class ResolveStage {
|
|
|
130668
130782
|
}
|
|
130669
130783
|
}
|
|
130670
130784
|
for (const packageRelPath of packagePaths) {
|
|
130671
|
-
const absPackagePath =
|
|
130785
|
+
const absPackagePath = path27.join(projectPath, packageRelPath);
|
|
130672
130786
|
const aliases = this.loadTsConfigPaths(absPackagePath, packageRelPath);
|
|
130673
130787
|
if (aliases.length > 0) {
|
|
130674
130788
|
packages.push({
|
|
@@ -130698,7 +130812,7 @@ class ResolveStage {
|
|
|
130698
130812
|
structuralAliasesFor(filePath, rootAliases, packages) {
|
|
130699
130813
|
return [...this.getPackageAliases(filePath, packages), ...rootAliases].map((alias) => ({
|
|
130700
130814
|
pattern: alias.prefix + (alias.targets.some((target) => target.includes("*")) ? "/*" : ""),
|
|
130701
|
-
targets: alias.targets.map((target) => alias.packagePath ?
|
|
130815
|
+
targets: alias.targets.map((target) => alias.packagePath ? path27.posix.join(alias.packagePath, target) : target)
|
|
130702
130816
|
}));
|
|
130703
130817
|
}
|
|
130704
130818
|
}
|
|
@@ -130762,7 +130876,7 @@ var init_with_deadlock_retry = __esm(() => {
|
|
|
130762
130876
|
});
|
|
130763
130877
|
|
|
130764
130878
|
// ../../packages/core/dist/services/etl/stages/load.js
|
|
130765
|
-
import
|
|
130879
|
+
import path28 from "path";
|
|
130766
130880
|
function formatDuration(ms) {
|
|
130767
130881
|
const totalSec = Math.max(0, Math.round(ms / 1000));
|
|
130768
130882
|
if (totalSec < 60)
|
|
@@ -131039,7 +131153,7 @@ class LoadStage {
|
|
|
131039
131153
|
const filePath = file2.file.relativePath;
|
|
131040
131154
|
const batch = buildSymbolPersistenceBatch(ctx.projectId, file2);
|
|
131041
131155
|
if (ctx.graphGenerationLease) {
|
|
131042
|
-
const manifest = getLanguageManifestEntry(
|
|
131156
|
+
const manifest = getLanguageManifestEntry(path28.extname(filePath));
|
|
131043
131157
|
const diagnostics2 = (file2.structuralDiagnostics ?? []).slice(0, 10).map((diagnostic2) => ({
|
|
131044
131158
|
code: diagnostic2.code,
|
|
131045
131159
|
severity: diagnostic2.severity,
|
|
@@ -131091,7 +131205,7 @@ var init_load = __esm(() => {
|
|
|
131091
131205
|
});
|
|
131092
131206
|
|
|
131093
131207
|
// ../../packages/core/dist/data/graph-generation/graph-generation-repository-pg.js
|
|
131094
|
-
import { randomUUID as
|
|
131208
|
+
import { randomUUID as randomUUID6 } from "crypto";
|
|
131095
131209
|
function boundedText2(value, label, max = 512) {
|
|
131096
131210
|
const normalized = value.normalize("NFC").trim();
|
|
131097
131211
|
if (!normalized || normalized.length > max || normalized.includes("\x00")) {
|
|
@@ -131195,8 +131309,8 @@ class GraphGenerationRepositoryPg {
|
|
|
131195
131309
|
}
|
|
131196
131310
|
async begin(rawInput) {
|
|
131197
131311
|
const input = validateBegin2(rawInput);
|
|
131198
|
-
const generationId =
|
|
131199
|
-
const leaseToken =
|
|
131312
|
+
const generationId = randomUUID6();
|
|
131313
|
+
const leaseToken = randomUUID6();
|
|
131200
131314
|
return getPrismaClient2().$transaction(async (tx) => {
|
|
131201
131315
|
const workspace = await lockWorkspace(tx, input.projectId);
|
|
131202
131316
|
if (workspace.active_graph_generation_id !== input.expectedActiveGenerationId) {
|
|
@@ -131436,8 +131550,8 @@ function buildGraphInputSnapshotHash(files) {
|
|
|
131436
131550
|
|
|
131437
131551
|
class GraphGenerationCoordinator {
|
|
131438
131552
|
repository;
|
|
131439
|
-
constructor(
|
|
131440
|
-
this.repository =
|
|
131553
|
+
constructor(repository2 = getGraphGenerationRepository()) {
|
|
131554
|
+
this.repository = repository2;
|
|
131441
131555
|
}
|
|
131442
131556
|
async begin(input) {
|
|
131443
131557
|
const deadline = Date.now() + GRAPH_GENERATION_LEASE_TTL_MS;
|
|
@@ -131493,609 +131607,6 @@ var init_graph_generation_coordinator = __esm(() => {
|
|
|
131493
131607
|
init_with_deadlock_retry();
|
|
131494
131608
|
});
|
|
131495
131609
|
|
|
131496
|
-
// ../../packages/core/dist/services/etl/pipeline.js
|
|
131497
|
-
import { createHash as createHash7 } from "crypto";
|
|
131498
|
-
import { setTimeout as delay2 } from "timers/promises";
|
|
131499
|
-
import path28 from "path";
|
|
131500
|
-
function buildHeaderLanguageEvidence(files) {
|
|
131501
|
-
const headers = new Set(files.filter((file2) => path28.posix.extname(file2.relativePath).toLowerCase() === ".h").map((file2) => path28.posix.normalize(file2.relativePath)));
|
|
131502
|
-
const mutable = new Map;
|
|
131503
|
-
const entry2 = (header) => {
|
|
131504
|
-
let value = mutable.get(header);
|
|
131505
|
-
if (!value) {
|
|
131506
|
-
value = { cImporters: new Set, cppImporters: new Set, build: new Set };
|
|
131507
|
-
mutable.set(header, value);
|
|
131508
|
-
}
|
|
131509
|
-
return value;
|
|
131510
|
-
};
|
|
131511
|
-
for (const file2 of files) {
|
|
131512
|
-
if (path28.posix.basename(file2.relativePath) !== "compile_commands.json" || file2.snapshotContent === undefined)
|
|
131513
|
-
continue;
|
|
131514
|
-
let commands;
|
|
131515
|
-
try {
|
|
131516
|
-
commands = JSON.parse(file2.snapshotContent);
|
|
131517
|
-
} catch {
|
|
131518
|
-
continue;
|
|
131519
|
-
}
|
|
131520
|
-
if (!Array.isArray(commands))
|
|
131521
|
-
continue;
|
|
131522
|
-
for (const command of commands) {
|
|
131523
|
-
if (!command || typeof command !== "object")
|
|
131524
|
-
continue;
|
|
131525
|
-
const record3 = command;
|
|
131526
|
-
if (typeof record3.file !== "string")
|
|
131527
|
-
continue;
|
|
131528
|
-
const projectRoot = path28.resolve(file2.absolutePath, ...file2.relativePath.split("/").map(() => ".."));
|
|
131529
|
-
const commandDirectory = typeof record3.directory === "string" ? path28.resolve(projectRoot, record3.directory) : projectRoot;
|
|
131530
|
-
const absoluteInput = path28.resolve(commandDirectory, record3.file);
|
|
131531
|
-
const relative2 = path28.relative(projectRoot, absoluteInput);
|
|
131532
|
-
const header = path28.posix.normalize(relative2.replaceAll(path28.sep, "/"));
|
|
131533
|
-
if (!headers.has(header))
|
|
131534
|
-
continue;
|
|
131535
|
-
const invocation = typeof record3.command === "string" ? record3.command : Array.isArray(record3.arguments) ? record3.arguments.join(" ") : "";
|
|
131536
|
-
if (/(?:^|\s)(?:clang\+\+|g\+\+|c\+\+)(?:\s|$)|(?:^|\s)-x\s*c\+\+(?:\s|$)/u.test(invocation))
|
|
131537
|
-
entry2(header).build.add("cpp");
|
|
131538
|
-
else if (/(?:^|\s)(?:clang|gcc|cc)(?:\s|$)|(?:^|\s)-x\s*c(?:\s|$)/u.test(invocation))
|
|
131539
|
-
entry2(header).build.add("c");
|
|
131540
|
-
}
|
|
131541
|
-
}
|
|
131542
|
-
return Object.freeze(Object.fromEntries([...mutable.entries()].sort(([a], [b]) => a.localeCompare(b)).map(([header, value]) => [header, Object.freeze({
|
|
131543
|
-
...value.cImporters.size ? { cImporters: Object.freeze([...value.cImporters].sort()) } : {},
|
|
131544
|
-
...value.cppImporters.size ? { cppImporters: Object.freeze([...value.cppImporters].sort()) } : {},
|
|
131545
|
-
...value.build.size ? { buildLanguage: value.build.size > 1 ? "conflict" : [...value.build][0] } : {}
|
|
131546
|
-
})])));
|
|
131547
|
-
}
|
|
131548
|
-
function abortable(operation, signal) {
|
|
131549
|
-
if (signal.aborted)
|
|
131550
|
-
return Promise.reject(signal.reason);
|
|
131551
|
-
return new Promise((resolve5, reject) => {
|
|
131552
|
-
let abortReason;
|
|
131553
|
-
const onAbort = () => {
|
|
131554
|
-
abortReason = signal.reason;
|
|
131555
|
-
};
|
|
131556
|
-
signal.addEventListener("abort", onAbort, { once: true });
|
|
131557
|
-
operation.then((value) => abortReason === undefined ? resolve5(value) : reject(abortReason), (error51) => reject(abortReason ?? error51)).finally(() => signal.removeEventListener("abort", onAbort));
|
|
131558
|
-
});
|
|
131559
|
-
}
|
|
131560
|
-
var EtlPipeline;
|
|
131561
|
-
var init_pipeline = __esm(() => {
|
|
131562
|
-
init_dist();
|
|
131563
|
-
init_discover();
|
|
131564
|
-
init_parse3();
|
|
131565
|
-
init_resolve();
|
|
131566
|
-
init_load();
|
|
131567
|
-
init_event_bus();
|
|
131568
|
-
init_symbol_repository_factory();
|
|
131569
|
-
init_index_job_tracker();
|
|
131570
|
-
init_cache_factory();
|
|
131571
|
-
init_index_manager();
|
|
131572
|
-
init_vector_store_factory();
|
|
131573
|
-
init_keyword_search_factory();
|
|
131574
|
-
init_alias_resolver();
|
|
131575
|
-
init_symbol_repo_workspace();
|
|
131576
|
-
init_project_indexer();
|
|
131577
|
-
init_parser_readiness();
|
|
131578
|
-
init_parse3();
|
|
131579
|
-
init_language_manifest();
|
|
131580
|
-
init_graph_generation_coordinator();
|
|
131581
|
-
init_managed_run_repository_pg();
|
|
131582
|
-
EtlPipeline = class EtlPipeline {
|
|
131583
|
-
static instance = null;
|
|
131584
|
-
static runTails = new Map;
|
|
131585
|
-
discover = new DiscoverStage;
|
|
131586
|
-
parse = new ParseStage;
|
|
131587
|
-
resolve = new ResolveStage;
|
|
131588
|
-
load = new LoadStage;
|
|
131589
|
-
graphGenerations = new GraphGenerationCoordinator;
|
|
131590
|
-
constructor() {}
|
|
131591
|
-
static getInstance() {
|
|
131592
|
-
if (!EtlPipeline.instance) {
|
|
131593
|
-
EtlPipeline.instance = new EtlPipeline;
|
|
131594
|
-
}
|
|
131595
|
-
return EtlPipeline.instance;
|
|
131596
|
-
}
|
|
131597
|
-
async run(input) {
|
|
131598
|
-
await assertParserReadyForIndexing();
|
|
131599
|
-
const projectId = await getProjectIdentityAliasResolver().resolve(input.projectId);
|
|
131600
|
-
const canonicalInput = projectId === input.projectId ? input : { ...input, projectId };
|
|
131601
|
-
const previous = EtlPipeline.runTails.get(projectId);
|
|
131602
|
-
let release;
|
|
131603
|
-
const tail = new Promise((resolve5) => {
|
|
131604
|
-
release = resolve5;
|
|
131605
|
-
});
|
|
131606
|
-
EtlPipeline.runTails.set(projectId, tail);
|
|
131607
|
-
if (previous) {
|
|
131608
|
-
logger.info("EtlPipeline: waiting for prior project run", {
|
|
131609
|
-
projectId,
|
|
131610
|
-
jobId: input.jobId
|
|
131611
|
-
});
|
|
131612
|
-
await previous;
|
|
131613
|
-
}
|
|
131614
|
-
try {
|
|
131615
|
-
return await this.runInternal(canonicalInput);
|
|
131616
|
-
} finally {
|
|
131617
|
-
if (EtlPipeline.runTails.get(projectId) === tail) {
|
|
131618
|
-
EtlPipeline.runTails.delete(projectId);
|
|
131619
|
-
}
|
|
131620
|
-
release();
|
|
131621
|
-
}
|
|
131622
|
-
}
|
|
131623
|
-
async runInternal(input, generationRetry = 0) {
|
|
131624
|
-
const projectId = await getProjectIdentityAliasResolver().resolve(input.projectId);
|
|
131625
|
-
const { projectPath, jobId, forceReindex = false, filesToProcess, include_tests = false, managedRunLease } = input;
|
|
131626
|
-
const t0 = performance.now();
|
|
131627
|
-
const stageTimings = {
|
|
131628
|
-
discover: 0,
|
|
131629
|
-
parse: 0,
|
|
131630
|
-
resolve: 0,
|
|
131631
|
-
load: 0
|
|
131632
|
-
};
|
|
131633
|
-
if (forceReindex) {
|
|
131634
|
-
const vectorStore = await getVectorStore();
|
|
131635
|
-
const keywordSearch = getKeywordSearch();
|
|
131636
|
-
await Promise.all([
|
|
131637
|
-
vectorStore.deleteByProject(projectId),
|
|
131638
|
-
keywordSearch.deleteByProject(projectId)
|
|
131639
|
-
]);
|
|
131640
|
-
}
|
|
131641
|
-
const managedRunRepository = managedRunLease ? ManagedRunRepositoryPg.getInstance() : undefined;
|
|
131642
|
-
const ctx = {
|
|
131643
|
-
projectId,
|
|
131644
|
-
projectPath,
|
|
131645
|
-
jobId,
|
|
131646
|
-
resumeCursor: managedRunLease ? (await managedRunRepository?.getActive(projectId, "indexing"))?.fileCursor ?? undefined : undefined,
|
|
131647
|
-
managedRunLease,
|
|
131648
|
-
emit: (event) => {
|
|
131649
|
-
if (event.type === "progress") {
|
|
131650
|
-
const p = event.payload;
|
|
131651
|
-
indexJobTracker.updateProgress(jobId, p.current, p.total);
|
|
131652
|
-
eventBus.publish("indexing:progress", {
|
|
131653
|
-
jobId,
|
|
131654
|
-
projectId,
|
|
131655
|
-
stage: event.stage,
|
|
131656
|
-
current: p.current,
|
|
131657
|
-
total: p.total,
|
|
131658
|
-
percentage: p.percentage
|
|
131659
|
-
});
|
|
131660
|
-
} else if (event.type === "file_error") {
|
|
131661
|
-
const p = event.payload;
|
|
131662
|
-
eventBus.publish("indexing:file", {
|
|
131663
|
-
jobId,
|
|
131664
|
-
projectId,
|
|
131665
|
-
filePath: p.filePath,
|
|
131666
|
-
stage: event.stage,
|
|
131667
|
-
status: "error",
|
|
131668
|
-
error: p.error
|
|
131669
|
-
});
|
|
131670
|
-
} else if (event.type === "file_processed") {
|
|
131671
|
-
const p = event.payload;
|
|
131672
|
-
eventBus.publish("indexing:file", {
|
|
131673
|
-
jobId,
|
|
131674
|
-
projectId,
|
|
131675
|
-
filePath: p.filePath,
|
|
131676
|
-
stage: event.stage,
|
|
131677
|
-
status: "ok"
|
|
131678
|
-
});
|
|
131679
|
-
}
|
|
131680
|
-
}
|
|
131681
|
-
};
|
|
131682
|
-
eventBus.publish("indexing:started", { jobId, projectId, projectPath });
|
|
131683
|
-
let graphGenerationLease;
|
|
131684
|
-
let graphHeartbeat;
|
|
131685
|
-
let graphHeartbeatFailure;
|
|
131686
|
-
const graphAbortController = new AbortController;
|
|
131687
|
-
const heartbeatTimerController = new AbortController;
|
|
131688
|
-
let stopGraphHeartbeat = false;
|
|
131689
|
-
let managedRunHeartbeat;
|
|
131690
|
-
let managedRunLeaseLost;
|
|
131691
|
-
let stopManagedRunHeartbeat = false;
|
|
131692
|
-
const managedRunTimerController = new AbortController;
|
|
131693
|
-
if (managedRunLease && managedRunRepository) {
|
|
131694
|
-
managedRunHeartbeat = (async () => {
|
|
131695
|
-
while (!stopManagedRunHeartbeat) {
|
|
131696
|
-
try {
|
|
131697
|
-
await delay2(30000, undefined, { signal: managedRunTimerController.signal });
|
|
131698
|
-
} catch {
|
|
131699
|
-
return;
|
|
131700
|
-
}
|
|
131701
|
-
if (stopManagedRunHeartbeat || !managedRunLease)
|
|
131702
|
-
return;
|
|
131703
|
-
try {
|
|
131704
|
-
const outcome2 = await managedRunRepository.heartbeat(managedRunLease);
|
|
131705
|
-
if (outcome2.status === "lease_lost") {
|
|
131706
|
-
managedRunLeaseLost = new Error("managed_run_lease_lost");
|
|
131707
|
-
graphAbortController.abort(managedRunLeaseLost);
|
|
131708
|
-
return;
|
|
131709
|
-
}
|
|
131710
|
-
} catch (heartbeatError) {
|
|
131711
|
-
managedRunLeaseLost = heartbeatError;
|
|
131712
|
-
graphAbortController.abort(managedRunLeaseLost);
|
|
131713
|
-
return;
|
|
131714
|
-
}
|
|
131715
|
-
}
|
|
131716
|
-
})();
|
|
131717
|
-
}
|
|
131718
|
-
try {
|
|
131719
|
-
const st1 = performance.now();
|
|
131720
|
-
const discoveredSnapshot = await this.discover.run(ctx, { forceReindex, includeTests: include_tests });
|
|
131721
|
-
ctx.structuralHeaderEvidenceByFile = buildHeaderLanguageEvidence(discoveredSnapshot);
|
|
131722
|
-
stageTimings.discover = Math.round(performance.now() - st1);
|
|
131723
|
-
const activeGraph = await getSymbolRepository().getActiveGraphSnapshot(projectId);
|
|
131724
|
-
try {
|
|
131725
|
-
graphGenerationLease = await this.graphGenerations.begin({
|
|
131726
|
-
projectId,
|
|
131727
|
-
expectedActiveGenerationId: activeGraph?.generationId ?? null,
|
|
131728
|
-
fingerprint: `sha256:${createHash7("sha256").update(JSON.stringify(STRUCTURAL_FINGERPRINT_INPUTS)).digest("hex")}`,
|
|
131729
|
-
inputSnapshotHash: buildGraphInputSnapshotHash(discoveredSnapshot),
|
|
131730
|
-
expectedFilesCount: discoveredSnapshot.length
|
|
131731
|
-
});
|
|
131732
|
-
} catch (beginError) {
|
|
131733
|
-
if (beginError.message.startsWith("graph_generation_stale_active:") && generationRetry < 3) {
|
|
131734
|
-
stopManagedRunHeartbeat = true;
|
|
131735
|
-
managedRunTimerController.abort();
|
|
131736
|
-
if (managedRunHeartbeat)
|
|
131737
|
-
await managedRunHeartbeat;
|
|
131738
|
-
return this.runInternal(input, generationRetry + 1);
|
|
131739
|
-
}
|
|
131740
|
-
throw beginError;
|
|
131741
|
-
}
|
|
131742
|
-
ctx.graphGenerationLease = graphGenerationLease;
|
|
131743
|
-
ctx.abortSignal = graphAbortController.signal;
|
|
131744
|
-
graphHeartbeat = (async () => {
|
|
131745
|
-
while (!stopGraphHeartbeat) {
|
|
131746
|
-
try {
|
|
131747
|
-
await delay2(30000, undefined, { signal: heartbeatTimerController.signal });
|
|
131748
|
-
} catch {
|
|
131749
|
-
return;
|
|
131750
|
-
}
|
|
131751
|
-
if (stopGraphHeartbeat || !graphGenerationLease)
|
|
131752
|
-
return;
|
|
131753
|
-
try {
|
|
131754
|
-
await this.graphGenerations.heartbeat(graphGenerationLease);
|
|
131755
|
-
} catch (heartbeatError) {
|
|
131756
|
-
graphHeartbeatFailure = heartbeatError;
|
|
131757
|
-
graphAbortController.abort(graphHeartbeatFailure);
|
|
131758
|
-
return;
|
|
131759
|
-
}
|
|
131760
|
-
}
|
|
131761
|
-
})();
|
|
131762
|
-
const requestedPaths = new Set(filesToProcess ?? []);
|
|
131763
|
-
const preparedFiles = discoveredSnapshot.map((file2) => ({
|
|
131764
|
-
...file2,
|
|
131765
|
-
needsReparse: forceReindex || !activeGraph || file2.needsReparse || requestedPaths.has(file2.relativePath)
|
|
131766
|
-
}));
|
|
131767
|
-
if (activeGraph) {
|
|
131768
|
-
for (const file2 of preparedFiles) {
|
|
131769
|
-
if (file2.needsReparse)
|
|
131770
|
-
continue;
|
|
131771
|
-
const copied = await getSymbolRepository().copyFileGeneration(graphGenerationLease, activeGraph.generationId, file2.relativePath);
|
|
131772
|
-
if (copied.status === "lease_lost")
|
|
131773
|
-
throw new Error("graph_generation_lease_lost");
|
|
131774
|
-
if (copied.status === "missing")
|
|
131775
|
-
file2.needsReparse = true;
|
|
131776
|
-
}
|
|
131777
|
-
}
|
|
131778
|
-
const discovered = preparedFiles.map((file2) => Object.freeze(file2));
|
|
131779
|
-
eventBus.publish("indexing:started", {
|
|
131780
|
-
jobId,
|
|
131781
|
-
projectId,
|
|
131782
|
-
projectPath,
|
|
131783
|
-
totalFiles: discovered.filter((f) => f.needsReparse).length
|
|
131784
|
-
});
|
|
131785
|
-
const st2 = performance.now();
|
|
131786
|
-
let remainingFiles = [...discovered];
|
|
131787
|
-
let parsed = [];
|
|
131788
|
-
const staleFailures = new Set;
|
|
131789
|
-
while (remainingFiles.length > 0) {
|
|
131790
|
-
try {
|
|
131791
|
-
parsed.push(...await abortable(this.parse.run(ctx, remainingFiles), graphAbortController.signal));
|
|
131792
|
-
break;
|
|
131793
|
-
} catch (parseError) {
|
|
131794
|
-
if (!activeGraph || forceReindex || !filesToProcess?.length || !(parseError instanceof StructuralEtlParseError) || staleFailures.has(parseError.filePath))
|
|
131795
|
-
throw parseError;
|
|
131796
|
-
staleFailures.add(parseError.filePath);
|
|
131797
|
-
const stale = await getSymbolRepository().markFileStaleGeneration(graphGenerationLease, parseError.filePath, {
|
|
131798
|
-
lastKnownGoodGenerationId: activeGraph.generationId,
|
|
131799
|
-
diagnostics: parseError.diagnostics.length > 0 ? parseError.diagnostics.slice(0, 10).map((diagnostic2) => ({ ...diagnostic2 })) : [{ code: "incremental_structural_failure", message: parseError.message }],
|
|
131800
|
-
parserErrorCount: parseError.diagnosticCount
|
|
131801
|
-
});
|
|
131802
|
-
if (stale.status !== "stale")
|
|
131803
|
-
throw parseError;
|
|
131804
|
-
remainingFiles = remainingFiles.filter((file2) => file2.relativePath !== parseError.filePath);
|
|
131805
|
-
}
|
|
131806
|
-
}
|
|
131807
|
-
if (graphHeartbeatFailure)
|
|
131808
|
-
throw graphHeartbeatFailure;
|
|
131809
|
-
if (managedRunLeaseLost)
|
|
131810
|
-
throw managedRunLeaseLost;
|
|
131811
|
-
stageTimings.parse = Math.round(performance.now() - st2);
|
|
131812
|
-
const st3 = performance.now();
|
|
131813
|
-
const resolved = await abortable(this.resolve.run(ctx, parsed), graphAbortController.signal);
|
|
131814
|
-
if (graphHeartbeatFailure)
|
|
131815
|
-
throw graphHeartbeatFailure;
|
|
131816
|
-
if (managedRunLeaseLost)
|
|
131817
|
-
throw managedRunLeaseLost;
|
|
131818
|
-
stageTimings.resolve = Math.round(performance.now() - st3);
|
|
131819
|
-
const st4 = performance.now();
|
|
131820
|
-
const loadResult = await abortable(this.load.run(ctx, resolved), graphAbortController.signal);
|
|
131821
|
-
if (graphHeartbeatFailure)
|
|
131822
|
-
throw graphHeartbeatFailure;
|
|
131823
|
-
if (managedRunLeaseLost)
|
|
131824
|
-
throw managedRunLeaseLost;
|
|
131825
|
-
stageTimings.load = Math.round(performance.now() - st4);
|
|
131826
|
-
if (loadResult.errors > 0) {
|
|
131827
|
-
logger.warn("EtlPipeline: completed with file errors", {
|
|
131828
|
-
projectId,
|
|
131829
|
-
jobId,
|
|
131830
|
-
errors: loadResult.errors,
|
|
131831
|
-
fileErrors: (loadResult.fileErrors ?? []).slice(0, 10)
|
|
131832
|
-
});
|
|
131833
|
-
}
|
|
131834
|
-
const activationSnapshot = await abortable(this.discover.run(ctx, { forceReindex, includeTests: include_tests }), graphAbortController.signal);
|
|
131835
|
-
if (buildGraphInputSnapshotHash(activationSnapshot) !== graphGenerationLease.inputSnapshotHash) {
|
|
131836
|
-
throw new Error("graph_generation_stale_snapshot");
|
|
131837
|
-
}
|
|
131838
|
-
if (graphHeartbeatFailure)
|
|
131839
|
-
throw graphHeartbeatFailure;
|
|
131840
|
-
if (managedRunLeaseLost)
|
|
131841
|
-
throw managedRunLeaseLost;
|
|
131842
|
-
stopGraphHeartbeat = true;
|
|
131843
|
-
heartbeatTimerController.abort();
|
|
131844
|
-
await graphHeartbeat;
|
|
131845
|
-
stopManagedRunHeartbeat = true;
|
|
131846
|
-
managedRunTimerController.abort();
|
|
131847
|
-
if (managedRunHeartbeat)
|
|
131848
|
-
await managedRunHeartbeat;
|
|
131849
|
-
const activatedGraph = await this.graphGenerations.activate(graphGenerationLease);
|
|
131850
|
-
const activeGraphSummary = await getSymbolRepository().getActiveGraphSnapshot(projectId);
|
|
131851
|
-
if (!activeGraphSummary || activeGraphSummary.generationId !== activatedGraph.generationId) {
|
|
131852
|
-
throw new Error("activated_graph_summary_mismatch");
|
|
131853
|
-
}
|
|
131854
|
-
const durationMs = Math.round(performance.now() - t0);
|
|
131855
|
-
const result = {
|
|
131856
|
-
filesDiscovered: discovered.length,
|
|
131857
|
-
filesIndexed: loadResult.filesLoaded,
|
|
131858
|
-
filesSkipped: discovered.filter((f) => !f.needsReparse).length,
|
|
131859
|
-
chunksIndexed: loadResult.chunksLoaded,
|
|
131860
|
-
symbolsIndexed: loadResult.symbolsLoaded,
|
|
131861
|
-
errors: loadResult.errors,
|
|
131862
|
-
durationMs,
|
|
131863
|
-
stageTimings,
|
|
131864
|
-
activatedGraphGenerationId: activatedGraph.generationId,
|
|
131865
|
-
parserDiagnostics: {
|
|
131866
|
-
diagnosticsCount: activeGraphSummary.diagnostics.errors,
|
|
131867
|
-
recoveredFiles: activeGraphSummary.diagnostics.recovered,
|
|
131868
|
-
hardFailureFiles: activeGraphSummary.diagnostics.hardFailures,
|
|
131869
|
-
staleFiles: activeGraphSummary.diagnostics.staleFiles,
|
|
131870
|
-
languages: activeGraphSummary.languages
|
|
131871
|
-
}
|
|
131872
|
-
};
|
|
131873
|
-
await getSearchCache().invalidateProject(projectId);
|
|
131874
|
-
try {
|
|
131875
|
-
const admissionMarker = new IndexManager(await getVectorStore());
|
|
131876
|
-
await admissionMarker.updateIndexMetadata(projectId, projectPath, discovered.map((file2) => file2.relativePath));
|
|
131877
|
-
} catch (markerError) {
|
|
131878
|
-
logger.warn("EtlPipeline: search-admission marker write failed", {
|
|
131879
|
-
projectId,
|
|
131880
|
-
jobId,
|
|
131881
|
-
error: markerError
|
|
131882
|
-
});
|
|
131883
|
-
}
|
|
131884
|
-
if (forceReindex) {
|
|
131885
|
-
const liveFingerprint = currentEmbeddingFingerprint();
|
|
131886
|
-
if (liveFingerprint !== null) {
|
|
131887
|
-
try {
|
|
131888
|
-
await stampEmbeddingFingerprint(projectId, liveFingerprint);
|
|
131889
|
-
} catch (stampError) {
|
|
131890
|
-
logger.warn("EtlPipeline: embedding fingerprint stamp failed", {
|
|
131891
|
-
projectId,
|
|
131892
|
-
jobId,
|
|
131893
|
-
error: stampError
|
|
131894
|
-
});
|
|
131895
|
-
}
|
|
131896
|
-
}
|
|
131897
|
-
}
|
|
131898
|
-
indexJobTracker.updateProgress(jobId, result.filesIndexed, result.filesIndexed);
|
|
131899
|
-
await indexJobTracker.setResultAndFlush(jobId, {
|
|
131900
|
-
filesIndexed: result.filesIndexed,
|
|
131901
|
-
chunksIndexed: result.chunksIndexed,
|
|
131902
|
-
errors: result.errors,
|
|
131903
|
-
fileErrors: loadResult.fileErrors ?? [],
|
|
131904
|
-
duration: durationMs,
|
|
131905
|
-
activatedGraphGenerationId: result.activatedGraphGenerationId,
|
|
131906
|
-
parserDiagnostics: result.parserDiagnostics
|
|
131907
|
-
});
|
|
131908
|
-
eventBus.publish("indexing:completed", {
|
|
131909
|
-
jobId,
|
|
131910
|
-
projectId,
|
|
131911
|
-
filesIndexed: result.filesIndexed,
|
|
131912
|
-
chunksIndexed: result.chunksIndexed,
|
|
131913
|
-
symbolsIndexed: result.symbolsIndexed,
|
|
131914
|
-
errors: result.errors,
|
|
131915
|
-
durationMs,
|
|
131916
|
-
activatedGraphGenerationId: result.activatedGraphGenerationId
|
|
131917
|
-
});
|
|
131918
|
-
await this.graphGenerations.cleanup(graphGenerationLease);
|
|
131919
|
-
stopGraphHeartbeat = true;
|
|
131920
|
-
heartbeatTimerController.abort();
|
|
131921
|
-
await graphHeartbeat;
|
|
131922
|
-
stopManagedRunHeartbeat = true;
|
|
131923
|
-
managedRunTimerController.abort();
|
|
131924
|
-
if (managedRunHeartbeat)
|
|
131925
|
-
await managedRunHeartbeat;
|
|
131926
|
-
if (managedRunLease && managedRunRepository) {
|
|
131927
|
-
try {
|
|
131928
|
-
await managedRunRepository.complete(managedRunLease);
|
|
131929
|
-
} catch (completeError) {
|
|
131930
|
-
logger.error("EtlPipeline: managed_runs complete failed", completeError, { projectId, jobId });
|
|
131931
|
-
}
|
|
131932
|
-
}
|
|
131933
|
-
logger.info("EtlPipeline: run completed", { projectId, jobId, ...result });
|
|
131934
|
-
return result;
|
|
131935
|
-
} catch (err) {
|
|
131936
|
-
const durationMs = Math.round(performance.now() - t0);
|
|
131937
|
-
const error51 = err.message;
|
|
131938
|
-
if (graphGenerationLease) {
|
|
131939
|
-
try {
|
|
131940
|
-
await this.graphGenerations.abort(graphGenerationLease, error51);
|
|
131941
|
-
} catch (abortError) {
|
|
131942
|
-
logger.error("EtlPipeline: pending generation abort failed", abortError, { projectId, jobId });
|
|
131943
|
-
}
|
|
131944
|
-
}
|
|
131945
|
-
stopGraphHeartbeat = true;
|
|
131946
|
-
heartbeatTimerController.abort();
|
|
131947
|
-
graphAbortController.abort();
|
|
131948
|
-
await graphHeartbeat;
|
|
131949
|
-
stopManagedRunHeartbeat = true;
|
|
131950
|
-
managedRunTimerController.abort();
|
|
131951
|
-
if (managedRunHeartbeat)
|
|
131952
|
-
await managedRunHeartbeat;
|
|
131953
|
-
if (managedRunLease && managedRunRepository) {
|
|
131954
|
-
try {
|
|
131955
|
-
const outcome2 = await managedRunRepository.abort(managedRunLease);
|
|
131956
|
-
if (outcome2.status === "lease_lost") {
|
|
131957
|
-
logger.warn("EtlPipeline: managed_runs abort saw lease_lost", { projectId, jobId });
|
|
131958
|
-
}
|
|
131959
|
-
} catch (abortError) {
|
|
131960
|
-
logger.error("EtlPipeline: managed_runs abort failed", abortError, { projectId, jobId });
|
|
131961
|
-
}
|
|
131962
|
-
}
|
|
131963
|
-
eventBus.publish("indexing:failed", { jobId, projectId, error: error51, durationMs });
|
|
131964
|
-
indexJobTracker.setResult(jobId, { filesIndexed: 0, chunksIndexed: 0, errors: 1, duration: durationMs }, error51);
|
|
131965
|
-
logger.error("EtlPipeline: run failed", err, { projectId, jobId, durationMs });
|
|
131966
|
-
throw err;
|
|
131967
|
-
}
|
|
131968
|
-
}
|
|
131969
|
-
};
|
|
131970
|
-
});
|
|
131971
|
-
|
|
131972
|
-
// ../../packages/core/dist/services/indexing/execute-indexing.js
|
|
131973
|
-
async function executeIndexing(request) {
|
|
131974
|
-
const { jobId, projectId, projectPath, forceReindex, warmCache, warmupQueries, include_tests = false, managedRunLease, warmupCache: warmupCache2 } = request;
|
|
131975
|
-
const startTime = Date.now();
|
|
131976
|
-
try {
|
|
131977
|
-
indexJobTracker.updateStatus(jobId, "running");
|
|
131978
|
-
logger.info("Starting project indexing via ETL Pipeline", {
|
|
131979
|
-
jobId,
|
|
131980
|
-
projectPath,
|
|
131981
|
-
projectId,
|
|
131982
|
-
forceReindex,
|
|
131983
|
-
warmCache,
|
|
131984
|
-
include_tests
|
|
131985
|
-
});
|
|
131986
|
-
const etlResult = await EtlPipeline.getInstance().run({
|
|
131987
|
-
projectId,
|
|
131988
|
-
projectPath,
|
|
131989
|
-
jobId,
|
|
131990
|
-
forceReindex,
|
|
131991
|
-
include_tests,
|
|
131992
|
-
managedRunLease
|
|
131993
|
-
});
|
|
131994
|
-
const duration3 = Date.now() - startTime;
|
|
131995
|
-
logger.info("ETL Pipeline completed", {
|
|
131996
|
-
jobId,
|
|
131997
|
-
projectId,
|
|
131998
|
-
duration: duration3,
|
|
131999
|
-
filesIndexed: etlResult.filesIndexed,
|
|
132000
|
-
filesSkipped: etlResult.filesSkipped,
|
|
132001
|
-
chunksIndexed: etlResult.chunksIndexed,
|
|
132002
|
-
symbolsIndexed: etlResult.symbolsIndexed,
|
|
132003
|
-
errors: etlResult.errors,
|
|
132004
|
-
stageTimings: etlResult.stageTimings
|
|
132005
|
-
});
|
|
132006
|
-
if (warmCache) {
|
|
132007
|
-
logger.info("Starting cache warmup", { jobId, projectId });
|
|
132008
|
-
const warmupStats = await warmupCache2(projectId, projectPath, warmupQueries);
|
|
132009
|
-
logger.info("Cache warmup completed", { jobId, projectId, ...warmupStats });
|
|
132010
|
-
}
|
|
132011
|
-
indexJobTracker.updateProgress(jobId, etlResult.filesIndexed, etlResult.filesIndexed);
|
|
132012
|
-
await indexJobTracker.setResultAndFlush(jobId, {
|
|
132013
|
-
filesIndexed: etlResult.filesIndexed,
|
|
132014
|
-
chunksIndexed: etlResult.chunksIndexed,
|
|
132015
|
-
errors: etlResult.errors,
|
|
132016
|
-
duration: duration3,
|
|
132017
|
-
activatedGraphGenerationId: etlResult.activatedGraphGenerationId,
|
|
132018
|
-
parserDiagnostics: etlResult.parserDiagnostics
|
|
132019
|
-
});
|
|
132020
|
-
} catch (error51) {
|
|
132021
|
-
const duration3 = Date.now() - startTime;
|
|
132022
|
-
logger.error("Project indexing failed", error51, {
|
|
132023
|
-
jobId,
|
|
132024
|
-
projectPath,
|
|
132025
|
-
projectId,
|
|
132026
|
-
duration: duration3
|
|
132027
|
-
});
|
|
132028
|
-
indexJobTracker.setResult(jobId, {
|
|
132029
|
-
filesIndexed: 0,
|
|
132030
|
-
chunksIndexed: 0,
|
|
132031
|
-
errors: 1,
|
|
132032
|
-
duration: duration3
|
|
132033
|
-
}, error51.message);
|
|
132034
|
-
}
|
|
132035
|
-
}
|
|
132036
|
-
var init_execute_indexing = __esm(() => {
|
|
132037
|
-
init_dist();
|
|
132038
|
-
init_index_job_tracker();
|
|
132039
|
-
init_pipeline();
|
|
132040
|
-
});
|
|
132041
|
-
|
|
132042
|
-
// ../../packages/core/dist/services/indexing/acquire-indexing-lease.js
|
|
132043
|
-
async function acquireIndexingLease(request) {
|
|
132044
|
-
const { jobId, projectId } = request;
|
|
132045
|
-
const eventId = `index:${jobId}`;
|
|
132046
|
-
const managedRunRepo = ManagedRunRepositoryPg.getInstance();
|
|
132047
|
-
try {
|
|
132048
|
-
const beginOutcome = await managedRunRepo.begin({
|
|
132049
|
-
projectId,
|
|
132050
|
-
runKind: "indexing",
|
|
132051
|
-
eventId
|
|
132052
|
-
});
|
|
132053
|
-
if (beginOutcome.status === "busy") {
|
|
132054
|
-
indexJobTracker.setResult(jobId, { filesIndexed: 0, chunksIndexed: 0, errors: 0, duration: 0 }, `indexing_busy:${beginOutcome.activeRunId}`);
|
|
132055
|
-
return {
|
|
132056
|
-
status: "busy",
|
|
132057
|
-
activeRunId: beginOutcome.activeRunId,
|
|
132058
|
-
leaseExpiresAt: beginOutcome.leaseExpiresAt
|
|
132059
|
-
};
|
|
132060
|
-
}
|
|
132061
|
-
return { status: "acquired", lease: beginOutcome.lease };
|
|
132062
|
-
} catch (beginError) {
|
|
132063
|
-
logger.error("managed_runs begin failed", beginError, {
|
|
132064
|
-
jobId,
|
|
132065
|
-
projectId
|
|
132066
|
-
});
|
|
132067
|
-
indexJobTracker.setResult(jobId, { filesIndexed: 0, chunksIndexed: 0, errors: 1, duration: 0 }, `managed_runs_begin_failed:${beginError.message}`);
|
|
132068
|
-
return { status: "failed", message: beginError.message };
|
|
132069
|
-
}
|
|
132070
|
-
}
|
|
132071
|
-
var init_acquire_indexing_lease = __esm(() => {
|
|
132072
|
-
init_dist();
|
|
132073
|
-
init_index_job_tracker();
|
|
132074
|
-
init_managed_run_repository_pg();
|
|
132075
|
-
});
|
|
132076
|
-
|
|
132077
|
-
// ../../packages/core/dist/services/project-identity/project-root-identity.js
|
|
132078
|
-
import { realpath as realpath2 } from "fs/promises";
|
|
132079
|
-
import path29 from "path";
|
|
132080
|
-
async function canonicalizeProjectRoot(projectPath, canonicalize = realpath2) {
|
|
132081
|
-
return canonicalize(path29.resolve(projectPath));
|
|
132082
|
-
}
|
|
132083
|
-
async function assertProjectRootReuse(options) {
|
|
132084
|
-
if (!options.storedProjectPath || options.forceReindex)
|
|
132085
|
-
return;
|
|
132086
|
-
const canonicalize = options.canonicalize ?? realpath2;
|
|
132087
|
-
let storedCanonical;
|
|
132088
|
-
try {
|
|
132089
|
-
storedCanonical = await canonicalize(path29.resolve(options.storedProjectPath));
|
|
132090
|
-
} catch {
|
|
132091
|
-
storedCanonical = path29.resolve(options.storedProjectPath);
|
|
132092
|
-
}
|
|
132093
|
-
if (storedCanonical !== options.canonicalProjectPath) {
|
|
132094
|
-
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");
|
|
132095
|
-
}
|
|
132096
|
-
}
|
|
132097
|
-
var init_project_root_identity = () => {};
|
|
132098
|
-
|
|
132099
131610
|
// ../../packages/core/dist/services/symbol/definition-lookup.js
|
|
132100
131611
|
function toSymbolIdentityResolution(result) {
|
|
132101
131612
|
switch (result.status) {
|
|
@@ -132116,8 +131627,8 @@ function toSymbolIdentityResolution(result) {
|
|
|
132116
131627
|
|
|
132117
131628
|
class DefinitionLookupService {
|
|
132118
131629
|
repository;
|
|
132119
|
-
constructor(
|
|
132120
|
-
this.repository =
|
|
131630
|
+
constructor(repository2 = getSymbolRepository) {
|
|
131631
|
+
this.repository = repository2;
|
|
132121
131632
|
}
|
|
132122
131633
|
async lookup(projectId, query) {
|
|
132123
131634
|
const repo = this.repository();
|
|
@@ -132831,16 +132342,16 @@ function detectRoutes(httpEdges, defs, opts = {}) {
|
|
|
132831
132342
|
const seen = new Set;
|
|
132832
132343
|
const out = [];
|
|
132833
132344
|
for (const e of httpEdges) {
|
|
132834
|
-
const
|
|
132835
|
-
if (!
|
|
132345
|
+
const path29 = e.route;
|
|
132346
|
+
if (!path29)
|
|
132836
132347
|
continue;
|
|
132837
132348
|
const method = (e.method ?? "ANY").toUpperCase();
|
|
132838
|
-
const key = method + " " +
|
|
132349
|
+
const key = method + " " + path29;
|
|
132839
132350
|
if (seen.has(key))
|
|
132840
132351
|
continue;
|
|
132841
132352
|
seen.add(key);
|
|
132842
132353
|
out.push({
|
|
132843
|
-
path:
|
|
132354
|
+
path: path29,
|
|
132844
132355
|
method: e.method,
|
|
132845
132356
|
file: e.fromFile,
|
|
132846
132357
|
handler: e.targetFqn ?? e.symbolName
|
|
@@ -132851,12 +132362,12 @@ function detectRoutes(httpEdges, defs, opts = {}) {
|
|
|
132851
132362
|
continue;
|
|
132852
132363
|
const parsed = parseRouteName(d.name);
|
|
132853
132364
|
const method = parsed?.method ?? "ANY";
|
|
132854
|
-
const
|
|
132855
|
-
const key = method + " " +
|
|
132365
|
+
const path29 = parsed?.path ?? d.name;
|
|
132366
|
+
const key = method + " " + path29;
|
|
132856
132367
|
if (seen.has(key))
|
|
132857
132368
|
continue;
|
|
132858
132369
|
seen.add(key);
|
|
132859
|
-
out.push({ path:
|
|
132370
|
+
out.push({ path: path29, method: parsed?.method, file: d.filePath, handler: d.name });
|
|
132860
132371
|
}
|
|
132861
132372
|
for (const d of defs) {
|
|
132862
132373
|
const parsed = parseRouteName(d.name);
|
|
@@ -133077,7 +132588,7 @@ __export(exports_symbol_graph_service, {
|
|
|
133077
132588
|
symbolGraphService: () => symbolGraphService,
|
|
133078
132589
|
SymbolGraphService: () => SymbolGraphService
|
|
133079
132590
|
});
|
|
133080
|
-
import
|
|
132591
|
+
import path29 from "path";
|
|
133081
132592
|
import fs19 from "fs/promises";
|
|
133082
132593
|
|
|
133083
132594
|
class SymbolGraphService {
|
|
@@ -133431,7 +132942,7 @@ class SymbolGraphService {
|
|
|
133431
132942
|
}
|
|
133432
132943
|
async resolveToAbsolute(relativePath, projectId) {
|
|
133433
132944
|
const root = await this.getProjectRoot(projectId);
|
|
133434
|
-
return root ?
|
|
132945
|
+
return root ? path29.resolve(root, relativePath) : relativePath;
|
|
133435
132946
|
}
|
|
133436
132947
|
async getProjectRoot(projectId) {
|
|
133437
132948
|
const cached2 = this.projectRootCache.get(projectId);
|
|
@@ -133545,7 +133056,7 @@ class WorkspaceManager {
|
|
|
133545
133056
|
return matches[0];
|
|
133546
133057
|
}
|
|
133547
133058
|
async removeWorkspace(projectId) {
|
|
133548
|
-
await getSymbolRepository().clearProject(projectId);
|
|
133059
|
+
await withHeavyWorkLease("maintenance", `workspace-remove:${projectId}`, () => getSymbolRepository().clearProject(projectId));
|
|
133549
133060
|
logger.info("WorkspaceManager: workspace removed", { projectId });
|
|
133550
133061
|
}
|
|
133551
133062
|
subscribeToEvents() {
|
|
@@ -133570,11 +133081,633 @@ var init_workspace_manager = __esm(() => {
|
|
|
133570
133081
|
init_symbol_repository_factory();
|
|
133571
133082
|
init_event_bus();
|
|
133572
133083
|
init_symbol_graph_service();
|
|
133084
|
+
init_heavy_work_lease();
|
|
133573
133085
|
workspaceManager = WorkspaceManager.getInstance();
|
|
133574
133086
|
});
|
|
133575
133087
|
|
|
133576
|
-
// ../../packages/core/dist/
|
|
133088
|
+
// ../../packages/core/dist/services/etl/pipeline.js
|
|
133089
|
+
import { createHash as createHash7 } from "crypto";
|
|
133090
|
+
import { setTimeout as delay3 } from "timers/promises";
|
|
133091
|
+
import path30 from "path";
|
|
133092
|
+
function buildHeaderLanguageEvidence(files) {
|
|
133093
|
+
const headers = new Set(files.filter((file2) => path30.posix.extname(file2.relativePath).toLowerCase() === ".h").map((file2) => path30.posix.normalize(file2.relativePath)));
|
|
133094
|
+
const mutable = new Map;
|
|
133095
|
+
const entry2 = (header) => {
|
|
133096
|
+
let value = mutable.get(header);
|
|
133097
|
+
if (!value) {
|
|
133098
|
+
value = { cImporters: new Set, cppImporters: new Set, build: new Set };
|
|
133099
|
+
mutable.set(header, value);
|
|
133100
|
+
}
|
|
133101
|
+
return value;
|
|
133102
|
+
};
|
|
133103
|
+
for (const file2 of files) {
|
|
133104
|
+
if (path30.posix.basename(file2.relativePath) !== "compile_commands.json" || file2.snapshotContent === undefined)
|
|
133105
|
+
continue;
|
|
133106
|
+
let commands;
|
|
133107
|
+
try {
|
|
133108
|
+
commands = JSON.parse(file2.snapshotContent);
|
|
133109
|
+
} catch {
|
|
133110
|
+
continue;
|
|
133111
|
+
}
|
|
133112
|
+
if (!Array.isArray(commands))
|
|
133113
|
+
continue;
|
|
133114
|
+
for (const command of commands) {
|
|
133115
|
+
if (!command || typeof command !== "object")
|
|
133116
|
+
continue;
|
|
133117
|
+
const record3 = command;
|
|
133118
|
+
if (typeof record3.file !== "string")
|
|
133119
|
+
continue;
|
|
133120
|
+
const projectRoot = path30.resolve(file2.absolutePath, ...file2.relativePath.split("/").map(() => ".."));
|
|
133121
|
+
const commandDirectory = typeof record3.directory === "string" ? path30.resolve(projectRoot, record3.directory) : projectRoot;
|
|
133122
|
+
const absoluteInput = path30.resolve(commandDirectory, record3.file);
|
|
133123
|
+
const relative2 = path30.relative(projectRoot, absoluteInput);
|
|
133124
|
+
const header = path30.posix.normalize(relative2.replaceAll(path30.sep, "/"));
|
|
133125
|
+
if (!headers.has(header))
|
|
133126
|
+
continue;
|
|
133127
|
+
const invocation = typeof record3.command === "string" ? record3.command : Array.isArray(record3.arguments) ? record3.arguments.join(" ") : "";
|
|
133128
|
+
if (/(?:^|\s)(?:clang\+\+|g\+\+|c\+\+)(?:\s|$)|(?:^|\s)-x\s*c\+\+(?:\s|$)/u.test(invocation))
|
|
133129
|
+
entry2(header).build.add("cpp");
|
|
133130
|
+
else if (/(?:^|\s)(?:clang|gcc|cc)(?:\s|$)|(?:^|\s)-x\s*c(?:\s|$)/u.test(invocation))
|
|
133131
|
+
entry2(header).build.add("c");
|
|
133132
|
+
}
|
|
133133
|
+
}
|
|
133134
|
+
return Object.freeze(Object.fromEntries([...mutable.entries()].sort(([a], [b]) => a.localeCompare(b)).map(([header, value]) => [header, Object.freeze({
|
|
133135
|
+
...value.cImporters.size ? { cImporters: Object.freeze([...value.cImporters].sort()) } : {},
|
|
133136
|
+
...value.cppImporters.size ? { cppImporters: Object.freeze([...value.cppImporters].sort()) } : {},
|
|
133137
|
+
...value.build.size ? { buildLanguage: value.build.size > 1 ? "conflict" : [...value.build][0] } : {}
|
|
133138
|
+
})])));
|
|
133139
|
+
}
|
|
133140
|
+
function abortable(operation, signal) {
|
|
133141
|
+
if (signal.aborted)
|
|
133142
|
+
return Promise.reject(signal.reason);
|
|
133143
|
+
return new Promise((resolve5, reject) => {
|
|
133144
|
+
let abortReason;
|
|
133145
|
+
const onAbort = () => {
|
|
133146
|
+
abortReason = signal.reason;
|
|
133147
|
+
};
|
|
133148
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
133149
|
+
operation.then((value) => abortReason === undefined ? resolve5(value) : reject(abortReason), (error51) => reject(abortReason ?? error51)).finally(() => signal.removeEventListener("abort", onAbort));
|
|
133150
|
+
});
|
|
133151
|
+
}
|
|
133152
|
+
var EtlPipeline;
|
|
133153
|
+
var init_pipeline = __esm(() => {
|
|
133154
|
+
init_dist();
|
|
133155
|
+
init_discover();
|
|
133156
|
+
init_parse3();
|
|
133157
|
+
init_resolve();
|
|
133158
|
+
init_load();
|
|
133159
|
+
init_event_bus();
|
|
133160
|
+
init_symbol_repository_factory();
|
|
133161
|
+
init_index_job_tracker();
|
|
133162
|
+
init_cache_factory();
|
|
133163
|
+
init_index_manager();
|
|
133164
|
+
init_vector_store_factory();
|
|
133165
|
+
init_keyword_search_factory();
|
|
133166
|
+
init_alias_resolver();
|
|
133167
|
+
init_symbol_repo_workspace();
|
|
133168
|
+
init_project_indexer();
|
|
133169
|
+
init_parser_readiness();
|
|
133170
|
+
init_parse3();
|
|
133171
|
+
init_language_manifest();
|
|
133172
|
+
init_graph_generation_coordinator();
|
|
133173
|
+
init_managed_run_repository_pg();
|
|
133174
|
+
init_workspace_manager();
|
|
133175
|
+
EtlPipeline = class EtlPipeline {
|
|
133176
|
+
static instance = null;
|
|
133177
|
+
static runTails = new Map;
|
|
133178
|
+
discover = new DiscoverStage;
|
|
133179
|
+
parse = new ParseStage;
|
|
133180
|
+
resolve = new ResolveStage;
|
|
133181
|
+
load = new LoadStage;
|
|
133182
|
+
graphGenerations = new GraphGenerationCoordinator;
|
|
133183
|
+
constructor() {}
|
|
133184
|
+
static getInstance() {
|
|
133185
|
+
if (!EtlPipeline.instance) {
|
|
133186
|
+
EtlPipeline.instance = new EtlPipeline;
|
|
133187
|
+
}
|
|
133188
|
+
return EtlPipeline.instance;
|
|
133189
|
+
}
|
|
133190
|
+
async run(input) {
|
|
133191
|
+
await assertParserReadyForIndexing();
|
|
133192
|
+
const projectId = await getProjectIdentityAliasResolver().resolve(input.projectId);
|
|
133193
|
+
const canonicalInput = projectId === input.projectId ? input : { ...input, projectId };
|
|
133194
|
+
const previous = EtlPipeline.runTails.get(projectId);
|
|
133195
|
+
let release;
|
|
133196
|
+
const tail = new Promise((resolve5) => {
|
|
133197
|
+
release = resolve5;
|
|
133198
|
+
});
|
|
133199
|
+
EtlPipeline.runTails.set(projectId, tail);
|
|
133200
|
+
if (previous) {
|
|
133201
|
+
logger.info("EtlPipeline: waiting for prior project run", {
|
|
133202
|
+
projectId,
|
|
133203
|
+
jobId: input.jobId
|
|
133204
|
+
});
|
|
133205
|
+
await previous;
|
|
133206
|
+
}
|
|
133207
|
+
try {
|
|
133208
|
+
return await this.runInternal(canonicalInput);
|
|
133209
|
+
} finally {
|
|
133210
|
+
if (EtlPipeline.runTails.get(projectId) === tail) {
|
|
133211
|
+
EtlPipeline.runTails.delete(projectId);
|
|
133212
|
+
}
|
|
133213
|
+
release();
|
|
133214
|
+
}
|
|
133215
|
+
}
|
|
133216
|
+
async runInternal(input, generationRetry = 0) {
|
|
133217
|
+
const projectId = await getProjectIdentityAliasResolver().resolve(input.projectId);
|
|
133218
|
+
const { projectPath, jobId, forceReindex = false, filesToProcess, include_tests = false, managedRunLease } = input;
|
|
133219
|
+
const t0 = performance.now();
|
|
133220
|
+
const stageTimings = {
|
|
133221
|
+
discover: 0,
|
|
133222
|
+
parse: 0,
|
|
133223
|
+
resolve: 0,
|
|
133224
|
+
load: 0
|
|
133225
|
+
};
|
|
133226
|
+
if (forceReindex) {
|
|
133227
|
+
const vectorStore = await getVectorStore();
|
|
133228
|
+
const keywordSearch = getKeywordSearch();
|
|
133229
|
+
await Promise.all([
|
|
133230
|
+
vectorStore.deleteByProject(projectId),
|
|
133231
|
+
keywordSearch.deleteByProject(projectId)
|
|
133232
|
+
]);
|
|
133233
|
+
}
|
|
133234
|
+
const managedRunRepository = managedRunLease ? ManagedRunRepositoryPg.getInstance() : undefined;
|
|
133235
|
+
const ctx = {
|
|
133236
|
+
projectId,
|
|
133237
|
+
projectPath,
|
|
133238
|
+
jobId,
|
|
133239
|
+
resumeCursor: managedRunLease ? (await managedRunRepository?.getActive(projectId, "indexing"))?.fileCursor ?? undefined : undefined,
|
|
133240
|
+
managedRunLease,
|
|
133241
|
+
emit: (event) => {
|
|
133242
|
+
if (event.type === "progress") {
|
|
133243
|
+
const p = event.payload;
|
|
133244
|
+
indexJobTracker.updateProgress(jobId, p.current, p.total);
|
|
133245
|
+
eventBus.publish("indexing:progress", {
|
|
133246
|
+
jobId,
|
|
133247
|
+
projectId,
|
|
133248
|
+
stage: event.stage,
|
|
133249
|
+
current: p.current,
|
|
133250
|
+
total: p.total,
|
|
133251
|
+
percentage: p.percentage
|
|
133252
|
+
});
|
|
133253
|
+
} else if (event.type === "file_error") {
|
|
133254
|
+
const p = event.payload;
|
|
133255
|
+
eventBus.publish("indexing:file", {
|
|
133256
|
+
jobId,
|
|
133257
|
+
projectId,
|
|
133258
|
+
filePath: p.filePath,
|
|
133259
|
+
stage: event.stage,
|
|
133260
|
+
status: "error",
|
|
133261
|
+
error: p.error
|
|
133262
|
+
});
|
|
133263
|
+
} else if (event.type === "file_processed") {
|
|
133264
|
+
const p = event.payload;
|
|
133265
|
+
eventBus.publish("indexing:file", {
|
|
133266
|
+
jobId,
|
|
133267
|
+
projectId,
|
|
133268
|
+
filePath: p.filePath,
|
|
133269
|
+
stage: event.stage,
|
|
133270
|
+
status: "ok"
|
|
133271
|
+
});
|
|
133272
|
+
}
|
|
133273
|
+
}
|
|
133274
|
+
};
|
|
133275
|
+
eventBus.publish("indexing:started", { jobId, projectId, projectPath });
|
|
133276
|
+
let graphGenerationLease;
|
|
133277
|
+
let graphHeartbeat;
|
|
133278
|
+
let graphHeartbeatFailure;
|
|
133279
|
+
const graphAbortController = new AbortController;
|
|
133280
|
+
const heartbeatTimerController = new AbortController;
|
|
133281
|
+
let stopGraphHeartbeat = false;
|
|
133282
|
+
let managedRunHeartbeat;
|
|
133283
|
+
let managedRunLeaseLost;
|
|
133284
|
+
let stopManagedRunHeartbeat = false;
|
|
133285
|
+
const managedRunTimerController = new AbortController;
|
|
133286
|
+
if (managedRunLease && managedRunRepository) {
|
|
133287
|
+
managedRunHeartbeat = (async () => {
|
|
133288
|
+
while (!stopManagedRunHeartbeat) {
|
|
133289
|
+
try {
|
|
133290
|
+
await delay3(30000, undefined, { signal: managedRunTimerController.signal });
|
|
133291
|
+
} catch {
|
|
133292
|
+
return;
|
|
133293
|
+
}
|
|
133294
|
+
if (stopManagedRunHeartbeat || !managedRunLease)
|
|
133295
|
+
return;
|
|
133296
|
+
try {
|
|
133297
|
+
const outcome2 = await managedRunRepository.heartbeat(managedRunLease);
|
|
133298
|
+
if (outcome2.status === "lease_lost") {
|
|
133299
|
+
managedRunLeaseLost = new Error("managed_run_lease_lost");
|
|
133300
|
+
graphAbortController.abort(managedRunLeaseLost);
|
|
133301
|
+
return;
|
|
133302
|
+
}
|
|
133303
|
+
} catch (heartbeatError) {
|
|
133304
|
+
managedRunLeaseLost = heartbeatError;
|
|
133305
|
+
graphAbortController.abort(managedRunLeaseLost);
|
|
133306
|
+
return;
|
|
133307
|
+
}
|
|
133308
|
+
}
|
|
133309
|
+
})();
|
|
133310
|
+
}
|
|
133311
|
+
const jobHeartbeatController = new AbortController;
|
|
133312
|
+
(async () => {
|
|
133313
|
+
while (true) {
|
|
133314
|
+
try {
|
|
133315
|
+
await delay3(30000, undefined, { signal: jobHeartbeatController.signal });
|
|
133316
|
+
} catch {
|
|
133317
|
+
return;
|
|
133318
|
+
}
|
|
133319
|
+
try {
|
|
133320
|
+
indexJobTracker.heartbeat(jobId);
|
|
133321
|
+
} catch {}
|
|
133322
|
+
}
|
|
133323
|
+
})();
|
|
133324
|
+
try {
|
|
133325
|
+
const st1 = performance.now();
|
|
133326
|
+
const discoveredSnapshot = await this.discover.run(ctx, { forceReindex, includeTests: include_tests });
|
|
133327
|
+
ctx.structuralHeaderEvidenceByFile = buildHeaderLanguageEvidence(discoveredSnapshot);
|
|
133328
|
+
stageTimings.discover = Math.round(performance.now() - st1);
|
|
133329
|
+
await workspaceManager.markIndexing(projectId, projectPath);
|
|
133330
|
+
const activeGraph = await getSymbolRepository().getActiveGraphSnapshot(projectId);
|
|
133331
|
+
try {
|
|
133332
|
+
graphGenerationLease = await this.graphGenerations.begin({
|
|
133333
|
+
projectId,
|
|
133334
|
+
expectedActiveGenerationId: activeGraph?.generationId ?? null,
|
|
133335
|
+
fingerprint: `sha256:${createHash7("sha256").update(JSON.stringify(STRUCTURAL_FINGERPRINT_INPUTS)).digest("hex")}`,
|
|
133336
|
+
inputSnapshotHash: buildGraphInputSnapshotHash(discoveredSnapshot),
|
|
133337
|
+
expectedFilesCount: discoveredSnapshot.length
|
|
133338
|
+
});
|
|
133339
|
+
} catch (beginError) {
|
|
133340
|
+
if (beginError.message.startsWith("graph_generation_stale_active:") && generationRetry < 3) {
|
|
133341
|
+
stopManagedRunHeartbeat = true;
|
|
133342
|
+
managedRunTimerController.abort();
|
|
133343
|
+
jobHeartbeatController.abort();
|
|
133344
|
+
if (managedRunHeartbeat)
|
|
133345
|
+
await managedRunHeartbeat;
|
|
133346
|
+
return this.runInternal(input, generationRetry + 1);
|
|
133347
|
+
}
|
|
133348
|
+
throw beginError;
|
|
133349
|
+
}
|
|
133350
|
+
ctx.graphGenerationLease = graphGenerationLease;
|
|
133351
|
+
ctx.abortSignal = graphAbortController.signal;
|
|
133352
|
+
graphHeartbeat = (async () => {
|
|
133353
|
+
while (!stopGraphHeartbeat) {
|
|
133354
|
+
try {
|
|
133355
|
+
await delay3(30000, undefined, { signal: heartbeatTimerController.signal });
|
|
133356
|
+
} catch {
|
|
133357
|
+
return;
|
|
133358
|
+
}
|
|
133359
|
+
if (stopGraphHeartbeat || !graphGenerationLease)
|
|
133360
|
+
return;
|
|
133361
|
+
try {
|
|
133362
|
+
await this.graphGenerations.heartbeat(graphGenerationLease);
|
|
133363
|
+
} catch (heartbeatError) {
|
|
133364
|
+
graphHeartbeatFailure = heartbeatError;
|
|
133365
|
+
graphAbortController.abort(graphHeartbeatFailure);
|
|
133366
|
+
return;
|
|
133367
|
+
}
|
|
133368
|
+
}
|
|
133369
|
+
})();
|
|
133370
|
+
const requestedPaths = new Set(filesToProcess ?? []);
|
|
133371
|
+
const preparedFiles = discoveredSnapshot.map((file2) => ({
|
|
133372
|
+
...file2,
|
|
133373
|
+
needsReparse: forceReindex || !activeGraph || file2.needsReparse || requestedPaths.has(file2.relativePath)
|
|
133374
|
+
}));
|
|
133375
|
+
if (activeGraph) {
|
|
133376
|
+
for (const file2 of preparedFiles) {
|
|
133377
|
+
if (file2.needsReparse)
|
|
133378
|
+
continue;
|
|
133379
|
+
const copied = await getSymbolRepository().copyFileGeneration(graphGenerationLease, activeGraph.generationId, file2.relativePath);
|
|
133380
|
+
if (copied.status === "lease_lost")
|
|
133381
|
+
throw new Error("graph_generation_lease_lost");
|
|
133382
|
+
if (copied.status === "missing")
|
|
133383
|
+
file2.needsReparse = true;
|
|
133384
|
+
}
|
|
133385
|
+
}
|
|
133386
|
+
const discovered = preparedFiles.map((file2) => Object.freeze(file2));
|
|
133387
|
+
eventBus.publish("indexing:started", {
|
|
133388
|
+
jobId,
|
|
133389
|
+
projectId,
|
|
133390
|
+
projectPath,
|
|
133391
|
+
totalFiles: discovered.filter((f) => f.needsReparse).length
|
|
133392
|
+
});
|
|
133393
|
+
const st2 = performance.now();
|
|
133394
|
+
let remainingFiles = [...discovered];
|
|
133395
|
+
let parsed = [];
|
|
133396
|
+
const staleFailures = new Set;
|
|
133397
|
+
while (remainingFiles.length > 0) {
|
|
133398
|
+
try {
|
|
133399
|
+
parsed.push(...await abortable(this.parse.run(ctx, remainingFiles), graphAbortController.signal));
|
|
133400
|
+
break;
|
|
133401
|
+
} catch (parseError) {
|
|
133402
|
+
if (!activeGraph || forceReindex || !filesToProcess?.length || !(parseError instanceof StructuralEtlParseError) || staleFailures.has(parseError.filePath))
|
|
133403
|
+
throw parseError;
|
|
133404
|
+
staleFailures.add(parseError.filePath);
|
|
133405
|
+
const stale = await getSymbolRepository().markFileStaleGeneration(graphGenerationLease, parseError.filePath, {
|
|
133406
|
+
lastKnownGoodGenerationId: activeGraph.generationId,
|
|
133407
|
+
diagnostics: parseError.diagnostics.length > 0 ? parseError.diagnostics.slice(0, 10).map((diagnostic2) => ({ ...diagnostic2 })) : [{ code: "incremental_structural_failure", message: parseError.message }],
|
|
133408
|
+
parserErrorCount: parseError.diagnosticCount
|
|
133409
|
+
});
|
|
133410
|
+
if (stale.status !== "stale")
|
|
133411
|
+
throw parseError;
|
|
133412
|
+
remainingFiles = remainingFiles.filter((file2) => file2.relativePath !== parseError.filePath);
|
|
133413
|
+
}
|
|
133414
|
+
}
|
|
133415
|
+
if (graphHeartbeatFailure)
|
|
133416
|
+
throw graphHeartbeatFailure;
|
|
133417
|
+
if (managedRunLeaseLost)
|
|
133418
|
+
throw managedRunLeaseLost;
|
|
133419
|
+
stageTimings.parse = Math.round(performance.now() - st2);
|
|
133420
|
+
const st3 = performance.now();
|
|
133421
|
+
const resolved = await abortable(this.resolve.run(ctx, parsed), graphAbortController.signal);
|
|
133422
|
+
if (graphHeartbeatFailure)
|
|
133423
|
+
throw graphHeartbeatFailure;
|
|
133424
|
+
if (managedRunLeaseLost)
|
|
133425
|
+
throw managedRunLeaseLost;
|
|
133426
|
+
stageTimings.resolve = Math.round(performance.now() - st3);
|
|
133427
|
+
const st4 = performance.now();
|
|
133428
|
+
const loadResult = await abortable(this.load.run(ctx, resolved), graphAbortController.signal);
|
|
133429
|
+
if (graphHeartbeatFailure)
|
|
133430
|
+
throw graphHeartbeatFailure;
|
|
133431
|
+
if (managedRunLeaseLost)
|
|
133432
|
+
throw managedRunLeaseLost;
|
|
133433
|
+
stageTimings.load = Math.round(performance.now() - st4);
|
|
133434
|
+
if (loadResult.errors > 0) {
|
|
133435
|
+
logger.warn("EtlPipeline: completed with file errors", {
|
|
133436
|
+
projectId,
|
|
133437
|
+
jobId,
|
|
133438
|
+
errors: loadResult.errors,
|
|
133439
|
+
fileErrors: (loadResult.fileErrors ?? []).slice(0, 10)
|
|
133440
|
+
});
|
|
133441
|
+
}
|
|
133442
|
+
const activationSnapshot = await abortable(this.discover.run(ctx, { forceReindex, includeTests: include_tests }), graphAbortController.signal);
|
|
133443
|
+
if (buildGraphInputSnapshotHash(activationSnapshot) !== graphGenerationLease.inputSnapshotHash) {
|
|
133444
|
+
throw new Error("graph_generation_stale_snapshot");
|
|
133445
|
+
}
|
|
133446
|
+
if (graphHeartbeatFailure)
|
|
133447
|
+
throw graphHeartbeatFailure;
|
|
133448
|
+
if (managedRunLeaseLost)
|
|
133449
|
+
throw managedRunLeaseLost;
|
|
133450
|
+
stopGraphHeartbeat = true;
|
|
133451
|
+
heartbeatTimerController.abort();
|
|
133452
|
+
await graphHeartbeat;
|
|
133453
|
+
stopManagedRunHeartbeat = true;
|
|
133454
|
+
managedRunTimerController.abort();
|
|
133455
|
+
if (managedRunHeartbeat)
|
|
133456
|
+
await managedRunHeartbeat;
|
|
133457
|
+
const activatedGraph = await this.graphGenerations.activate(graphGenerationLease);
|
|
133458
|
+
const activeGraphSummary = await getSymbolRepository().getActiveGraphSnapshot(projectId);
|
|
133459
|
+
if (!activeGraphSummary || activeGraphSummary.generationId !== activatedGraph.generationId) {
|
|
133460
|
+
throw new Error("activated_graph_summary_mismatch");
|
|
133461
|
+
}
|
|
133462
|
+
const durationMs = Math.round(performance.now() - t0);
|
|
133463
|
+
const result = {
|
|
133464
|
+
filesDiscovered: discovered.length,
|
|
133465
|
+
filesIndexed: loadResult.filesLoaded,
|
|
133466
|
+
filesSkipped: discovered.filter((f) => !f.needsReparse).length,
|
|
133467
|
+
chunksIndexed: loadResult.chunksLoaded,
|
|
133468
|
+
symbolsIndexed: loadResult.symbolsLoaded,
|
|
133469
|
+
errors: loadResult.errors,
|
|
133470
|
+
durationMs,
|
|
133471
|
+
stageTimings,
|
|
133472
|
+
activatedGraphGenerationId: activatedGraph.generationId,
|
|
133473
|
+
parserDiagnostics: {
|
|
133474
|
+
diagnosticsCount: activeGraphSummary.diagnostics.errors,
|
|
133475
|
+
recoveredFiles: activeGraphSummary.diagnostics.recovered,
|
|
133476
|
+
hardFailureFiles: activeGraphSummary.diagnostics.hardFailures,
|
|
133477
|
+
staleFiles: activeGraphSummary.diagnostics.staleFiles,
|
|
133478
|
+
languages: activeGraphSummary.languages
|
|
133479
|
+
}
|
|
133480
|
+
};
|
|
133481
|
+
await getSearchCache().invalidateProject(projectId);
|
|
133482
|
+
try {
|
|
133483
|
+
const admissionMarker = new IndexManager(await getVectorStore());
|
|
133484
|
+
await admissionMarker.updateIndexMetadata(projectId, projectPath, discovered.map((file2) => file2.relativePath));
|
|
133485
|
+
} catch (markerError) {
|
|
133486
|
+
logger.warn("EtlPipeline: search-admission marker write failed", {
|
|
133487
|
+
projectId,
|
|
133488
|
+
jobId,
|
|
133489
|
+
error: markerError
|
|
133490
|
+
});
|
|
133491
|
+
}
|
|
133492
|
+
if (forceReindex) {
|
|
133493
|
+
const liveFingerprint = currentEmbeddingFingerprint();
|
|
133494
|
+
if (liveFingerprint !== null) {
|
|
133495
|
+
try {
|
|
133496
|
+
await stampEmbeddingFingerprint(projectId, liveFingerprint);
|
|
133497
|
+
} catch (stampError) {
|
|
133498
|
+
logger.warn("EtlPipeline: embedding fingerprint stamp failed", {
|
|
133499
|
+
projectId,
|
|
133500
|
+
jobId,
|
|
133501
|
+
error: stampError
|
|
133502
|
+
});
|
|
133503
|
+
}
|
|
133504
|
+
}
|
|
133505
|
+
}
|
|
133506
|
+
indexJobTracker.updateProgress(jobId, result.filesIndexed, result.filesIndexed);
|
|
133507
|
+
await indexJobTracker.setResultAndFlush(jobId, {
|
|
133508
|
+
filesIndexed: result.filesIndexed,
|
|
133509
|
+
chunksIndexed: result.chunksIndexed,
|
|
133510
|
+
errors: result.errors,
|
|
133511
|
+
fileErrors: loadResult.fileErrors ?? [],
|
|
133512
|
+
duration: durationMs,
|
|
133513
|
+
activatedGraphGenerationId: result.activatedGraphGenerationId,
|
|
133514
|
+
parserDiagnostics: result.parserDiagnostics
|
|
133515
|
+
});
|
|
133516
|
+
eventBus.publish("indexing:completed", {
|
|
133517
|
+
jobId,
|
|
133518
|
+
projectId,
|
|
133519
|
+
filesIndexed: result.filesIndexed,
|
|
133520
|
+
chunksIndexed: result.chunksIndexed,
|
|
133521
|
+
symbolsIndexed: result.symbolsIndexed,
|
|
133522
|
+
errors: result.errors,
|
|
133523
|
+
durationMs,
|
|
133524
|
+
activatedGraphGenerationId: result.activatedGraphGenerationId
|
|
133525
|
+
});
|
|
133526
|
+
await this.graphGenerations.cleanup(graphGenerationLease);
|
|
133527
|
+
jobHeartbeatController.abort();
|
|
133528
|
+
stopGraphHeartbeat = true;
|
|
133529
|
+
heartbeatTimerController.abort();
|
|
133530
|
+
await graphHeartbeat;
|
|
133531
|
+
stopManagedRunHeartbeat = true;
|
|
133532
|
+
managedRunTimerController.abort();
|
|
133533
|
+
if (managedRunHeartbeat)
|
|
133534
|
+
await managedRunHeartbeat;
|
|
133535
|
+
if (managedRunLease && managedRunRepository) {
|
|
133536
|
+
try {
|
|
133537
|
+
await managedRunRepository.complete(managedRunLease);
|
|
133538
|
+
} catch (completeError) {
|
|
133539
|
+
logger.error("EtlPipeline: managed_runs complete failed", completeError, { projectId, jobId });
|
|
133540
|
+
}
|
|
133541
|
+
}
|
|
133542
|
+
logger.info("EtlPipeline: run completed", { projectId, jobId, ...result });
|
|
133543
|
+
return result;
|
|
133544
|
+
} catch (err) {
|
|
133545
|
+
const durationMs = Math.round(performance.now() - t0);
|
|
133546
|
+
const error51 = err.message;
|
|
133547
|
+
if (graphGenerationLease) {
|
|
133548
|
+
try {
|
|
133549
|
+
await this.graphGenerations.abort(graphGenerationLease, error51);
|
|
133550
|
+
} catch (abortError) {
|
|
133551
|
+
logger.error("EtlPipeline: pending generation abort failed", abortError, { projectId, jobId });
|
|
133552
|
+
}
|
|
133553
|
+
}
|
|
133554
|
+
jobHeartbeatController.abort();
|
|
133555
|
+
stopGraphHeartbeat = true;
|
|
133556
|
+
heartbeatTimerController.abort();
|
|
133557
|
+
graphAbortController.abort();
|
|
133558
|
+
await graphHeartbeat;
|
|
133559
|
+
stopManagedRunHeartbeat = true;
|
|
133560
|
+
managedRunTimerController.abort();
|
|
133561
|
+
if (managedRunHeartbeat)
|
|
133562
|
+
await managedRunHeartbeat;
|
|
133563
|
+
if (managedRunLease && managedRunRepository) {
|
|
133564
|
+
try {
|
|
133565
|
+
const outcome2 = await managedRunRepository.abort(managedRunLease);
|
|
133566
|
+
if (outcome2.status === "lease_lost") {
|
|
133567
|
+
logger.warn("EtlPipeline: managed_runs abort saw lease_lost", { projectId, jobId });
|
|
133568
|
+
}
|
|
133569
|
+
} catch (abortError) {
|
|
133570
|
+
logger.error("EtlPipeline: managed_runs abort failed", abortError, { projectId, jobId });
|
|
133571
|
+
}
|
|
133572
|
+
}
|
|
133573
|
+
eventBus.publish("indexing:failed", { jobId, projectId, error: error51, durationMs });
|
|
133574
|
+
indexJobTracker.setResult(jobId, { filesIndexed: 0, chunksIndexed: 0, errors: 1, duration: durationMs }, error51);
|
|
133575
|
+
logger.error("EtlPipeline: run failed", err, { projectId, jobId, durationMs });
|
|
133576
|
+
throw err;
|
|
133577
|
+
}
|
|
133578
|
+
}
|
|
133579
|
+
};
|
|
133580
|
+
});
|
|
133581
|
+
|
|
133582
|
+
// ../../packages/core/dist/services/indexing/execute-indexing.js
|
|
133583
|
+
async function executeIndexing(request) {
|
|
133584
|
+
const { jobId, projectId, projectPath, forceReindex, warmCache, warmupQueries, include_tests = false, managedRunLease, warmupCache: warmupCache2 } = request;
|
|
133585
|
+
const startTime = Date.now();
|
|
133586
|
+
try {
|
|
133587
|
+
indexJobTracker.updateStatus(jobId, "running");
|
|
133588
|
+
logger.info("Starting project indexing via ETL Pipeline", {
|
|
133589
|
+
jobId,
|
|
133590
|
+
projectPath,
|
|
133591
|
+
projectId,
|
|
133592
|
+
forceReindex,
|
|
133593
|
+
warmCache,
|
|
133594
|
+
include_tests
|
|
133595
|
+
});
|
|
133596
|
+
const etlResult = await EtlPipeline.getInstance().run({
|
|
133597
|
+
projectId,
|
|
133598
|
+
projectPath,
|
|
133599
|
+
jobId,
|
|
133600
|
+
forceReindex,
|
|
133601
|
+
include_tests,
|
|
133602
|
+
managedRunLease
|
|
133603
|
+
});
|
|
133604
|
+
const duration3 = Date.now() - startTime;
|
|
133605
|
+
logger.info("ETL Pipeline completed", {
|
|
133606
|
+
jobId,
|
|
133607
|
+
projectId,
|
|
133608
|
+
duration: duration3,
|
|
133609
|
+
filesIndexed: etlResult.filesIndexed,
|
|
133610
|
+
filesSkipped: etlResult.filesSkipped,
|
|
133611
|
+
chunksIndexed: etlResult.chunksIndexed,
|
|
133612
|
+
symbolsIndexed: etlResult.symbolsIndexed,
|
|
133613
|
+
errors: etlResult.errors,
|
|
133614
|
+
stageTimings: etlResult.stageTimings
|
|
133615
|
+
});
|
|
133616
|
+
if (warmCache) {
|
|
133617
|
+
logger.info("Starting cache warmup", { jobId, projectId });
|
|
133618
|
+
const warmupStats = await warmupCache2(projectId, projectPath, warmupQueries);
|
|
133619
|
+
logger.info("Cache warmup completed", { jobId, projectId, ...warmupStats });
|
|
133620
|
+
}
|
|
133621
|
+
indexJobTracker.updateProgress(jobId, etlResult.filesIndexed, etlResult.filesIndexed);
|
|
133622
|
+
await indexJobTracker.setResultAndFlush(jobId, {
|
|
133623
|
+
filesIndexed: etlResult.filesIndexed,
|
|
133624
|
+
chunksIndexed: etlResult.chunksIndexed,
|
|
133625
|
+
errors: etlResult.errors,
|
|
133626
|
+
duration: duration3,
|
|
133627
|
+
activatedGraphGenerationId: etlResult.activatedGraphGenerationId,
|
|
133628
|
+
parserDiagnostics: etlResult.parserDiagnostics
|
|
133629
|
+
});
|
|
133630
|
+
} catch (error51) {
|
|
133631
|
+
const duration3 = Date.now() - startTime;
|
|
133632
|
+
logger.error("Project indexing failed", error51, {
|
|
133633
|
+
jobId,
|
|
133634
|
+
projectPath,
|
|
133635
|
+
projectId,
|
|
133636
|
+
duration: duration3
|
|
133637
|
+
});
|
|
133638
|
+
indexJobTracker.setResult(jobId, {
|
|
133639
|
+
filesIndexed: 0,
|
|
133640
|
+
chunksIndexed: 0,
|
|
133641
|
+
errors: 1,
|
|
133642
|
+
duration: duration3
|
|
133643
|
+
}, error51.message);
|
|
133644
|
+
}
|
|
133645
|
+
}
|
|
133646
|
+
var init_execute_indexing = __esm(() => {
|
|
133647
|
+
init_dist();
|
|
133648
|
+
init_index_job_tracker();
|
|
133649
|
+
init_pipeline();
|
|
133650
|
+
});
|
|
133651
|
+
|
|
133652
|
+
// ../../packages/core/dist/services/indexing/acquire-indexing-lease.js
|
|
133653
|
+
async function acquireIndexingLease(request) {
|
|
133654
|
+
const { jobId, projectId } = request;
|
|
133655
|
+
const eventId = `index:${jobId}`;
|
|
133656
|
+
const managedRunRepo = ManagedRunRepositoryPg.getInstance();
|
|
133657
|
+
try {
|
|
133658
|
+
const beginOutcome = await managedRunRepo.begin({
|
|
133659
|
+
projectId,
|
|
133660
|
+
runKind: "indexing",
|
|
133661
|
+
eventId
|
|
133662
|
+
});
|
|
133663
|
+
if (beginOutcome.status === "busy") {
|
|
133664
|
+
indexJobTracker.setResult(jobId, { filesIndexed: 0, chunksIndexed: 0, errors: 0, duration: 0 }, `indexing_busy:${beginOutcome.activeRunId}`);
|
|
133665
|
+
return {
|
|
133666
|
+
status: "busy",
|
|
133667
|
+
activeRunId: beginOutcome.activeRunId,
|
|
133668
|
+
leaseExpiresAt: beginOutcome.leaseExpiresAt
|
|
133669
|
+
};
|
|
133670
|
+
}
|
|
133671
|
+
return { status: "acquired", lease: beginOutcome.lease };
|
|
133672
|
+
} catch (beginError) {
|
|
133673
|
+
logger.error("managed_runs begin failed", beginError, {
|
|
133674
|
+
jobId,
|
|
133675
|
+
projectId
|
|
133676
|
+
});
|
|
133677
|
+
indexJobTracker.setResult(jobId, { filesIndexed: 0, chunksIndexed: 0, errors: 1, duration: 0 }, `managed_runs_begin_failed:${beginError.message}`);
|
|
133678
|
+
return { status: "failed", message: beginError.message };
|
|
133679
|
+
}
|
|
133680
|
+
}
|
|
133681
|
+
var init_acquire_indexing_lease = __esm(() => {
|
|
133682
|
+
init_dist();
|
|
133683
|
+
init_index_job_tracker();
|
|
133684
|
+
init_managed_run_repository_pg();
|
|
133685
|
+
});
|
|
133686
|
+
|
|
133687
|
+
// ../../packages/core/dist/services/project-identity/project-root-identity.js
|
|
133688
|
+
import { realpath as realpath2 } from "fs/promises";
|
|
133577
133689
|
import path31 from "path";
|
|
133690
|
+
async function canonicalizeProjectRoot(projectPath, canonicalize = realpath2) {
|
|
133691
|
+
return canonicalize(path31.resolve(projectPath));
|
|
133692
|
+
}
|
|
133693
|
+
async function assertProjectRootReuse(options) {
|
|
133694
|
+
if (!options.storedProjectPath || options.forceReindex)
|
|
133695
|
+
return;
|
|
133696
|
+
const canonicalize = options.canonicalize ?? realpath2;
|
|
133697
|
+
let storedCanonical;
|
|
133698
|
+
try {
|
|
133699
|
+
storedCanonical = await canonicalize(path31.resolve(options.storedProjectPath));
|
|
133700
|
+
} catch {
|
|
133701
|
+
storedCanonical = path31.resolve(options.storedProjectPath);
|
|
133702
|
+
}
|
|
133703
|
+
if (storedCanonical !== options.canonicalProjectPath) {
|
|
133704
|
+
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");
|
|
133705
|
+
}
|
|
133706
|
+
}
|
|
133707
|
+
var init_project_root_identity = () => {};
|
|
133708
|
+
|
|
133709
|
+
// ../../packages/core/dist/tools/index_project.js
|
|
133710
|
+
import path32 from "path";
|
|
133578
133711
|
|
|
133579
133712
|
class IndexProjectTool {
|
|
133580
133713
|
name = "index_project";
|
|
@@ -133622,7 +133755,7 @@ class IndexProjectTool {
|
|
|
133622
133755
|
try {
|
|
133623
133756
|
await assertParserReadyForIndexing();
|
|
133624
133757
|
const canonicalProjectPath = await canonicalizeProjectRoot(projectPath);
|
|
133625
|
-
const finalProjectId = projectId ||
|
|
133758
|
+
const finalProjectId = projectId || path32.basename(canonicalProjectPath) || "default";
|
|
133626
133759
|
const existing = await workspaceManager.getWorkspace(finalProjectId);
|
|
133627
133760
|
await assertProjectRootReuse({
|
|
133628
133761
|
projectId: finalProjectId,
|
|
@@ -134175,17 +134308,17 @@ function applyReplacer(root, replacer) {
|
|
|
134175
134308
|
return transformChildren(root, replacer, []);
|
|
134176
134309
|
return transformChildren(normalizeValue(replacedRoot), replacer, []);
|
|
134177
134310
|
}
|
|
134178
|
-
function transformChildren(value, replacer,
|
|
134311
|
+
function transformChildren(value, replacer, path33) {
|
|
134179
134312
|
if (isJsonObject(value))
|
|
134180
|
-
return transformObject(value, replacer,
|
|
134313
|
+
return transformObject(value, replacer, path33);
|
|
134181
134314
|
if (isJsonArray(value))
|
|
134182
|
-
return transformArray(value, replacer,
|
|
134315
|
+
return transformArray(value, replacer, path33);
|
|
134183
134316
|
return value;
|
|
134184
134317
|
}
|
|
134185
|
-
function transformObject(obj, replacer,
|
|
134318
|
+
function transformObject(obj, replacer, path33) {
|
|
134186
134319
|
const result = {};
|
|
134187
134320
|
for (const [key, value] of Object.entries(obj)) {
|
|
134188
|
-
const childPath = [...
|
|
134321
|
+
const childPath = [...path33, key];
|
|
134189
134322
|
const replacedValue = replacer(key, value, childPath);
|
|
134190
134323
|
if (replacedValue === undefined)
|
|
134191
134324
|
continue;
|
|
@@ -134193,11 +134326,11 @@ function transformObject(obj, replacer, path32) {
|
|
|
134193
134326
|
}
|
|
134194
134327
|
return result;
|
|
134195
134328
|
}
|
|
134196
|
-
function transformArray(arr, replacer,
|
|
134329
|
+
function transformArray(arr, replacer, path33) {
|
|
134197
134330
|
const result = [];
|
|
134198
134331
|
for (let i = 0;i < arr.length; i++) {
|
|
134199
134332
|
const value = arr[i];
|
|
134200
|
-
const childPath = [...
|
|
134333
|
+
const childPath = [...path33, i];
|
|
134201
134334
|
const replacedValue = replacer(String(i), value, childPath);
|
|
134202
134335
|
if (replacedValue === undefined)
|
|
134203
134336
|
continue;
|
|
@@ -135635,7 +135768,7 @@ __export(exports_memory_consolidation_job, {
|
|
|
135635
135768
|
memoryConsolidationJob: () => memoryConsolidationJob,
|
|
135636
135769
|
MemoryConsolidationJob: () => MemoryConsolidationJob
|
|
135637
135770
|
});
|
|
135638
|
-
import { randomUUID as
|
|
135771
|
+
import { randomUUID as randomUUID7 } from "crypto";
|
|
135639
135772
|
async function addSupercedesEdge(store3, newId, sourceId, batchId) {
|
|
135640
135773
|
const evidence = JSON.stringify({ batchId, consolidated: true });
|
|
135641
135774
|
await store3.createEdge({
|
|
@@ -135779,11 +135912,11 @@ class MemoryConsolidationJob {
|
|
|
135779
135912
|
});
|
|
135780
135913
|
return { merged: 0, batchesCreated: 0 };
|
|
135781
135914
|
}
|
|
135782
|
-
const batch = await consolidateWindow(rowsToCandidates(candidates2), this.llm, { idFactory: () => `batch-${now2}-${
|
|
135915
|
+
const batch = await consolidateWindow(rowsToCandidates(candidates2), this.llm, { idFactory: () => `batch-${now2}-${randomUUID7().slice(0, 8)}` }).catch(() => null);
|
|
135783
135916
|
if (!batch)
|
|
135784
135917
|
return { merged: 0, batchesCreated: 0 };
|
|
135785
135918
|
const sourceRows = candidates2.filter((c) => batch.sourceIds.includes(c.id));
|
|
135786
|
-
const newId = `mem-${now2}-${
|
|
135919
|
+
const newId = `mem-${now2}-${randomUUID7().slice(0, 8)}`;
|
|
135787
135920
|
const importance = sourceRows.length ? Math.min(1, Math.max(...sourceRows.map((r) => r.importance))) : 0.7;
|
|
135788
135921
|
const projectId = sourceRows.find((r) => r.project_id)?.project_id ?? null;
|
|
135789
135922
|
try {
|
|
@@ -139290,7 +139423,7 @@ var init_session_pin_store = __esm(() => {
|
|
|
139290
139423
|
// ../../packages/core/dist/services/hooks/attribution-resolver.js
|
|
139291
139424
|
import fs20 from "fs";
|
|
139292
139425
|
import os9 from "os";
|
|
139293
|
-
import
|
|
139426
|
+
import path33 from "path";
|
|
139294
139427
|
|
|
139295
139428
|
class PgWorkspaceRootProvider {
|
|
139296
139429
|
cache = null;
|
|
@@ -139340,7 +139473,7 @@ class AttributionResolver {
|
|
|
139340
139473
|
this.pins = options.pins ?? new SessionPinStore;
|
|
139341
139474
|
this.canonicalize = options.canonicalize ?? defaultCanonicalize;
|
|
139342
139475
|
this.homedir = options.homedir ?? os9.homedir;
|
|
139343
|
-
this.fsRoot = options.fsRoot ?? (() =>
|
|
139476
|
+
this.fsRoot = options.fsRoot ?? (() => path33.parse(path33.sep).root);
|
|
139344
139477
|
}
|
|
139345
139478
|
async resolve(input) {
|
|
139346
139479
|
const caller = input.callerProjectId;
|
|
@@ -139391,7 +139524,7 @@ class AttributionResolver {
|
|
|
139391
139524
|
}
|
|
139392
139525
|
let bestPath = null;
|
|
139393
139526
|
for (const candidate2 of byPath.keys()) {
|
|
139394
|
-
if (canonicalCwd === candidate2 || canonicalCwd.startsWith(candidate2.endsWith(
|
|
139527
|
+
if (canonicalCwd === candidate2 || canonicalCwd.startsWith(candidate2.endsWith(path33.sep) ? candidate2 : candidate2 + path33.sep)) {
|
|
139395
139528
|
if (bestPath === null || candidate2.length > bestPath.length) {
|
|
139396
139529
|
bestPath = candidate2;
|
|
139397
139530
|
}
|
|
@@ -139414,7 +139547,7 @@ class AttributionResolver {
|
|
|
139414
139547
|
return projectPath2;
|
|
139415
139548
|
const fsRoot = this.fsRoot();
|
|
139416
139549
|
let normalized = projectPath2;
|
|
139417
|
-
while (normalized.length > fsRoot.length && normalized.endsWith(
|
|
139550
|
+
while (normalized.length > fsRoot.length && normalized.endsWith(path33.sep)) {
|
|
139418
139551
|
normalized = normalized.slice(0, -1);
|
|
139419
139552
|
}
|
|
139420
139553
|
return normalized;
|
|
@@ -139425,7 +139558,7 @@ function defaultCanonicalize(cwd) {
|
|
|
139425
139558
|
return fs20.realpathSync(cwd);
|
|
139426
139559
|
} catch {
|
|
139427
139560
|
try {
|
|
139428
|
-
return
|
|
139561
|
+
return path33.resolve(cwd);
|
|
139429
139562
|
} catch {
|
|
139430
139563
|
return;
|
|
139431
139564
|
}
|
|
@@ -140174,31 +140307,31 @@ class TracePathService {
|
|
|
140174
140307
|
const chains = [];
|
|
140175
140308
|
const seen = new Set;
|
|
140176
140309
|
let walks = 0;
|
|
140177
|
-
const walk = (fqn,
|
|
140310
|
+
const walk = (fqn, path34) => {
|
|
140178
140311
|
if (chains.length >= CHAIN_CAP)
|
|
140179
140312
|
return;
|
|
140180
140313
|
if (walks >= MAX_WALKS)
|
|
140181
140314
|
return;
|
|
140182
140315
|
walks++;
|
|
140183
|
-
const key =
|
|
140316
|
+
const key = path34.join("\u2192");
|
|
140184
140317
|
if (seen.has(key))
|
|
140185
140318
|
return;
|
|
140186
140319
|
seen.add(key);
|
|
140187
140320
|
const next = adj.get(fqn);
|
|
140188
140321
|
if (!next || next.length === 0 || !whoHasChild.has(fqn)) {
|
|
140189
|
-
if (
|
|
140190
|
-
chains.push(
|
|
140322
|
+
if (path34.length > 1)
|
|
140323
|
+
chains.push(path34.map((n) => this.fqnToName(n)).join(" \u2192 "));
|
|
140191
140324
|
return;
|
|
140192
140325
|
}
|
|
140193
140326
|
for (const child of next) {
|
|
140194
140327
|
if (chains.length >= CHAIN_CAP || walks >= MAX_WALKS)
|
|
140195
140328
|
return;
|
|
140196
|
-
if (
|
|
140197
|
-
const cycled = [...
|
|
140329
|
+
if (path34.includes(child)) {
|
|
140330
|
+
const cycled = [...path34, `${this.fqnToName(child)}\u21BA`];
|
|
140198
140331
|
chains.push(cycled.map((n) => n).join(" \u2192 "));
|
|
140199
140332
|
continue;
|
|
140200
140333
|
}
|
|
140201
|
-
walk(child, [...
|
|
140334
|
+
walk(child, [...path34, child]);
|
|
140202
140335
|
}
|
|
140203
140336
|
};
|
|
140204
140337
|
for (const seed of seeds) {
|
|
@@ -141081,7 +141214,7 @@ var init_file_content_cache = __esm(() => {
|
|
|
141081
141214
|
});
|
|
141082
141215
|
|
|
141083
141216
|
// ../../packages/core/dist/services/file-read/file-metadata.js
|
|
141084
|
-
import
|
|
141217
|
+
import path34 from "path";
|
|
141085
141218
|
|
|
141086
141219
|
class FileMetadataExtractor {
|
|
141087
141220
|
symbolGraph;
|
|
@@ -141117,7 +141250,7 @@ class FileMetadataExtractor {
|
|
|
141117
141250
|
return metadata;
|
|
141118
141251
|
}
|
|
141119
141252
|
detectLanguage(filePath) {
|
|
141120
|
-
const ext2 =
|
|
141253
|
+
const ext2 = path34.extname(filePath).toLowerCase();
|
|
141121
141254
|
const languageMap2 = {
|
|
141122
141255
|
".ts": "TypeScript",
|
|
141123
141256
|
".tsx": "TypeScript",
|
|
@@ -141239,7 +141372,7 @@ var init_line_range = __esm(() => {
|
|
|
141239
141372
|
});
|
|
141240
141373
|
|
|
141241
141374
|
// ../../packages/core/dist/services/file-read/path-containment.js
|
|
141242
|
-
import
|
|
141375
|
+
import path35 from "path";
|
|
141243
141376
|
|
|
141244
141377
|
class PathContainment {
|
|
141245
141378
|
projectRoots;
|
|
@@ -141247,14 +141380,14 @@ class PathContainment {
|
|
|
141247
141380
|
this.projectRoots = projectRoots;
|
|
141248
141381
|
}
|
|
141249
141382
|
async resolveFilePath(filePath, projectId) {
|
|
141250
|
-
if (
|
|
141251
|
-
return
|
|
141383
|
+
if (path35.isAbsolute(filePath)) {
|
|
141384
|
+
return path35.resolve(filePath);
|
|
141252
141385
|
}
|
|
141253
141386
|
if (projectId) {
|
|
141254
141387
|
const root = await this.projectRoots.getProjectRoot(projectId);
|
|
141255
141388
|
if (root) {
|
|
141256
141389
|
const cleaned = sanitizeFilePath(filePath);
|
|
141257
|
-
return
|
|
141390
|
+
return path35.resolve(root, cleaned);
|
|
141258
141391
|
}
|
|
141259
141392
|
return null;
|
|
141260
141393
|
}
|
|
@@ -141265,17 +141398,17 @@ class PathContainment {
|
|
|
141265
141398
|
if (projectId) {
|
|
141266
141399
|
const root = await this.projectRoots.getProjectRoot(projectId);
|
|
141267
141400
|
if (root)
|
|
141268
|
-
roots.push(
|
|
141401
|
+
roots.push(path35.resolve(root));
|
|
141269
141402
|
}
|
|
141270
|
-
roots.push(
|
|
141403
|
+
roots.push(path35.resolve(process.cwd()));
|
|
141271
141404
|
const envRoots = (process.env.MASSA_AI_READ_FILE_ROOTS ?? "").split(":").map((s) => s.trim()).filter((s) => s.length > 0);
|
|
141272
141405
|
for (const extra of envRoots) {
|
|
141273
|
-
roots.push(
|
|
141406
|
+
roots.push(path35.resolve(extra));
|
|
141274
141407
|
}
|
|
141275
|
-
const target =
|
|
141408
|
+
const target = path35.resolve(absoluteFilePath);
|
|
141276
141409
|
for (const root of roots) {
|
|
141277
|
-
const rel =
|
|
141278
|
-
if (rel !== "" && !rel.startsWith("..") && !
|
|
141410
|
+
const rel = path35.relative(root, target);
|
|
141411
|
+
if (rel !== "" && !rel.startsWith("..") && !path35.isAbsolute(rel)) {
|
|
141279
141412
|
return { allowed: true };
|
|
141280
141413
|
}
|
|
141281
141414
|
if (rel === "")
|
|
@@ -144220,12 +144353,13 @@ function createProjectIdentityService(options = {}) {
|
|
|
144220
144353
|
}
|
|
144221
144354
|
},
|
|
144222
144355
|
apply(input) {
|
|
144223
|
-
return applyService.apply(input);
|
|
144356
|
+
return withHeavyWorkLease("maintenance", "project-identity", () => applyService.apply(input));
|
|
144224
144357
|
}
|
|
144225
144358
|
};
|
|
144226
144359
|
}
|
|
144227
144360
|
var init_service = __esm(() => {
|
|
144228
144361
|
init_db_connection();
|
|
144362
|
+
init_heavy_work_lease();
|
|
144229
144363
|
init_apply();
|
|
144230
144364
|
init_errors4();
|
|
144231
144365
|
init_planner();
|
|
@@ -144523,7 +144657,7 @@ var init_inference_probe = __esm(() => {
|
|
|
144523
144657
|
// ../../packages/core/dist/services/health/local-health-checker.js
|
|
144524
144658
|
import fs22 from "fs/promises";
|
|
144525
144659
|
import { existsSync as existsSync3 } from "fs";
|
|
144526
|
-
import
|
|
144660
|
+
import path36 from "path";
|
|
144527
144661
|
|
|
144528
144662
|
class LocalHealthChecker {
|
|
144529
144663
|
dataDir = config2.get("dataDir");
|
|
@@ -144602,7 +144736,7 @@ class LocalHealthChecker {
|
|
|
144602
144736
|
try {
|
|
144603
144737
|
if (!existsSync3(this.dataDir))
|
|
144604
144738
|
await fs22.mkdir(this.dataDir, { recursive: true });
|
|
144605
|
-
const probe2 =
|
|
144739
|
+
const probe2 = path36.join(this.dataDir, ".health-check-test");
|
|
144606
144740
|
await fs22.writeFile(probe2, "ok");
|
|
144607
144741
|
await fs22.unlink(probe2);
|
|
144608
144742
|
return { available: true, latency: Date.now() - start, details: { path: this.dataDir, writable: true } };
|
|
@@ -144948,6 +145082,9 @@ class PgScheduledJobStore {
|
|
|
144948
145082
|
}, "save");
|
|
144949
145083
|
this.ensureHydrated();
|
|
144950
145084
|
}
|
|
145085
|
+
async ready() {
|
|
145086
|
+
await this.ensureHydrated();
|
|
145087
|
+
}
|
|
144951
145088
|
get(id) {
|
|
144952
145089
|
this.ensureHydrated();
|
|
144953
145090
|
return this.mirror.get(id) ?? null;
|
|
@@ -145024,10 +145161,18 @@ class Scheduler {
|
|
|
145024
145161
|
handlers = new Map;
|
|
145025
145162
|
cronCache = new Map;
|
|
145026
145163
|
running = new Set;
|
|
145164
|
+
heavyWorkProbe;
|
|
145165
|
+
deferred = new Set;
|
|
145166
|
+
heavyWorkReason = null;
|
|
145167
|
+
lastProbeError = null;
|
|
145168
|
+
consecutiveProbeFailures = 0;
|
|
145169
|
+
evaluating = false;
|
|
145170
|
+
pendingTickAt = null;
|
|
145027
145171
|
timer = null;
|
|
145028
145172
|
started = false;
|
|
145029
145173
|
constructor(opts = {}) {
|
|
145030
145174
|
this.store = opts.store ?? getScheduledJobStore();
|
|
145175
|
+
this.heavyWorkProbe = opts.heavyWorkProbe ?? probeHeavyWork;
|
|
145031
145176
|
const schedulerConfig = config2.get("scheduler");
|
|
145032
145177
|
this.tickIntervalMs = opts.tickIntervalMs ?? envPositiveInt(process.env.MASSA_AI_SCHEDULER_TICK_MS) ?? schedulerConfig?.tickMs ?? DEFAULTS.tickMs;
|
|
145033
145178
|
this.maxConcurrent = opts.maxConcurrent ?? envPositiveInt(process.env.MASSA_AI_SCHEDULER_MAX_CONCURRENT) ?? schedulerConfig?.maxConcurrent ?? DEFAULTS.maxConcurrent;
|
|
@@ -145128,31 +145273,43 @@ class Scheduler {
|
|
|
145128
145273
|
this.timer.unref?.();
|
|
145129
145274
|
this.tick().catch(() => {});
|
|
145130
145275
|
}
|
|
145131
|
-
catchUpMissedJobs(now2 = Date.now()) {
|
|
145132
|
-
if (!this.enabled)
|
|
145133
|
-
return { caughtUp: 0, skipped: 0 };
|
|
145276
|
+
async catchUpMissedJobs(now2 = Date.now()) {
|
|
145277
|
+
if (!this.enabled || this.evaluating)
|
|
145278
|
+
return { caughtUp: 0, skipped: 0, deferred: 0 };
|
|
145279
|
+
this.evaluating = true;
|
|
145280
|
+
try {
|
|
145281
|
+
return await this.catchUpOnce(now2);
|
|
145282
|
+
} finally {
|
|
145283
|
+
this.evaluating = false;
|
|
145284
|
+
}
|
|
145285
|
+
}
|
|
145286
|
+
async catchUpOnce(now2) {
|
|
145134
145287
|
const jobs = this.store.listEnabled();
|
|
145135
|
-
let caughtUp = 0;
|
|
145136
145288
|
let skipped = 0;
|
|
145289
|
+
const missed = [];
|
|
145137
145290
|
for (const job of jobs) {
|
|
145138
145291
|
if (this.running.has(job.jobKind)) {
|
|
145139
145292
|
skipped++;
|
|
145140
145293
|
continue;
|
|
145141
145294
|
}
|
|
145142
|
-
|
|
145143
|
-
|
|
145144
|
-
|
|
145145
|
-
|
|
145295
|
+
if (now2 - job.nextRunAt > this.tickIntervalMs)
|
|
145296
|
+
missed.push(job);
|
|
145297
|
+
}
|
|
145298
|
+
if (missed.length > 0 && await this.heavyWorkBusy()) {
|
|
145299
|
+
for (const job of missed)
|
|
145300
|
+
this.deferred.add(job.id);
|
|
145301
|
+
return { caughtUp: 0, skipped, deferred: missed.length };
|
|
145302
|
+
}
|
|
145303
|
+
for (const job of missed) {
|
|
145146
145304
|
logger.info("Scheduler: catch-up tick for missed job", {
|
|
145147
145305
|
id: job.id,
|
|
145148
145306
|
name: job.name,
|
|
145149
145307
|
jobKind: job.jobKind,
|
|
145150
|
-
overdueMs
|
|
145308
|
+
overdueMs: now2 - job.nextRunAt
|
|
145151
145309
|
});
|
|
145152
145310
|
this.fireJob(job, now2);
|
|
145153
|
-
caughtUp++;
|
|
145154
145311
|
}
|
|
145155
|
-
return { caughtUp, skipped };
|
|
145312
|
+
return { caughtUp: missed.length, skipped, deferred: 0 };
|
|
145156
145313
|
}
|
|
145157
145314
|
stop() {
|
|
145158
145315
|
if (this.timer) {
|
|
@@ -145160,17 +145317,47 @@ class Scheduler {
|
|
|
145160
145317
|
this.timer = null;
|
|
145161
145318
|
}
|
|
145162
145319
|
this.started = false;
|
|
145320
|
+
this.pendingTickAt = null;
|
|
145163
145321
|
logger.info("Scheduler stopped");
|
|
145164
145322
|
}
|
|
145165
145323
|
isRunning() {
|
|
145166
145324
|
return this.started && this.timer !== null;
|
|
145167
145325
|
}
|
|
145168
145326
|
async tick(now2 = Date.now()) {
|
|
145169
|
-
const result = { evaluated: 0, fired: 0, skipped: 0, errors: 0 };
|
|
145327
|
+
const result = { evaluated: 0, fired: 0, skipped: 0, errors: 0, deferred: 0 };
|
|
145170
145328
|
if (!this.enabled)
|
|
145171
145329
|
return result;
|
|
145172
|
-
|
|
145330
|
+
if (this.evaluating) {
|
|
145331
|
+
this.pendingTickAt = now2;
|
|
145332
|
+
return result;
|
|
145333
|
+
}
|
|
145334
|
+
this.evaluating = true;
|
|
145335
|
+
try {
|
|
145336
|
+
return await this.tickOnce(now2, result);
|
|
145337
|
+
} finally {
|
|
145338
|
+
this.evaluating = false;
|
|
145339
|
+
const pending = this.pendingTickAt;
|
|
145340
|
+
this.pendingTickAt = null;
|
|
145341
|
+
if (pending !== null) {
|
|
145342
|
+
this.tick(pending).catch((e) => {
|
|
145343
|
+
logger.warn("Scheduler tick failed (swallowed)", { error: e });
|
|
145344
|
+
});
|
|
145345
|
+
}
|
|
145346
|
+
}
|
|
145347
|
+
}
|
|
145348
|
+
async tickOnce(now2, result) {
|
|
145349
|
+
let jobs = this.store.listEnabled();
|
|
145173
145350
|
result.evaluated = jobs.length;
|
|
145351
|
+
const due = jobs.filter((job) => !this.running.has(job.jobKind) && job.nextRunAt <= now2);
|
|
145352
|
+
if (due.length > 0) {
|
|
145353
|
+
if (await this.heavyWorkBusy()) {
|
|
145354
|
+
for (const job of due)
|
|
145355
|
+
this.deferred.add(job.id);
|
|
145356
|
+
result.deferred = due.length;
|
|
145357
|
+
return result;
|
|
145358
|
+
}
|
|
145359
|
+
jobs = this.store.listEnabled();
|
|
145360
|
+
}
|
|
145174
145361
|
for (const job of jobs) {
|
|
145175
145362
|
if (this.running.has(job.jobKind)) {
|
|
145176
145363
|
result.skipped++;
|
|
@@ -145180,7 +145367,7 @@ class Scheduler {
|
|
|
145180
145367
|
continue;
|
|
145181
145368
|
}
|
|
145182
145369
|
const overdueMs = now2 - job.nextRunAt;
|
|
145183
|
-
const isMissed = overdueMs > this.tickIntervalMs;
|
|
145370
|
+
const isMissed = overdueMs > this.tickIntervalMs && !this.deferred.has(job.id);
|
|
145184
145371
|
if (isMissed) {
|
|
145185
145372
|
logger.warn("Scheduler: missed run (skipping, rescheduling)", {
|
|
145186
145373
|
id: job.id,
|
|
@@ -145202,7 +145389,42 @@ class Scheduler {
|
|
|
145202
145389
|
}
|
|
145203
145390
|
return result;
|
|
145204
145391
|
}
|
|
145392
|
+
async heavyWorkBusy() {
|
|
145393
|
+
let state;
|
|
145394
|
+
try {
|
|
145395
|
+
state = await this.heavyWorkProbe();
|
|
145396
|
+
} catch (e) {
|
|
145397
|
+
this.consecutiveProbeFailures++;
|
|
145398
|
+
this.lastProbeError = e.message;
|
|
145399
|
+
if (this.consecutiveProbeFailures === 1 || this.consecutiveProbeFailures % PROBE_FAILURE_WARN_EVERY === 0) {
|
|
145400
|
+
logger.warn("Scheduler: heavy-work probe failed; deferring due jobs", {
|
|
145401
|
+
consecutiveFailures: this.consecutiveProbeFailures,
|
|
145402
|
+
error: e
|
|
145403
|
+
});
|
|
145404
|
+
}
|
|
145405
|
+
return true;
|
|
145406
|
+
}
|
|
145407
|
+
this.consecutiveProbeFailures = 0;
|
|
145408
|
+
this.lastProbeError = null;
|
|
145409
|
+
if (state.busy) {
|
|
145410
|
+
if (this.heavyWorkReason === null) {
|
|
145411
|
+
logger.info("Scheduler: heavy database work in progress; deferring due jobs", {
|
|
145412
|
+
reason: state.reason ?? "unknown"
|
|
145413
|
+
});
|
|
145414
|
+
}
|
|
145415
|
+
this.heavyWorkReason = state.reason ?? "unknown";
|
|
145416
|
+
return true;
|
|
145417
|
+
}
|
|
145418
|
+
if (this.heavyWorkReason !== null) {
|
|
145419
|
+
logger.info("Scheduler: heavy database work finished; running deferred jobs", {
|
|
145420
|
+
deferred: this.deferred.size
|
|
145421
|
+
});
|
|
145422
|
+
this.heavyWorkReason = null;
|
|
145423
|
+
}
|
|
145424
|
+
return false;
|
|
145425
|
+
}
|
|
145205
145426
|
fireJob(job, firedAt) {
|
|
145427
|
+
this.deferred.delete(job.id);
|
|
145206
145428
|
const handler = this.handlers.get(job.jobKind);
|
|
145207
145429
|
if (!handler) {
|
|
145208
145430
|
logger.warn("Scheduler: no handler registered for jobKind", {
|
|
@@ -145262,6 +145484,9 @@ class Scheduler {
|
|
|
145262
145484
|
}
|
|
145263
145485
|
})();
|
|
145264
145486
|
}
|
|
145487
|
+
async ready() {
|
|
145488
|
+
await this.store.ready?.();
|
|
145489
|
+
}
|
|
145265
145490
|
status(now2 = Date.now()) {
|
|
145266
145491
|
const jobs = this.store.listAll();
|
|
145267
145492
|
return {
|
|
@@ -145276,10 +145501,17 @@ class Scheduler {
|
|
|
145276
145501
|
nextRunAt: j.nextRunAt,
|
|
145277
145502
|
lastRunAt: j.lastRunAt,
|
|
145278
145503
|
lastSuccessAt: j.lastSuccessAt ?? null,
|
|
145504
|
+
lastFailureAt: j.lastFailureAt ?? null,
|
|
145279
145505
|
consecutiveFailures: j.consecutiveFailures ?? 0,
|
|
145506
|
+
lastError: j.lastError ?? null,
|
|
145280
145507
|
due: j.enabled && j.nextRunAt <= now2,
|
|
145281
|
-
currentlyRunning: this.running.has(j.jobKind)
|
|
145282
|
-
|
|
145508
|
+
currentlyRunning: this.running.has(j.jobKind),
|
|
145509
|
+
deferred: this.deferred.has(j.id)
|
|
145510
|
+
})),
|
|
145511
|
+
heavyWork: {
|
|
145512
|
+
lastProbeError: this.lastProbeError,
|
|
145513
|
+
consecutiveProbeFailures: this.consecutiveProbeFailures
|
|
145514
|
+
}
|
|
145283
145515
|
};
|
|
145284
145516
|
}
|
|
145285
145517
|
isJobRunning(jobKind) {
|
|
@@ -145298,12 +145530,13 @@ function resetScheduler() {
|
|
|
145298
145530
|
}
|
|
145299
145531
|
resetScheduledJobStore();
|
|
145300
145532
|
}
|
|
145301
|
-
var DEFAULTS, cachedScheduler = null;
|
|
145533
|
+
var DEFAULTS, PROBE_FAILURE_WARN_EVERY = 5, cachedScheduler = null;
|
|
145302
145534
|
var init_scheduler = __esm(() => {
|
|
145303
145535
|
init_dist();
|
|
145304
145536
|
init_config();
|
|
145305
145537
|
init_scheduler_cron();
|
|
145306
145538
|
init_scheduler_store_factory();
|
|
145539
|
+
init_heavy_work_lease();
|
|
145307
145540
|
DEFAULTS = {
|
|
145308
145541
|
tickMs: 60000,
|
|
145309
145542
|
maxConcurrent: 2
|
|
@@ -145992,7 +146225,7 @@ var init_auto_improve_llm = __esm(() => {
|
|
|
145992
146225
|
});
|
|
145993
146226
|
|
|
145994
146227
|
// ../../packages/core/dist/services/jobs/auto-improve-apply.js
|
|
145995
|
-
import { randomUUID as
|
|
146228
|
+
import { randomUUID as randomUUID8 } from "crypto";
|
|
145996
146229
|
function validateCreatePayload(p) {
|
|
145997
146230
|
if ("type" in p && p.type !== undefined && p.type !== null) {
|
|
145998
146231
|
if (typeof p.type !== "string" || !VALID_MEMORY_TYPES.has(p.type)) {
|
|
@@ -146033,7 +146266,7 @@ function buildUpdatePatch(p) {
|
|
|
146033
146266
|
return patch;
|
|
146034
146267
|
}
|
|
146035
146268
|
async function applyProposal(job, record3) {
|
|
146036
|
-
const memId = record3.targetMemoryId ?? `proposal-mem-${record3.id}-${
|
|
146269
|
+
const memId = record3.targetMemoryId ?? `proposal-mem-${record3.id}-${randomUUID8().slice(0, 8)}`;
|
|
146037
146270
|
const p = record3.payload;
|
|
146038
146271
|
if (record3.kind === "memory.create") {
|
|
146039
146272
|
validateCreatePayload(p);
|
|
@@ -146300,8 +146533,8 @@ __export(exports_auto_improve_job, {
|
|
|
146300
146533
|
|
|
146301
146534
|
class AutoImproveJob {
|
|
146302
146535
|
llm;
|
|
146303
|
-
|
|
146304
|
-
|
|
146536
|
+
injectedObservationStore;
|
|
146537
|
+
injectedProposalStore;
|
|
146305
146538
|
memoryRepo;
|
|
146306
146539
|
thresholds;
|
|
146307
146540
|
minObservations;
|
|
@@ -146312,10 +146545,16 @@ class AutoImproveJob {
|
|
|
146312
146545
|
lastRunAt = 0;
|
|
146313
146546
|
newSinceRun = 0;
|
|
146314
146547
|
runCalls = 0;
|
|
146548
|
+
get observationStore() {
|
|
146549
|
+
return this.injectedObservationStore ?? getObservationStore();
|
|
146550
|
+
}
|
|
146551
|
+
get proposalStore() {
|
|
146552
|
+
return this.injectedProposalStore ?? getProposalStore();
|
|
146553
|
+
}
|
|
146315
146554
|
constructor(opts = {}) {
|
|
146316
146555
|
this.llm = opts.llm ?? llm;
|
|
146317
|
-
this.
|
|
146318
|
-
this.
|
|
146556
|
+
this.injectedObservationStore = opts.observationStore;
|
|
146557
|
+
this.injectedProposalStore = opts.proposalStore;
|
|
146319
146558
|
this.thresholds = { ...DEFAULT_THRESHOLDS, ...opts.thresholds };
|
|
146320
146559
|
this.reviewGateOverride = opts.reviewGate;
|
|
146321
146560
|
this.idFactory = opts.idFactory ?? (() => newProposalId());
|
|
@@ -146395,7 +146634,7 @@ __export(exports_observation_consolidation_job, {
|
|
|
146395
146634
|
observationConsolidationJob: () => observationConsolidationJob,
|
|
146396
146635
|
ObservationConsolidationJob: () => ObservationConsolidationJob
|
|
146397
146636
|
});
|
|
146398
|
-
import { randomUUID as
|
|
146637
|
+
import { randomUUID as randomUUID9 } from "crypto";
|
|
146399
146638
|
function readBridgeConfig() {
|
|
146400
146639
|
try {
|
|
146401
146640
|
const c = config2.get("hooks")?.bridge;
|
|
@@ -146413,7 +146652,7 @@ function readBridgeConfig() {
|
|
|
146413
146652
|
|
|
146414
146653
|
class ObservationConsolidationJob {
|
|
146415
146654
|
llm;
|
|
146416
|
-
|
|
146655
|
+
injectedStore;
|
|
146417
146656
|
memoryRepo;
|
|
146418
146657
|
minObservations;
|
|
146419
146658
|
minIntervalMs;
|
|
@@ -146421,9 +146660,12 @@ class ObservationConsolidationJob {
|
|
|
146421
146660
|
lastRunAt = 0;
|
|
146422
146661
|
newSinceRun = 0;
|
|
146423
146662
|
runCalls = 0;
|
|
146663
|
+
get store() {
|
|
146664
|
+
return this.injectedStore ?? getObservationStore();
|
|
146665
|
+
}
|
|
146424
146666
|
constructor(opts = {}) {
|
|
146425
146667
|
this.llm = opts.llm ?? llm;
|
|
146426
|
-
this.
|
|
146668
|
+
this.injectedStore = opts.store;
|
|
146427
146669
|
const injected = opts.memoryRepo;
|
|
146428
146670
|
this.memoryRepo = injected ?? { insert: (i) => getMemoryRepository().insert(i) };
|
|
146429
146671
|
const cfg = readBridgeConfig();
|
|
@@ -146485,7 +146727,7 @@ class ObservationConsolidationJob {
|
|
|
146485
146727
|
if (observations.length < 2)
|
|
146486
146728
|
return noop2;
|
|
146487
146729
|
const window2 = observations.slice(0, this.maxWindow);
|
|
146488
|
-
const batchId = `obs-batch-${Date.now()}-${
|
|
146730
|
+
const batchId = `obs-batch-${Date.now()}-${randomUUID9().slice(0, 8)}`;
|
|
146489
146731
|
const prompt = buildObservationPrompt(window2);
|
|
146490
146732
|
let batch;
|
|
146491
146733
|
try {
|
|
@@ -146511,7 +146753,7 @@ class ObservationConsolidationJob {
|
|
|
146511
146753
|
}
|
|
146512
146754
|
if (!batch)
|
|
146513
146755
|
return noop2;
|
|
146514
|
-
const newId = `mem-${Date.now()}-${
|
|
146756
|
+
const newId = `mem-${Date.now()}-${randomUUID9().slice(0, 8)}`;
|
|
146515
146757
|
const importance = 0.7;
|
|
146516
146758
|
try {
|
|
146517
146759
|
await Promise.resolve(this.memoryRepo.insert({
|
|
@@ -146743,7 +146985,7 @@ var init_scheduler2 = __esm(() => {
|
|
|
146743
146985
|
// ../../packages/core/dist/services/pricing/models-dev-client.js
|
|
146744
146986
|
import fs23 from "fs/promises";
|
|
146745
146987
|
import { existsSync as existsSync4 } from "fs";
|
|
146746
|
-
import
|
|
146988
|
+
import path37 from "path";
|
|
146747
146989
|
function getModelsDevClient() {
|
|
146748
146990
|
if (!clientInstance) {
|
|
146749
146991
|
clientInstance = new ModelsDevClient;
|
|
@@ -146763,7 +147005,7 @@ var init_models_dev_client = __esm(() => {
|
|
|
146763
147005
|
memoryCacheTimestamp = 0;
|
|
146764
147006
|
getLocalCachePath() {
|
|
146765
147007
|
const dataDir = config2.get("dataDir");
|
|
146766
|
-
return
|
|
147008
|
+
return path37.join(dataDir, ModelsDevClient.LOCAL_CACHE_FILE);
|
|
146767
147009
|
}
|
|
146768
147010
|
async loadLocalCache() {
|
|
146769
147011
|
const cachePath = this.getLocalCachePath();
|
|
@@ -146798,7 +147040,7 @@ var init_models_dev_client = __esm(() => {
|
|
|
146798
147040
|
async saveLocalCache(models) {
|
|
146799
147041
|
const cachePath = this.getLocalCachePath();
|
|
146800
147042
|
try {
|
|
146801
|
-
const dir =
|
|
147043
|
+
const dir = path37.dirname(cachePath);
|
|
146802
147044
|
await fs23.mkdir(dir, { recursive: true });
|
|
146803
147045
|
const data = {
|
|
146804
147046
|
timestamp: Date.now(),
|
|
@@ -152694,33 +152936,33 @@ var require_URL = __commonJS((exports, module) => {
|
|
|
152694
152936
|
else
|
|
152695
152937
|
return basepath.substring(0, lastslash + 1) + refpath;
|
|
152696
152938
|
}
|
|
152697
|
-
function remove_dot_segments(
|
|
152698
|
-
if (!
|
|
152699
|
-
return
|
|
152939
|
+
function remove_dot_segments(path38) {
|
|
152940
|
+
if (!path38)
|
|
152941
|
+
return path38;
|
|
152700
152942
|
var output = "";
|
|
152701
|
-
while (
|
|
152702
|
-
if (
|
|
152703
|
-
|
|
152943
|
+
while (path38.length > 0) {
|
|
152944
|
+
if (path38 === "." || path38 === "..") {
|
|
152945
|
+
path38 = "";
|
|
152704
152946
|
break;
|
|
152705
152947
|
}
|
|
152706
|
-
var twochars =
|
|
152707
|
-
var threechars =
|
|
152708
|
-
var fourchars =
|
|
152948
|
+
var twochars = path38.substring(0, 2);
|
|
152949
|
+
var threechars = path38.substring(0, 3);
|
|
152950
|
+
var fourchars = path38.substring(0, 4);
|
|
152709
152951
|
if (threechars === "../") {
|
|
152710
|
-
|
|
152952
|
+
path38 = path38.substring(3);
|
|
152711
152953
|
} else if (twochars === "./") {
|
|
152712
|
-
|
|
152954
|
+
path38 = path38.substring(2);
|
|
152713
152955
|
} else if (threechars === "/./") {
|
|
152714
|
-
|
|
152715
|
-
} else if (twochars === "/." &&
|
|
152716
|
-
|
|
152717
|
-
} else if (fourchars === "/../" || threechars === "/.." &&
|
|
152718
|
-
|
|
152956
|
+
path38 = "/" + path38.substring(3);
|
|
152957
|
+
} else if (twochars === "/." && path38.length === 2) {
|
|
152958
|
+
path38 = "/";
|
|
152959
|
+
} else if (fourchars === "/../" || threechars === "/.." && path38.length === 3) {
|
|
152960
|
+
path38 = "/" + path38.substring(4);
|
|
152719
152961
|
output = output.replace(/\/?[^\/]*$/, "");
|
|
152720
152962
|
} else {
|
|
152721
|
-
var segment =
|
|
152963
|
+
var segment = path38.match(/(\/?([^\/]*))/)[0];
|
|
152722
152964
|
output += segment;
|
|
152723
|
-
|
|
152965
|
+
path38 = path38.substring(segment.length);
|
|
152724
152966
|
}
|
|
152725
152967
|
}
|
|
152726
152968
|
return output;
|
|
@@ -164790,21 +165032,21 @@ function jsonToKeyPathChunks(value, label = "$") {
|
|
|
164790
165032
|
walk(value, label, out);
|
|
164791
165033
|
return out;
|
|
164792
165034
|
}
|
|
164793
|
-
function walk(val,
|
|
165035
|
+
function walk(val, path38, out) {
|
|
164794
165036
|
if (val === null || val === undefined)
|
|
164795
165037
|
return;
|
|
164796
165038
|
if (Array.isArray(val)) {
|
|
164797
165039
|
if (val.length === 0) {
|
|
164798
|
-
out.push({ path:
|
|
165040
|
+
out.push({ path: path38, content: `**${path38}** = _[]_` });
|
|
164799
165041
|
return;
|
|
164800
165042
|
}
|
|
164801
165043
|
if (val.every((v) => v !== null && typeof v === "object")) {
|
|
164802
|
-
val.forEach((v, i) => walk(v, `${
|
|
165044
|
+
val.forEach((v, i) => walk(v, `${path38}[${i}]`, out));
|
|
164803
165045
|
return;
|
|
164804
165046
|
}
|
|
164805
165047
|
const items = val.map((v) => `- \`${String(v)}\``).join(`
|
|
164806
165048
|
`);
|
|
164807
|
-
out.push({ path:
|
|
165049
|
+
out.push({ path: path38, content: `**${path38}**
|
|
164808
165050
|
|
|
164809
165051
|
${items}` });
|
|
164810
165052
|
return;
|
|
@@ -164812,16 +165054,16 @@ ${items}` });
|
|
|
164812
165054
|
if (typeof val === "object") {
|
|
164813
165055
|
const entries = Object.entries(val);
|
|
164814
165056
|
if (entries.length === 0) {
|
|
164815
|
-
out.push({ path:
|
|
165057
|
+
out.push({ path: path38, content: `**${path38}** = _{}_` });
|
|
164816
165058
|
return;
|
|
164817
165059
|
}
|
|
164818
165060
|
for (const [k, v] of entries) {
|
|
164819
165061
|
const safeKey = /^[A-Za-z_$][\w$]*$/.test(k) ? k : JSON.stringify(k);
|
|
164820
|
-
walk(v, `${
|
|
165062
|
+
walk(v, `${path38}.${safeKey}`, out);
|
|
164821
165063
|
}
|
|
164822
165064
|
return;
|
|
164823
165065
|
}
|
|
164824
|
-
out.push({ path:
|
|
165066
|
+
out.push({ path: path38, content: `**${path38}** = \`${String(val)}\`` });
|
|
164825
165067
|
}
|
|
164826
165068
|
var gfm, STRIP_SELECTORS, tdCache = null;
|
|
164827
165069
|
var init_html_to_md = __esm(() => {
|
|
@@ -165161,6 +165403,7 @@ var init_services = __esm(() => {
|
|
|
165161
165403
|
init_embeddings();
|
|
165162
165404
|
init_local_health_checker();
|
|
165163
165405
|
init_index_job_tracker();
|
|
165406
|
+
init_heavy_work_lease();
|
|
165164
165407
|
init_scheduler2();
|
|
165165
165408
|
init_models_dev_client();
|
|
165166
165409
|
init_memory_graph_service();
|
|
@@ -165587,9 +165830,9 @@ var init_hook_service = __esm(() => {
|
|
|
165587
165830
|
});
|
|
165588
165831
|
|
|
165589
165832
|
// ../../packages/core/dist/services/bootstrap/bootstrap-service.js
|
|
165590
|
-
import { randomUUID as
|
|
165833
|
+
import { randomUUID as randomUUID10 } from "crypto";
|
|
165591
165834
|
import fs24 from "fs";
|
|
165592
|
-
import
|
|
165835
|
+
import path38 from "path";
|
|
165593
165836
|
import { spawn as spawn2 } from "child_process";
|
|
165594
165837
|
function readBootstrapConfig() {
|
|
165595
165838
|
try {
|
|
@@ -165689,7 +165932,7 @@ class BootstrapService {
|
|
|
165689
165932
|
return { ...noopResult("no-signals"), signalCount };
|
|
165690
165933
|
}
|
|
165691
165934
|
const capped = seeds.slice(0, cfg.maxSeedMemories);
|
|
165692
|
-
const bootstrapId = `boot-${Date.now()}-${
|
|
165935
|
+
const bootstrapId = `boot-${Date.now()}-${randomUUID10().slice(0, 8)}`;
|
|
165693
165936
|
let ids;
|
|
165694
165937
|
try {
|
|
165695
165938
|
ids = await storeSeeds(this.memoryRepo, projectId, bootstrapId, capped, signals);
|
|
@@ -165749,7 +165992,7 @@ async function scanSignals(_projectId, projectRoot, caps, symbolGraph, gitRunner
|
|
|
165749
165992
|
}
|
|
165750
165993
|
try {
|
|
165751
165994
|
for (const name26 of README_CANDIDATES) {
|
|
165752
|
-
const p =
|
|
165995
|
+
const p = path38.join(projectRoot, name26);
|
|
165753
165996
|
if (fs24.existsSync(p) && fs24.statSync(p).isFile()) {
|
|
165754
165997
|
const buf = fs24.readFileSync(p);
|
|
165755
165998
|
signals.readme = buf.slice(0, MAX_README_BYTES).toString("utf8");
|
|
@@ -165760,14 +166003,14 @@ async function scanSignals(_projectId, projectRoot, caps, symbolGraph, gitRunner
|
|
|
165760
166003
|
logger.debug("bootstrap scan: README read failed", { error: e.message });
|
|
165761
166004
|
}
|
|
165762
166005
|
try {
|
|
165763
|
-
const docsDir =
|
|
166006
|
+
const docsDir = path38.join(projectRoot, "docs");
|
|
165764
166007
|
if (fs24.existsSync(docsDir) && fs24.statSync(docsDir).isDirectory()) {
|
|
165765
166008
|
const entries = walkMarkdown(docsDir).slice(0, MAX_DOCS);
|
|
165766
166009
|
for (const rel of entries) {
|
|
165767
166010
|
try {
|
|
165768
166011
|
const buf = fs24.readFileSync(rel);
|
|
165769
166012
|
signals.docs.push({
|
|
165770
|
-
path:
|
|
166013
|
+
path: path38.relative(projectRoot, rel),
|
|
165771
166014
|
snippet: buf.slice(0, MAX_DOC_BYTES).toString("utf8")
|
|
165772
166015
|
});
|
|
165773
166016
|
} catch {}
|
|
@@ -165778,7 +166021,7 @@ async function scanSignals(_projectId, projectRoot, caps, symbolGraph, gitRunner
|
|
|
165778
166021
|
}
|
|
165779
166022
|
try {
|
|
165780
166023
|
for (const name26 of MANIFEST_FILES) {
|
|
165781
|
-
const p =
|
|
166024
|
+
const p = path38.join(projectRoot, name26);
|
|
165782
166025
|
if (!fs24.existsSync(p) || !fs24.statSync(p).isFile())
|
|
165783
166026
|
continue;
|
|
165784
166027
|
const raw2 = fs24.readFileSync(p).slice(0, MAX_MANIFEST_BYTES).toString("utf8");
|
|
@@ -165826,7 +166069,7 @@ function walkMarkdown(dir) {
|
|
|
165826
166069
|
continue;
|
|
165827
166070
|
}
|
|
165828
166071
|
for (const e of entries) {
|
|
165829
|
-
const full =
|
|
166072
|
+
const full = path38.join(cur, e.name);
|
|
165830
166073
|
if (e.isDirectory()) {
|
|
165831
166074
|
if (e.name === "node_modules" || e.name.startsWith("."))
|
|
165832
166075
|
continue;
|
|
@@ -165943,7 +166186,7 @@ async function storeSeeds(memoryRepo, projectId, bootstrapId, seeds, signals) {
|
|
|
165943
166186
|
const ids = [];
|
|
165944
166187
|
const signalCount = countSignals(signals);
|
|
165945
166188
|
for (const seed of seeds) {
|
|
165946
|
-
const id = `seed-${Date.now()}-${
|
|
166189
|
+
const id = `seed-${Date.now()}-${randomUUID10().slice(0, 8)}`;
|
|
165947
166190
|
const input = {
|
|
165948
166191
|
id,
|
|
165949
166192
|
content: truncate3(seed.summary, MAX_SUMMARY_CHARS),
|
|
@@ -166057,7 +166300,7 @@ var init_bootstrap_service = __esm(() => {
|
|
|
166057
166300
|
MAX_DOC_BYTES = 2 * 1024;
|
|
166058
166301
|
MAX_MANIFEST_BYTES = 2 * 1024;
|
|
166059
166302
|
SeedMemorySchema = exports_external.object({
|
|
166060
|
-
summary: exports_external.string().min(1)
|
|
166303
|
+
summary: exports_external.string().min(1),
|
|
166061
166304
|
type: exports_external.enum(["pattern", "code", "decision"]),
|
|
166062
166305
|
level: exports_external.union([exports_external.literal(0), exports_external.literal(1), exports_external.literal(2)]),
|
|
166063
166306
|
importance: exports_external.number().min(0).max(1),
|
|
@@ -166650,7 +166893,9 @@ var init_handoff_auto_injector = __esm(() => {
|
|
|
166650
166893
|
var exports_dist = {};
|
|
166651
166894
|
__export(exports_dist, {
|
|
166652
166895
|
workspaceManager: () => workspaceManager,
|
|
166896
|
+
withHeavyWorkLease: () => withHeavyWorkLease,
|
|
166653
166897
|
validateEvent: () => validateEvent,
|
|
166898
|
+
validateEnum: () => validateEnum,
|
|
166654
166899
|
validateAllGrammars: () => validateAllGrammars,
|
|
166655
166900
|
tracePathService: () => tracePathService,
|
|
166656
166901
|
toSymbolIdentityResolution: () => toSymbolIdentityResolution,
|
|
@@ -166694,6 +166939,7 @@ __export(exports_dist, {
|
|
|
166694
166939
|
recordSearchDegradation: () => recordSearchDegradation,
|
|
166695
166940
|
quoteDiscoveredIdentifier: () => quoteDiscoveredIdentifier,
|
|
166696
166941
|
projectNotIndexed: () => projectNotIndexed,
|
|
166942
|
+
probeHeavyWork: () => probeHeavyWork,
|
|
166697
166943
|
payloadStorePolicies: () => payloadStorePolicies,
|
|
166698
166944
|
parseStructuralFqn: () => parseStructuralFqn,
|
|
166699
166945
|
parseProjectIdentityPreviewRequest: () => parseProjectIdentityPreviewRequest,
|
|
@@ -166824,6 +167070,7 @@ __export(exports_dist, {
|
|
|
166824
167070
|
UNKNOWN_ACTOR: () => UNKNOWN_ACTOR,
|
|
166825
167071
|
TracePathTool: () => TracePathTool,
|
|
166826
167072
|
TracePathService: () => TracePathService,
|
|
167073
|
+
ToolError: () => ToolError,
|
|
166827
167074
|
TokenMetrics: () => TokenMetrics,
|
|
166828
167075
|
TaskEnvelopeService: () => TaskEnvelopeService,
|
|
166829
167076
|
TYPESCRIPT_RESOLVER_VERSION: () => TYPESCRIPT_RESOLVER_VERSION,
|
|
@@ -167000,6 +167247,7 @@ var init_dist15 = __esm(() => {
|
|
|
167000
167247
|
init_proposal_repository();
|
|
167001
167248
|
init_proposal_payload_validation();
|
|
167002
167249
|
init_auto_improve_job();
|
|
167250
|
+
init_enum_validation();
|
|
167003
167251
|
init_tools();
|
|
167004
167252
|
init_services();
|
|
167005
167253
|
init_graph_generation();
|
|
@@ -169467,7 +169715,7 @@ init_dist();
|
|
|
169467
169715
|
init_dist15();
|
|
169468
169716
|
init_dist();
|
|
169469
169717
|
import fs25 from "fs/promises";
|
|
169470
|
-
import
|
|
169718
|
+
import path39 from "path";
|
|
169471
169719
|
var _indexProjectTool = null;
|
|
169472
169720
|
function indexProjectTool() {
|
|
169473
169721
|
if (!_indexProjectTool)
|
|
@@ -169770,7 +170018,7 @@ class EmbeddedApiClient {
|
|
|
169770
170018
|
} else {
|
|
169771
170019
|
end = start + 20;
|
|
169772
170020
|
}
|
|
169773
|
-
const absolutePath =
|
|
170021
|
+
const absolutePath = path39.join(workspace.project_path, file2);
|
|
169774
170022
|
const content = await fs25.readFile(absolutePath, "utf-8");
|
|
169775
170023
|
const lines = content.split(/\r?\n/);
|
|
169776
170024
|
const slice = lines.slice(start - 1, Math.min(lines.length, end));
|
|
@@ -170026,21 +170274,21 @@ class EmbeddedApiClient {
|
|
|
170026
170274
|
async uploadAndIndex(params) {
|
|
170027
170275
|
const rawBase = params.projectId || params.projectPath.replace(/\\/g, "/").split("/").filter(Boolean).pop() || "default";
|
|
170028
170276
|
const finalProjectId = rawBase.replace(/[^a-zA-Z0-9_.-]/g, "_").slice(0, 128);
|
|
170029
|
-
const uploadRoot = process.env.MASSA_AI_UPLOAD_DIR ||
|
|
170030
|
-
const stagingDir =
|
|
170277
|
+
const uploadRoot = process.env.MASSA_AI_UPLOAD_DIR || path39.join(getGlobalDataDir(), "uploads");
|
|
170278
|
+
const stagingDir = path39.resolve(uploadRoot, finalProjectId);
|
|
170031
170279
|
await fs25.rm(stagingDir, { recursive: true, force: true });
|
|
170032
170280
|
await fs25.mkdir(stagingDir, { recursive: true });
|
|
170033
170281
|
const WRITE_BATCH = 20;
|
|
170034
170282
|
for (let i = 0;i < params.files.length; i += WRITE_BATCH) {
|
|
170035
170283
|
await Promise.all(params.files.slice(i, i + WRITE_BATCH).map(async (file2) => {
|
|
170036
|
-
if (
|
|
170284
|
+
if (path39.isAbsolute(file2.relativePath) || file2.relativePath.includes("..")) {
|
|
170037
170285
|
throw new Error(`Invalid file path: ${file2.relativePath}`);
|
|
170038
170286
|
}
|
|
170039
|
-
const dest =
|
|
170040
|
-
if (!dest.startsWith(stagingDir +
|
|
170287
|
+
const dest = path39.resolve(stagingDir, file2.relativePath.replace(/\//g, path39.sep));
|
|
170288
|
+
if (!dest.startsWith(stagingDir + path39.sep)) {
|
|
170041
170289
|
throw new Error(`Path escapes staging directory: ${file2.relativePath}`);
|
|
170042
170290
|
}
|
|
170043
|
-
await fs25.mkdir(
|
|
170291
|
+
await fs25.mkdir(path39.dirname(dest), { recursive: true });
|
|
170044
170292
|
await fs25.writeFile(dest, file2.content, "utf-8");
|
|
170045
170293
|
}));
|
|
170046
170294
|
}
|
|
@@ -170100,37 +170348,39 @@ class EmbeddedApiClient {
|
|
|
170100
170348
|
return { success: false, error: "projectId is required" };
|
|
170101
170349
|
const result = {};
|
|
170102
170350
|
const errors4 = [];
|
|
170103
|
-
|
|
170104
|
-
|
|
170105
|
-
|
|
170106
|
-
|
|
170107
|
-
|
|
170108
|
-
|
|
170109
|
-
|
|
170110
|
-
|
|
170111
|
-
|
|
170112
|
-
|
|
170113
|
-
|
|
170114
|
-
|
|
170351
|
+
await withHeavyWorkLease("maintenance", `project-reset:${projectId}`, async () => {
|
|
170352
|
+
if (clearVectors) {
|
|
170353
|
+
try {
|
|
170354
|
+
const vectorStore = await getVectorStore();
|
|
170355
|
+
const keywordSearch = getKeywordSearch();
|
|
170356
|
+
const [vectorsDeleted, keywordsDeleted] = await Promise.all([
|
|
170357
|
+
vectorStore.deleteByProject(projectId),
|
|
170358
|
+
keywordSearch.deleteByProject(projectId)
|
|
170359
|
+
]);
|
|
170360
|
+
result.vectorsDeleted = vectorsDeleted;
|
|
170361
|
+
result.keywordsDeleted = keywordsDeleted;
|
|
170362
|
+
} catch (e) {
|
|
170363
|
+
errors4.push(`vectors: ${e.message}`);
|
|
170364
|
+
}
|
|
170115
170365
|
}
|
|
170116
|
-
|
|
170117
|
-
|
|
170118
|
-
|
|
170119
|
-
|
|
170120
|
-
|
|
170121
|
-
|
|
170122
|
-
|
|
170366
|
+
if (clearSymbols) {
|
|
170367
|
+
try {
|
|
170368
|
+
await workspaceManager.removeWorkspace(projectId);
|
|
170369
|
+
result.symbolsDeleted = "ok";
|
|
170370
|
+
} catch (e) {
|
|
170371
|
+
errors4.push(`symbols: ${e.message}`);
|
|
170372
|
+
}
|
|
170123
170373
|
}
|
|
170124
|
-
|
|
170125
|
-
|
|
170126
|
-
|
|
170127
|
-
|
|
170128
|
-
|
|
170129
|
-
|
|
170130
|
-
|
|
170131
|
-
|
|
170374
|
+
if (clearMemories) {
|
|
170375
|
+
try {
|
|
170376
|
+
const repo = getMemoryRepository();
|
|
170377
|
+
const deleted = await repo.deleteByProject(projectId);
|
|
170378
|
+
result.memoriesDeleted = deleted;
|
|
170379
|
+
} catch (e) {
|
|
170380
|
+
errors4.push(`memories: ${e.message}`);
|
|
170381
|
+
}
|
|
170132
170382
|
}
|
|
170133
|
-
}
|
|
170383
|
+
});
|
|
170134
170384
|
return {
|
|
170135
170385
|
success: errors4.length === 0,
|
|
170136
170386
|
data: { projectId, ...result, errors: errors4, message: `Project '${projectId}' reset complete.` }
|
|
@@ -170542,7 +170792,7 @@ class EmbeddedApiClient {
|
|
|
170542
170792
|
// src/file-collector.ts
|
|
170543
170793
|
init_config();
|
|
170544
170794
|
import fs26 from "fs/promises";
|
|
170545
|
-
import
|
|
170795
|
+
import path40 from "path";
|
|
170546
170796
|
var SKIP_DIRS = new Set([
|
|
170547
170797
|
"node_modules",
|
|
170548
170798
|
".git",
|
|
@@ -170558,11 +170808,21 @@ var SKIP_DIRS = new Set([
|
|
|
170558
170808
|
".cache",
|
|
170559
170809
|
"vendor",
|
|
170560
170810
|
".svn",
|
|
170561
|
-
".hg"
|
|
170811
|
+
".hg",
|
|
170812
|
+
"Pods"
|
|
170562
170813
|
]);
|
|
170563
170814
|
var MAX_FILE_BYTES = 512 * 1024;
|
|
170564
|
-
var MAX_TOTAL_BYTES =
|
|
170565
|
-
var MAX_FILES =
|
|
170815
|
+
var MAX_TOTAL_BYTES = 150 * 1024 * 1024;
|
|
170816
|
+
var MAX_FILES = 15000;
|
|
170817
|
+
async function getIncludeDirs(projectPath2) {
|
|
170818
|
+
try {
|
|
170819
|
+
const raw2 = await fs26.readFile(path40.join(projectPath2, ".massa-ai-collect"), "utf-8");
|
|
170820
|
+
return raw2.split(`
|
|
170821
|
+
`).map((s) => s.trim().replace(/^\/+|\/+$/g, "")).filter((s) => s && !s.startsWith("#"));
|
|
170822
|
+
} catch {
|
|
170823
|
+
return [];
|
|
170824
|
+
}
|
|
170825
|
+
}
|
|
170566
170826
|
function getAllowedExtensions() {
|
|
170567
170827
|
try {
|
|
170568
170828
|
const list = config2.get("security").allowedExtensions;
|
|
@@ -170575,7 +170835,16 @@ async function collectFiles(projectPath2) {
|
|
|
170575
170835
|
const files = [];
|
|
170576
170836
|
const state = { totalBytes: 0 };
|
|
170577
170837
|
const allowed = getAllowedExtensions();
|
|
170578
|
-
await
|
|
170838
|
+
const includeDirs = await getIncludeDirs(projectPath2);
|
|
170839
|
+
if (includeDirs.length === 0) {
|
|
170840
|
+
await walk2(projectPath2, projectPath2, files, state, allowed);
|
|
170841
|
+
} else {
|
|
170842
|
+
for (const top of includeDirs) {
|
|
170843
|
+
if (files.length >= MAX_FILES || state.totalBytes >= MAX_TOTAL_BYTES)
|
|
170844
|
+
break;
|
|
170845
|
+
await walk2(projectPath2, path40.join(projectPath2, top), files, state, allowed);
|
|
170846
|
+
}
|
|
170847
|
+
}
|
|
170579
170848
|
return files;
|
|
170580
170849
|
}
|
|
170581
170850
|
async function walk2(root2, dir, files, state, allowed) {
|
|
@@ -170592,13 +170861,13 @@ async function walk2(root2, dir, files, state, allowed) {
|
|
|
170592
170861
|
break;
|
|
170593
170862
|
if (entry2.isDirectory()) {
|
|
170594
170863
|
if (!SKIP_DIRS.has(entry2.name) && !entry2.name.startsWith(".")) {
|
|
170595
|
-
await walk2(root2,
|
|
170864
|
+
await walk2(root2, path40.join(dir, entry2.name), files, state, allowed);
|
|
170596
170865
|
}
|
|
170597
170866
|
} else if (entry2.isFile()) {
|
|
170598
|
-
const ext2 =
|
|
170867
|
+
const ext2 = path40.extname(entry2.name).toLowerCase();
|
|
170599
170868
|
if (!allowed.has(ext2))
|
|
170600
170869
|
continue;
|
|
170601
|
-
const fullPath =
|
|
170870
|
+
const fullPath = path40.join(dir, entry2.name);
|
|
170602
170871
|
try {
|
|
170603
170872
|
const stat = await fs26.stat(fullPath);
|
|
170604
170873
|
if (stat.size > MAX_FILE_BYTES)
|
|
@@ -170607,7 +170876,7 @@ async function walk2(root2, dir, files, state, allowed) {
|
|
|
170607
170876
|
continue;
|
|
170608
170877
|
const content = await fs26.readFile(fullPath, "utf-8");
|
|
170609
170878
|
state.totalBytes += stat.size;
|
|
170610
|
-
const relativePath =
|
|
170879
|
+
const relativePath = path40.relative(root2, fullPath).split(path40.sep).join("/");
|
|
170611
170880
|
files.push({ relativePath, content });
|
|
170612
170881
|
} catch {}
|
|
170613
170882
|
}
|