@massa-ai/mcp-client 1.63.1 → 1.65.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 +410 -179
- package/dist/index.js +1105 -848
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -28537,22 +28537,15 @@ var BOOTSTRAP_RULE_IDS, RETIRED_RULE_IDS, BOOTSTRAP_RULES, RULES_BY_ID, Bootstra
|
|
|
28537
28537
|
};
|
|
28538
28538
|
var init_rules = __esm(() => {
|
|
28539
28539
|
BOOTSTRAP_RULE_IDS = [
|
|
28540
|
-
"caveman",
|
|
28541
28540
|
"massa-ai-router",
|
|
28542
28541
|
"dedupe-guardrails",
|
|
28543
|
-
"plan-challenge",
|
|
28544
28542
|
"conversation-feedback",
|
|
28545
28543
|
"indexing-hygiene",
|
|
28546
28544
|
"english-code",
|
|
28547
28545
|
"code-comments"
|
|
28548
28546
|
];
|
|
28549
|
-
RETIRED_RULE_IDS = ["persona-router"];
|
|
28547
|
+
RETIRED_RULE_IDS = ["persona-router", "caveman", "plan-challenge"];
|
|
28550
28548
|
BOOTSTRAP_RULES = [
|
|
28551
|
-
{
|
|
28552
|
-
id: "caveman",
|
|
28553
|
-
defaultEnabled: true,
|
|
28554
|
-
description: "Keep communication compressed while preserving technical accuracy."
|
|
28555
|
-
},
|
|
28556
28549
|
{
|
|
28557
28550
|
id: "massa-ai-router",
|
|
28558
28551
|
defaultEnabled: true,
|
|
@@ -28563,11 +28556,6 @@ var init_rules = __esm(() => {
|
|
|
28563
28556
|
defaultEnabled: true,
|
|
28564
28557
|
description: "Reuse already-loaded massa-ai context instead of bulk-loading workflows or references."
|
|
28565
28558
|
},
|
|
28566
|
-
{
|
|
28567
|
-
id: "plan-challenge",
|
|
28568
|
-
defaultEnabled: true,
|
|
28569
|
-
description: "Run The Fool as a post-plan challenge gate per the configured policy."
|
|
28570
|
-
},
|
|
28571
28559
|
{
|
|
28572
28560
|
id: "conversation-feedback",
|
|
28573
28561
|
defaultEnabled: true,
|
|
@@ -35199,7 +35187,8 @@ var init_ignore_patterns = __esm(() => {
|
|
|
35199
35187
|
"**/pnpm-lock.yaml",
|
|
35200
35188
|
"**/package-lock.json",
|
|
35201
35189
|
"**/bun.lockb",
|
|
35202
|
-
"**/yarn.lock"
|
|
35190
|
+
"**/yarn.lock",
|
|
35191
|
+
"**/Pods/**"
|
|
35203
35192
|
];
|
|
35204
35193
|
});
|
|
35205
35194
|
|
|
@@ -124317,6 +124306,33 @@ class ManagedRunRepositoryPg {
|
|
|
124317
124306
|
`;
|
|
124318
124307
|
return rows[0] ? toActive(rows[0]) : null;
|
|
124319
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
|
+
}
|
|
124320
124336
|
}
|
|
124321
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;
|
|
124322
124338
|
var init_managed_run_repository_pg = __esm(() => {
|
|
@@ -124354,10 +124370,111 @@ var init_embedding_freshness = __esm(() => {
|
|
|
124354
124370
|
};
|
|
124355
124371
|
});
|
|
124356
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
|
+
|
|
124357
124474
|
// ../../packages/core/dist/services/search/project-indexer.js
|
|
124358
124475
|
import fs15 from "fs/promises";
|
|
124359
|
-
import
|
|
124360
|
-
import { randomUUID as
|
|
124476
|
+
import path22 from "path";
|
|
124477
|
+
import { randomUUID as randomUUID4 } from "crypto";
|
|
124361
124478
|
async function runWithIndexLock(lockMap, projectId, work) {
|
|
124362
124479
|
const prevLock = lockMap.get(projectId);
|
|
124363
124480
|
const isQueued = prevLock !== undefined;
|
|
@@ -124399,7 +124516,7 @@ async function indexProjectInternal(deps, projectPath, projectId, options = {})
|
|
|
124399
124516
|
dot: false
|
|
124400
124517
|
});
|
|
124401
124518
|
const filteredFiles = files.filter((file2) => {
|
|
124402
|
-
const relativePath =
|
|
124519
|
+
const relativePath = path22.relative(projectPath, file2);
|
|
124403
124520
|
const shouldIgnore = ig.ignores(relativePath);
|
|
124404
124521
|
if (shouldIgnore) {
|
|
124405
124522
|
logger.debug("Ignoring file per .gitignore during indexing", {
|
|
@@ -124439,7 +124556,7 @@ async function indexProjectInternal(deps, projectPath, projectId, options = {})
|
|
|
124439
124556
|
});
|
|
124440
124557
|
}
|
|
124441
124558
|
}
|
|
124442
|
-
const indexedFilesList = filteredFiles.map((f) =>
|
|
124559
|
+
const indexedFilesList = filteredFiles.map((f) => path22.relative(projectPath, f));
|
|
124443
124560
|
await deps.indexManager.updateIndexMetadata(projectId, projectPath, indexedFilesList);
|
|
124444
124561
|
logger.info("Project indexing completed", {
|
|
124445
124562
|
projectId,
|
|
@@ -124510,7 +124627,7 @@ async function ensureFreshIndex(deps, projectId, projectPath, options = {}) {
|
|
|
124510
124627
|
if (needsFullReindex) {
|
|
124511
124628
|
logger.info("Performing full reindex", { projectId });
|
|
124512
124629
|
const managedRunRepo = ManagedRunRepositoryPg.getInstance();
|
|
124513
|
-
const eventId = `reindex:${projectId}:${
|
|
124630
|
+
const eventId = `reindex:${projectId}:${randomUUID4()}`;
|
|
124514
124631
|
const beginOutcome = await managedRunRepo.begin({
|
|
124515
124632
|
projectId,
|
|
124516
124633
|
runKind: "indexing",
|
|
@@ -124563,25 +124680,7 @@ async function ensureFreshIndex(deps, projectId, projectPath, options = {}) {
|
|
|
124563
124680
|
projectId,
|
|
124564
124681
|
fileCount: filesToReindex.length
|
|
124565
124682
|
});
|
|
124566
|
-
const
|
|
124567
|
-
let filesIndexed = 0;
|
|
124568
|
-
let chunksIndexed = 0;
|
|
124569
|
-
let errors4 = 0;
|
|
124570
|
-
for (const relativeFilePath of filesToReindex) {
|
|
124571
|
-
try {
|
|
124572
|
-
const fullPath = path21.join(projectPath, relativeFilePath);
|
|
124573
|
-
const result = await deps.indexFile(fullPath, projectId, projectPath, centralityMap);
|
|
124574
|
-
filesIndexed++;
|
|
124575
|
-
chunksIndexed += result.chunks;
|
|
124576
|
-
} catch (error51) {
|
|
124577
|
-
logger.error("Failed to reindex file", error51, {
|
|
124578
|
-
file: relativeFilePath
|
|
124579
|
-
});
|
|
124580
|
-
errors4++;
|
|
124581
|
-
}
|
|
124582
|
-
}
|
|
124583
|
-
await deps.indexManager.updateIndexMetadata(projectId, projectPath, filesToReindex);
|
|
124584
|
-
await deps.searchCache.invalidateProject(projectId);
|
|
124683
|
+
const { filesIndexed, chunksIndexed, errors: errors4 } = await runIncrementalReindex(deps, projectId, projectPath, filesToReindex);
|
|
124585
124684
|
logger.info("Incremental reindex completed", {
|
|
124586
124685
|
projectId,
|
|
124587
124686
|
filesIndexed,
|
|
@@ -124630,7 +124729,7 @@ async function checkSearchAdmission(deps, projectId, projectPath) {
|
|
|
124630
124729
|
async function indexFile(deps, filePath, projectId, projectRoot, centralityMap) {
|
|
124631
124730
|
projectId = await getProjectIdentityAliasResolver().resolve(projectId);
|
|
124632
124731
|
const content = await fs15.readFile(filePath, "utf-8");
|
|
124633
|
-
const relativePath =
|
|
124732
|
+
const relativePath = path22.relative(projectRoot, filePath);
|
|
124634
124733
|
const maxFileSize = config2.get("security").maxFileSize || 1024 * 1024;
|
|
124635
124734
|
if (content.length > maxFileSize) {
|
|
124636
124735
|
logger.warn("File too large, skipping", {
|
|
@@ -124650,7 +124749,7 @@ async function indexFile(deps, filePath, projectId, projectRoot, centralityMap)
|
|
|
124650
124749
|
chunkIndex: i,
|
|
124651
124750
|
totalChunks: chunks.length,
|
|
124652
124751
|
type: chunk.type,
|
|
124653
|
-
language:
|
|
124752
|
+
language: path22.extname(filePath).slice(1),
|
|
124654
124753
|
lineStart: chunk.lineStart,
|
|
124655
124754
|
lineEnd: chunk.lineEnd,
|
|
124656
124755
|
label: chunk.label,
|
|
@@ -124675,6 +124774,7 @@ var init_project_indexer = __esm(() => {
|
|
|
124675
124774
|
init_managed_run_repository_pg();
|
|
124676
124775
|
init_symbol_repo_workspace();
|
|
124677
124776
|
init_embedding_freshness();
|
|
124777
|
+
init_incremental_reindex();
|
|
124678
124778
|
globAsync2 = glob;
|
|
124679
124779
|
});
|
|
124680
124780
|
|
|
@@ -126494,7 +126594,7 @@ var init_index_job_store = __esm(() => {
|
|
|
126494
126594
|
});
|
|
126495
126595
|
|
|
126496
126596
|
// ../../packages/core/dist/services/jobs/index-job-tracker.js
|
|
126497
|
-
import { randomUUID as
|
|
126597
|
+
import { randomUUID as randomUUID5 } from "crypto";
|
|
126498
126598
|
|
|
126499
126599
|
class IndexJobTracker {
|
|
126500
126600
|
static instance;
|
|
@@ -126518,7 +126618,7 @@ class IndexJobTracker {
|
|
|
126518
126618
|
return IndexJobTracker.instance;
|
|
126519
126619
|
}
|
|
126520
126620
|
createJob(projectId, projectPath) {
|
|
126521
|
-
const jobId =
|
|
126621
|
+
const jobId = randomUUID5();
|
|
126522
126622
|
const job = {
|
|
126523
126623
|
jobId,
|
|
126524
126624
|
projectId,
|
|
@@ -126608,7 +126708,9 @@ class IndexJobTracker {
|
|
|
126608
126708
|
const cutoff = now2 - staleMs;
|
|
126609
126709
|
let reaped = 0;
|
|
126610
126710
|
for (const job of running) {
|
|
126611
|
-
const
|
|
126711
|
+
const live = this.jobs.get(job.jobId);
|
|
126712
|
+
const liveHb = live?.heartbeatAt?.getTime();
|
|
126713
|
+
const hbMs = liveHb ?? job.heartbeatAt?.getTime();
|
|
126612
126714
|
const startedMs = job.startedAt?.getTime();
|
|
126613
126715
|
const stale = hbMs != null && hbMs < cutoff || hbMs == null && startedMs != null && startedMs < cutoff;
|
|
126614
126716
|
if (!stale)
|
|
@@ -126722,7 +126824,7 @@ function stripNul(content) {
|
|
|
126722
126824
|
|
|
126723
126825
|
// ../../packages/core/dist/services/etl/stages/discover.js
|
|
126724
126826
|
import fs16 from "fs/promises";
|
|
126725
|
-
import
|
|
126827
|
+
import path23 from "path";
|
|
126726
126828
|
import { createHash as createHash5 } from "crypto";
|
|
126727
126829
|
|
|
126728
126830
|
class DiscoverStage {
|
|
@@ -126748,7 +126850,7 @@ class DiscoverStage {
|
|
|
126748
126850
|
dot: false,
|
|
126749
126851
|
absolute: false
|
|
126750
126852
|
});
|
|
126751
|
-
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");
|
|
126752
126854
|
}
|
|
126753
126855
|
if (ctx.resumeCursor?.path) {
|
|
126754
126856
|
const cursorPath = ctx.resumeCursor.path;
|
|
@@ -126807,7 +126909,7 @@ class DiscoverStage {
|
|
|
126807
126909
|
return discovered;
|
|
126808
126910
|
}
|
|
126809
126911
|
async processFile(ctx, relativePath, forceReindex) {
|
|
126810
|
-
const absolutePath =
|
|
126912
|
+
const absolutePath = path23.join(ctx.projectPath, relativePath);
|
|
126811
126913
|
try {
|
|
126812
126914
|
const stat = await fs16.stat(absolutePath);
|
|
126813
126915
|
const content = stripNul(await fs16.readFile(absolutePath, "utf-8"));
|
|
@@ -126854,7 +126956,7 @@ class DiscoverStage {
|
|
|
126854
126956
|
ig.add(pattern);
|
|
126855
126957
|
}
|
|
126856
126958
|
try {
|
|
126857
|
-
const gitignorePath =
|
|
126959
|
+
const gitignorePath = path23.join(projectPath, ".gitignore");
|
|
126858
126960
|
const gitignoreContent = await fs16.readFile(gitignorePath, "utf8");
|
|
126859
126961
|
const rules = gitignoreContent.split(`
|
|
126860
126962
|
`).map((line) => line.trim()).filter((line) => line && !line.startsWith("#"));
|
|
@@ -128210,8 +128312,8 @@ function rustUseLeaves(node, source, prefix = []) {
|
|
|
128210
128312
|
}
|
|
128211
128313
|
if (node.type === "use_wildcard")
|
|
128212
128314
|
return [{ path: [...prefix, "*"], glob: true }];
|
|
128213
|
-
const
|
|
128214
|
-
return
|
|
128315
|
+
const path24 = rustPathSegments(node, source);
|
|
128316
|
+
return path24.length ? [{ path: [...prefix, ...path24] }] : [];
|
|
128215
128317
|
}
|
|
128216
128318
|
function functionalCaptures(captures, source, family) {
|
|
128217
128319
|
if (family !== "clojure")
|
|
@@ -129183,7 +129285,7 @@ var init_structural_runtime = __esm(() => {
|
|
|
129183
129285
|
});
|
|
129184
129286
|
|
|
129185
129287
|
// ../../packages/core/dist/services/etl/stages/parse.js
|
|
129186
|
-
import
|
|
129288
|
+
import path24 from "path";
|
|
129187
129289
|
import fs17 from "fs/promises";
|
|
129188
129290
|
function resolveChunkerMaxChars() {
|
|
129189
129291
|
const global2 = Number(process.env.EMBEDDING_MAX_CHARS);
|
|
@@ -129212,8 +129314,8 @@ class ParseStage {
|
|
|
129212
129314
|
const results = new Map;
|
|
129213
129315
|
let processed = 0;
|
|
129214
129316
|
const phases = [
|
|
129215
|
-
files.filter((file2) =>
|
|
129216
|
-
files.filter((file2) =>
|
|
129317
|
+
files.filter((file2) => path24.extname(file2.relativePath).toLowerCase() !== ".h"),
|
|
129318
|
+
files.filter((file2) => path24.extname(file2.relativePath).toLowerCase() === ".h")
|
|
129217
129319
|
];
|
|
129218
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)));
|
|
129219
129321
|
for (const batch of batches) {
|
|
@@ -129251,19 +129353,19 @@ class ParseStage {
|
|
|
129251
129353
|
return files.map((file2) => results.get(file2.relativePath));
|
|
129252
129354
|
}
|
|
129253
129355
|
recordHeaderImporterEvidence(ctx, files, parsedFiles) {
|
|
129254
|
-
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)));
|
|
129255
129357
|
const mutable = {
|
|
129256
129358
|
...ctx.structuralHeaderEvidenceByFile
|
|
129257
129359
|
};
|
|
129258
129360
|
for (const parsed of parsedFiles) {
|
|
129259
|
-
const extension =
|
|
129361
|
+
const extension = path24.extname(parsed.file.relativePath).toLowerCase();
|
|
129260
129362
|
const key = extension === ".c" ? "cImporters" : [".cpp", ".hpp"].includes(extension) ? "cppImporters" : undefined;
|
|
129261
129363
|
if (!key)
|
|
129262
129364
|
continue;
|
|
129263
129365
|
for (const imported of parsed.rawImports) {
|
|
129264
129366
|
if (!["c_include", "cpp_include"].includes(imported.form) || imported.specifier.startsWith("<"))
|
|
129265
129367
|
continue;
|
|
129266
|
-
const header =
|
|
129368
|
+
const header = path24.posix.normalize(path24.posix.join(path24.posix.dirname(parsed.file.relativePath), imported.specifier));
|
|
129267
129369
|
if (!knownHeaders.has(header))
|
|
129268
129370
|
continue;
|
|
129269
129371
|
const existing = mutable[header] ?? {};
|
|
@@ -129274,7 +129376,7 @@ class ParseStage {
|
|
|
129274
129376
|
}
|
|
129275
129377
|
async parseFile(ctx, file2) {
|
|
129276
129378
|
if (!file2.needsReparse) {
|
|
129277
|
-
const extension =
|
|
129379
|
+
const extension = path24.extname(file2.relativePath).toLowerCase();
|
|
129278
129380
|
if ([".c", ".cpp", ".hpp"].includes(extension)) {
|
|
129279
129381
|
const content = file2.snapshotContent ?? await fs17.readFile(file2.absolutePath, "utf8");
|
|
129280
129382
|
const outcome = await this.runtime.parse({ extension, source: Buffer.from(content) });
|
|
@@ -129289,7 +129391,7 @@ class ParseStage {
|
|
|
129289
129391
|
}
|
|
129290
129392
|
try {
|
|
129291
129393
|
const content = file2.snapshotContent ?? await fs17.readFile(file2.absolutePath, "utf-8");
|
|
129292
|
-
const ext2 =
|
|
129394
|
+
const ext2 = path24.extname(file2.relativePath).toLowerCase();
|
|
129293
129395
|
const chunkerMaxChars = resolveChunkerMaxChars();
|
|
129294
129396
|
const chunks = smartChunk(content, file2.relativePath, chunkerMaxChars ? { maxChunkChars: chunkerMaxChars } : {});
|
|
129295
129397
|
let symbols;
|
|
@@ -129844,7 +129946,7 @@ var init_resolver = __esm(() => {
|
|
|
129844
129946
|
});
|
|
129845
129947
|
|
|
129846
129948
|
// ../../packages/core/dist/services/structural/resolvers/typescript.js
|
|
129847
|
-
import
|
|
129949
|
+
import path25 from "path";
|
|
129848
129950
|
function candidates(identities) {
|
|
129849
129951
|
return Object.freeze(identities.map((identity) => Object.freeze({
|
|
129850
129952
|
fqn: identity.fqn,
|
|
@@ -129939,7 +130041,7 @@ function probe(base, known, dialect = "typescript") {
|
|
|
129939
130041
|
const bases = /\.[cm]?jsx?$/u.test(base) ? [base.replace(/\.[cm]?jsx?$/u, ".ts"), base.replace(/\.[cm]?jsx?$/u, ".tsx"), base] : [base];
|
|
129940
130042
|
for (const candidateBase of bases)
|
|
129941
130043
|
for (const suffix of DIALECT_PROBES[dialect] ?? [""]) {
|
|
129942
|
-
const value =
|
|
130044
|
+
const value = path25.posix.normalize(`${candidateBase}${suffix}`);
|
|
129943
130045
|
if (!value.startsWith("../") && value !== ".." && known.has(value))
|
|
129944
130046
|
return value;
|
|
129945
130047
|
}
|
|
@@ -129948,7 +130050,7 @@ function probe(base, known, dialect = "typescript") {
|
|
|
129948
130050
|
function resolveStructuralSpecifier(specifier, fromFile, build, dialect = "typescript") {
|
|
129949
130051
|
const known = new Set(build.knownFiles.map(normalizeStructuralFile));
|
|
129950
130052
|
if (specifier.startsWith("./") || specifier.startsWith("../")) {
|
|
129951
|
-
return probe(
|
|
130053
|
+
return probe(path25.posix.join(path25.posix.dirname(fromFile), specifier), known, dialect);
|
|
129952
130054
|
}
|
|
129953
130055
|
const aliases = build.pathAliasesByFile?.[normalizeStructuralFile(fromFile)] ?? build.pathAliases ?? [];
|
|
129954
130056
|
for (const alias of aliases) {
|
|
@@ -130212,7 +130314,7 @@ var init_scripting2 = __esm(() => {
|
|
|
130212
130314
|
});
|
|
130213
130315
|
|
|
130214
130316
|
// ../../packages/core/dist/services/structural/resolvers/systems.js
|
|
130215
|
-
import
|
|
130317
|
+
import path26 from "path";
|
|
130216
130318
|
var DIALECTS, SYSTEMS_LANGUAGE_RESOLVER;
|
|
130217
130319
|
var init_systems2 = __esm(() => {
|
|
130218
130320
|
init_typescript2();
|
|
@@ -130231,7 +130333,7 @@ var init_systems2 = __esm(() => {
|
|
|
130231
130333
|
const bindings = item.bindings.map((binding) => binding.imported === "*" && binding.local === "*" && unresolvedTarget && !unresolvedTarget.qualifier ? { ...binding, imported: unresolvedTarget.name, local: unresolvedTarget.name } : binding);
|
|
130232
130334
|
if (item.specifier === "crate" || item.specifier.startsWith("crate/")) {
|
|
130233
130335
|
const crateRoot = file2.file.startsWith("src/") ? "src" : "";
|
|
130234
|
-
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, "")))}` };
|
|
130235
130337
|
}
|
|
130236
130338
|
if (item.specifier === "self" || item.specifier.startsWith("self/"))
|
|
130237
130339
|
return { ...item, bindings, specifier: `./${item.specifier.replace(/^self\/?/u, "")}` };
|
|
@@ -130329,7 +130431,7 @@ var init_data_document2 = __esm(() => {
|
|
|
130329
130431
|
});
|
|
130330
130432
|
|
|
130331
130433
|
// ../../packages/core/dist/services/etl/stages/resolve.js
|
|
130332
|
-
import
|
|
130434
|
+
import path27 from "path";
|
|
130333
130435
|
import fs18 from "fs";
|
|
130334
130436
|
|
|
130335
130437
|
class ResolveStage {
|
|
@@ -130354,7 +130456,7 @@ class ResolveStage {
|
|
|
130354
130456
|
const structuralDocuments = files.flatMap((file2) => {
|
|
130355
130457
|
if (!file2.structure)
|
|
130356
130458
|
return [];
|
|
130357
|
-
const language = resolveStructuralLanguage(
|
|
130459
|
+
const language = resolveStructuralLanguage(path27.extname(file2.file.relativePath));
|
|
130358
130460
|
if (language.status !== "supported")
|
|
130359
130461
|
throw new Error(`structural_manifest_missing:${file2.file.relativePath}`);
|
|
130360
130462
|
return [{
|
|
@@ -130366,13 +130468,13 @@ class ResolveStage {
|
|
|
130366
130468
|
}];
|
|
130367
130469
|
});
|
|
130368
130470
|
const currentStructuralFiles = new Set(structuralDocuments.map((document2) => document2.file));
|
|
130369
|
-
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));
|
|
130370
130472
|
const pathAliasesByFile = Object.fromEntries([...knownRelPaths].map((file2) => [
|
|
130371
130473
|
file2,
|
|
130372
130474
|
this.structuralAliasesFor(file2, rootAliases, monorepoPackages)
|
|
130373
130475
|
]));
|
|
130374
130476
|
const buildMetadata = { knownFiles: [...knownRelPaths], pathAliasesByFile };
|
|
130375
|
-
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));
|
|
130376
130478
|
const seedIds = new Set;
|
|
130377
130479
|
for (const definition of seedRows) {
|
|
130378
130480
|
if (seedIds.has(definition.id))
|
|
@@ -130469,7 +130571,7 @@ class ResolveStage {
|
|
|
130469
130571
|
if (parsed.file !== definition.file_path) {
|
|
130470
130572
|
throw new Error(`structural_repository_seed_file_mismatch:${definition.id}`);
|
|
130471
130573
|
}
|
|
130472
|
-
const language = resolveStructuralLanguage(
|
|
130574
|
+
const language = resolveStructuralLanguage(path27.extname(definition.file_path));
|
|
130473
130575
|
if (language.status !== "supported")
|
|
130474
130576
|
throw new Error(`structural_repository_seed_language:${definition.id}`);
|
|
130475
130577
|
let identity;
|
|
@@ -130521,7 +130623,7 @@ class ResolveStage {
|
|
|
130521
130623
|
});
|
|
130522
130624
|
}
|
|
130523
130625
|
resolveFile(parsed, projectPath, knownRelPaths, rootAliases, monorepoPackages, symbolIndex, knownFqns) {
|
|
130524
|
-
const fromDir =
|
|
130626
|
+
const fromDir = path27.dirname(path27.join(projectPath, parsed.file.relativePath));
|
|
130525
130627
|
const packageAliases = this.getPackageAliases(parsed.file.relativePath, monorepoPackages);
|
|
130526
130628
|
const allAliases = [...packageAliases, ...rootAliases];
|
|
130527
130629
|
const resolvedImports = parsed.rawImports.map((raw2) => {
|
|
@@ -130592,7 +130694,7 @@ class ResolveStage {
|
|
|
130592
130694
|
index.set(def.name, `${def.file_path}#${def.name}`);
|
|
130593
130695
|
}
|
|
130594
130696
|
} catch (err) {
|
|
130595
|
-
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()));
|
|
130596
130698
|
if (skippedStructural)
|
|
130597
130699
|
throw new Error("structural_repository_seed_failed", { cause: err });
|
|
130598
130700
|
logger.warn("buildSymbolIndex: repo seed failed, in-batch only", {
|
|
@@ -130616,7 +130718,7 @@ class ResolveStage {
|
|
|
130616
130718
|
}
|
|
130617
130719
|
resolveSpecifier(specifier, fromDir, projectPath, knownRelPaths, aliases) {
|
|
130618
130720
|
if (specifier.startsWith("./") || specifier.startsWith("../")) {
|
|
130619
|
-
const resolved = this.probeExtensions(
|
|
130721
|
+
const resolved = this.probeExtensions(path27.resolve(fromDir, specifier), projectPath, knownRelPaths);
|
|
130620
130722
|
return { resolvedPath: resolved, external: false };
|
|
130621
130723
|
}
|
|
130622
130724
|
for (const alias of aliases) {
|
|
@@ -130624,8 +130726,8 @@ class ResolveStage {
|
|
|
130624
130726
|
const suffix = specifier.slice(alias.prefix.length);
|
|
130625
130727
|
for (const target of alias.targets) {
|
|
130626
130728
|
const cleanTarget = target.replace(/\/\*$/, "");
|
|
130627
|
-
const basePath = alias.packagePath ?
|
|
130628
|
-
const absPath =
|
|
130729
|
+
const basePath = alias.packagePath ? path27.join(projectPath, alias.packagePath) : projectPath;
|
|
130730
|
+
const absPath = path27.join(basePath, cleanTarget + suffix);
|
|
130629
130731
|
const resolved = this.probeExtensions(absPath, projectPath, knownRelPaths);
|
|
130630
130732
|
if (resolved)
|
|
130631
130733
|
return { resolvedPath: resolved, external: false };
|
|
@@ -130641,7 +130743,7 @@ class ResolveStage {
|
|
|
130641
130743
|
...TS_EXTENSIONS.map((ext2) => absPath.replace(/\.[^.]+$/, ext2))
|
|
130642
130744
|
];
|
|
130643
130745
|
for (const candidate2 of candidates2) {
|
|
130644
|
-
const rel =
|
|
130746
|
+
const rel = path27.relative(projectPath, candidate2).replace(/\\/g, "/");
|
|
130645
130747
|
if (knownRelPaths.has(rel))
|
|
130646
130748
|
return rel;
|
|
130647
130749
|
}
|
|
@@ -130649,7 +130751,7 @@ class ResolveStage {
|
|
|
130649
130751
|
}
|
|
130650
130752
|
loadTsConfigPaths(projectPath, packageBase) {
|
|
130651
130753
|
const aliases = [];
|
|
130652
|
-
const tsconfigPath =
|
|
130754
|
+
const tsconfigPath = path27.join(projectPath, "tsconfig.json");
|
|
130653
130755
|
try {
|
|
130654
130756
|
const raw2 = fs18.readFileSync(tsconfigPath, "utf-8");
|
|
130655
130757
|
const stripped = raw2.replace(/\/\/[^\n]*/g, "").replace(/\/\*[\s\S]*?\*\//g, "");
|
|
@@ -130680,7 +130782,7 @@ class ResolveStage {
|
|
|
130680
130782
|
}
|
|
130681
130783
|
}
|
|
130682
130784
|
for (const packageRelPath of packagePaths) {
|
|
130683
|
-
const absPackagePath =
|
|
130785
|
+
const absPackagePath = path27.join(projectPath, packageRelPath);
|
|
130684
130786
|
const aliases = this.loadTsConfigPaths(absPackagePath, packageRelPath);
|
|
130685
130787
|
if (aliases.length > 0) {
|
|
130686
130788
|
packages.push({
|
|
@@ -130710,7 +130812,7 @@ class ResolveStage {
|
|
|
130710
130812
|
structuralAliasesFor(filePath, rootAliases, packages) {
|
|
130711
130813
|
return [...this.getPackageAliases(filePath, packages), ...rootAliases].map((alias) => ({
|
|
130712
130814
|
pattern: alias.prefix + (alias.targets.some((target) => target.includes("*")) ? "/*" : ""),
|
|
130713
|
-
targets: alias.targets.map((target) => alias.packagePath ?
|
|
130815
|
+
targets: alias.targets.map((target) => alias.packagePath ? path27.posix.join(alias.packagePath, target) : target)
|
|
130714
130816
|
}));
|
|
130715
130817
|
}
|
|
130716
130818
|
}
|
|
@@ -130774,7 +130876,7 @@ var init_with_deadlock_retry = __esm(() => {
|
|
|
130774
130876
|
});
|
|
130775
130877
|
|
|
130776
130878
|
// ../../packages/core/dist/services/etl/stages/load.js
|
|
130777
|
-
import
|
|
130879
|
+
import path28 from "path";
|
|
130778
130880
|
function formatDuration(ms) {
|
|
130779
130881
|
const totalSec = Math.max(0, Math.round(ms / 1000));
|
|
130780
130882
|
if (totalSec < 60)
|
|
@@ -131051,7 +131153,7 @@ class LoadStage {
|
|
|
131051
131153
|
const filePath = file2.file.relativePath;
|
|
131052
131154
|
const batch = buildSymbolPersistenceBatch(ctx.projectId, file2);
|
|
131053
131155
|
if (ctx.graphGenerationLease) {
|
|
131054
|
-
const manifest = getLanguageManifestEntry(
|
|
131156
|
+
const manifest = getLanguageManifestEntry(path28.extname(filePath));
|
|
131055
131157
|
const diagnostics2 = (file2.structuralDiagnostics ?? []).slice(0, 10).map((diagnostic2) => ({
|
|
131056
131158
|
code: diagnostic2.code,
|
|
131057
131159
|
severity: diagnostic2.severity,
|
|
@@ -131103,7 +131205,7 @@ var init_load = __esm(() => {
|
|
|
131103
131205
|
});
|
|
131104
131206
|
|
|
131105
131207
|
// ../../packages/core/dist/data/graph-generation/graph-generation-repository-pg.js
|
|
131106
|
-
import { randomUUID as
|
|
131208
|
+
import { randomUUID as randomUUID6 } from "crypto";
|
|
131107
131209
|
function boundedText2(value, label, max = 512) {
|
|
131108
131210
|
const normalized = value.normalize("NFC").trim();
|
|
131109
131211
|
if (!normalized || normalized.length > max || normalized.includes("\x00")) {
|
|
@@ -131207,8 +131309,8 @@ class GraphGenerationRepositoryPg {
|
|
|
131207
131309
|
}
|
|
131208
131310
|
async begin(rawInput) {
|
|
131209
131311
|
const input = validateBegin2(rawInput);
|
|
131210
|
-
const generationId =
|
|
131211
|
-
const leaseToken =
|
|
131312
|
+
const generationId = randomUUID6();
|
|
131313
|
+
const leaseToken = randomUUID6();
|
|
131212
131314
|
return getPrismaClient2().$transaction(async (tx) => {
|
|
131213
131315
|
const workspace = await lockWorkspace(tx, input.projectId);
|
|
131214
131316
|
if (workspace.active_graph_generation_id !== input.expectedActiveGenerationId) {
|
|
@@ -131448,8 +131550,8 @@ function buildGraphInputSnapshotHash(files) {
|
|
|
131448
131550
|
|
|
131449
131551
|
class GraphGenerationCoordinator {
|
|
131450
131552
|
repository;
|
|
131451
|
-
constructor(
|
|
131452
|
-
this.repository =
|
|
131553
|
+
constructor(repository2 = getGraphGenerationRepository()) {
|
|
131554
|
+
this.repository = repository2;
|
|
131453
131555
|
}
|
|
131454
131556
|
async begin(input) {
|
|
131455
131557
|
const deadline = Date.now() + GRAPH_GENERATION_LEASE_TTL_MS;
|
|
@@ -131505,609 +131607,6 @@ var init_graph_generation_coordinator = __esm(() => {
|
|
|
131505
131607
|
init_with_deadlock_retry();
|
|
131506
131608
|
});
|
|
131507
131609
|
|
|
131508
|
-
// ../../packages/core/dist/services/etl/pipeline.js
|
|
131509
|
-
import { createHash as createHash7 } from "crypto";
|
|
131510
|
-
import { setTimeout as delay2 } from "timers/promises";
|
|
131511
|
-
import path28 from "path";
|
|
131512
|
-
function buildHeaderLanguageEvidence(files) {
|
|
131513
|
-
const headers = new Set(files.filter((file2) => path28.posix.extname(file2.relativePath).toLowerCase() === ".h").map((file2) => path28.posix.normalize(file2.relativePath)));
|
|
131514
|
-
const mutable = new Map;
|
|
131515
|
-
const entry2 = (header) => {
|
|
131516
|
-
let value = mutable.get(header);
|
|
131517
|
-
if (!value) {
|
|
131518
|
-
value = { cImporters: new Set, cppImporters: new Set, build: new Set };
|
|
131519
|
-
mutable.set(header, value);
|
|
131520
|
-
}
|
|
131521
|
-
return value;
|
|
131522
|
-
};
|
|
131523
|
-
for (const file2 of files) {
|
|
131524
|
-
if (path28.posix.basename(file2.relativePath) !== "compile_commands.json" || file2.snapshotContent === undefined)
|
|
131525
|
-
continue;
|
|
131526
|
-
let commands;
|
|
131527
|
-
try {
|
|
131528
|
-
commands = JSON.parse(file2.snapshotContent);
|
|
131529
|
-
} catch {
|
|
131530
|
-
continue;
|
|
131531
|
-
}
|
|
131532
|
-
if (!Array.isArray(commands))
|
|
131533
|
-
continue;
|
|
131534
|
-
for (const command of commands) {
|
|
131535
|
-
if (!command || typeof command !== "object")
|
|
131536
|
-
continue;
|
|
131537
|
-
const record3 = command;
|
|
131538
|
-
if (typeof record3.file !== "string")
|
|
131539
|
-
continue;
|
|
131540
|
-
const projectRoot = path28.resolve(file2.absolutePath, ...file2.relativePath.split("/").map(() => ".."));
|
|
131541
|
-
const commandDirectory = typeof record3.directory === "string" ? path28.resolve(projectRoot, record3.directory) : projectRoot;
|
|
131542
|
-
const absoluteInput = path28.resolve(commandDirectory, record3.file);
|
|
131543
|
-
const relative2 = path28.relative(projectRoot, absoluteInput);
|
|
131544
|
-
const header = path28.posix.normalize(relative2.replaceAll(path28.sep, "/"));
|
|
131545
|
-
if (!headers.has(header))
|
|
131546
|
-
continue;
|
|
131547
|
-
const invocation = typeof record3.command === "string" ? record3.command : Array.isArray(record3.arguments) ? record3.arguments.join(" ") : "";
|
|
131548
|
-
if (/(?:^|\s)(?:clang\+\+|g\+\+|c\+\+)(?:\s|$)|(?:^|\s)-x\s*c\+\+(?:\s|$)/u.test(invocation))
|
|
131549
|
-
entry2(header).build.add("cpp");
|
|
131550
|
-
else if (/(?:^|\s)(?:clang|gcc|cc)(?:\s|$)|(?:^|\s)-x\s*c(?:\s|$)/u.test(invocation))
|
|
131551
|
-
entry2(header).build.add("c");
|
|
131552
|
-
}
|
|
131553
|
-
}
|
|
131554
|
-
return Object.freeze(Object.fromEntries([...mutable.entries()].sort(([a], [b]) => a.localeCompare(b)).map(([header, value]) => [header, Object.freeze({
|
|
131555
|
-
...value.cImporters.size ? { cImporters: Object.freeze([...value.cImporters].sort()) } : {},
|
|
131556
|
-
...value.cppImporters.size ? { cppImporters: Object.freeze([...value.cppImporters].sort()) } : {},
|
|
131557
|
-
...value.build.size ? { buildLanguage: value.build.size > 1 ? "conflict" : [...value.build][0] } : {}
|
|
131558
|
-
})])));
|
|
131559
|
-
}
|
|
131560
|
-
function abortable(operation, signal) {
|
|
131561
|
-
if (signal.aborted)
|
|
131562
|
-
return Promise.reject(signal.reason);
|
|
131563
|
-
return new Promise((resolve5, reject) => {
|
|
131564
|
-
let abortReason;
|
|
131565
|
-
const onAbort = () => {
|
|
131566
|
-
abortReason = signal.reason;
|
|
131567
|
-
};
|
|
131568
|
-
signal.addEventListener("abort", onAbort, { once: true });
|
|
131569
|
-
operation.then((value) => abortReason === undefined ? resolve5(value) : reject(abortReason), (error51) => reject(abortReason ?? error51)).finally(() => signal.removeEventListener("abort", onAbort));
|
|
131570
|
-
});
|
|
131571
|
-
}
|
|
131572
|
-
var EtlPipeline;
|
|
131573
|
-
var init_pipeline = __esm(() => {
|
|
131574
|
-
init_dist();
|
|
131575
|
-
init_discover();
|
|
131576
|
-
init_parse3();
|
|
131577
|
-
init_resolve();
|
|
131578
|
-
init_load();
|
|
131579
|
-
init_event_bus();
|
|
131580
|
-
init_symbol_repository_factory();
|
|
131581
|
-
init_index_job_tracker();
|
|
131582
|
-
init_cache_factory();
|
|
131583
|
-
init_index_manager();
|
|
131584
|
-
init_vector_store_factory();
|
|
131585
|
-
init_keyword_search_factory();
|
|
131586
|
-
init_alias_resolver();
|
|
131587
|
-
init_symbol_repo_workspace();
|
|
131588
|
-
init_project_indexer();
|
|
131589
|
-
init_parser_readiness();
|
|
131590
|
-
init_parse3();
|
|
131591
|
-
init_language_manifest();
|
|
131592
|
-
init_graph_generation_coordinator();
|
|
131593
|
-
init_managed_run_repository_pg();
|
|
131594
|
-
EtlPipeline = class EtlPipeline {
|
|
131595
|
-
static instance = null;
|
|
131596
|
-
static runTails = new Map;
|
|
131597
|
-
discover = new DiscoverStage;
|
|
131598
|
-
parse = new ParseStage;
|
|
131599
|
-
resolve = new ResolveStage;
|
|
131600
|
-
load = new LoadStage;
|
|
131601
|
-
graphGenerations = new GraphGenerationCoordinator;
|
|
131602
|
-
constructor() {}
|
|
131603
|
-
static getInstance() {
|
|
131604
|
-
if (!EtlPipeline.instance) {
|
|
131605
|
-
EtlPipeline.instance = new EtlPipeline;
|
|
131606
|
-
}
|
|
131607
|
-
return EtlPipeline.instance;
|
|
131608
|
-
}
|
|
131609
|
-
async run(input) {
|
|
131610
|
-
await assertParserReadyForIndexing();
|
|
131611
|
-
const projectId = await getProjectIdentityAliasResolver().resolve(input.projectId);
|
|
131612
|
-
const canonicalInput = projectId === input.projectId ? input : { ...input, projectId };
|
|
131613
|
-
const previous = EtlPipeline.runTails.get(projectId);
|
|
131614
|
-
let release;
|
|
131615
|
-
const tail = new Promise((resolve5) => {
|
|
131616
|
-
release = resolve5;
|
|
131617
|
-
});
|
|
131618
|
-
EtlPipeline.runTails.set(projectId, tail);
|
|
131619
|
-
if (previous) {
|
|
131620
|
-
logger.info("EtlPipeline: waiting for prior project run", {
|
|
131621
|
-
projectId,
|
|
131622
|
-
jobId: input.jobId
|
|
131623
|
-
});
|
|
131624
|
-
await previous;
|
|
131625
|
-
}
|
|
131626
|
-
try {
|
|
131627
|
-
return await this.runInternal(canonicalInput);
|
|
131628
|
-
} finally {
|
|
131629
|
-
if (EtlPipeline.runTails.get(projectId) === tail) {
|
|
131630
|
-
EtlPipeline.runTails.delete(projectId);
|
|
131631
|
-
}
|
|
131632
|
-
release();
|
|
131633
|
-
}
|
|
131634
|
-
}
|
|
131635
|
-
async runInternal(input, generationRetry = 0) {
|
|
131636
|
-
const projectId = await getProjectIdentityAliasResolver().resolve(input.projectId);
|
|
131637
|
-
const { projectPath, jobId, forceReindex = false, filesToProcess, include_tests = false, managedRunLease } = input;
|
|
131638
|
-
const t0 = performance.now();
|
|
131639
|
-
const stageTimings = {
|
|
131640
|
-
discover: 0,
|
|
131641
|
-
parse: 0,
|
|
131642
|
-
resolve: 0,
|
|
131643
|
-
load: 0
|
|
131644
|
-
};
|
|
131645
|
-
if (forceReindex) {
|
|
131646
|
-
const vectorStore = await getVectorStore();
|
|
131647
|
-
const keywordSearch = getKeywordSearch();
|
|
131648
|
-
await Promise.all([
|
|
131649
|
-
vectorStore.deleteByProject(projectId),
|
|
131650
|
-
keywordSearch.deleteByProject(projectId)
|
|
131651
|
-
]);
|
|
131652
|
-
}
|
|
131653
|
-
const managedRunRepository = managedRunLease ? ManagedRunRepositoryPg.getInstance() : undefined;
|
|
131654
|
-
const ctx = {
|
|
131655
|
-
projectId,
|
|
131656
|
-
projectPath,
|
|
131657
|
-
jobId,
|
|
131658
|
-
resumeCursor: managedRunLease ? (await managedRunRepository?.getActive(projectId, "indexing"))?.fileCursor ?? undefined : undefined,
|
|
131659
|
-
managedRunLease,
|
|
131660
|
-
emit: (event) => {
|
|
131661
|
-
if (event.type === "progress") {
|
|
131662
|
-
const p = event.payload;
|
|
131663
|
-
indexJobTracker.updateProgress(jobId, p.current, p.total);
|
|
131664
|
-
eventBus.publish("indexing:progress", {
|
|
131665
|
-
jobId,
|
|
131666
|
-
projectId,
|
|
131667
|
-
stage: event.stage,
|
|
131668
|
-
current: p.current,
|
|
131669
|
-
total: p.total,
|
|
131670
|
-
percentage: p.percentage
|
|
131671
|
-
});
|
|
131672
|
-
} else if (event.type === "file_error") {
|
|
131673
|
-
const p = event.payload;
|
|
131674
|
-
eventBus.publish("indexing:file", {
|
|
131675
|
-
jobId,
|
|
131676
|
-
projectId,
|
|
131677
|
-
filePath: p.filePath,
|
|
131678
|
-
stage: event.stage,
|
|
131679
|
-
status: "error",
|
|
131680
|
-
error: p.error
|
|
131681
|
-
});
|
|
131682
|
-
} else if (event.type === "file_processed") {
|
|
131683
|
-
const p = event.payload;
|
|
131684
|
-
eventBus.publish("indexing:file", {
|
|
131685
|
-
jobId,
|
|
131686
|
-
projectId,
|
|
131687
|
-
filePath: p.filePath,
|
|
131688
|
-
stage: event.stage,
|
|
131689
|
-
status: "ok"
|
|
131690
|
-
});
|
|
131691
|
-
}
|
|
131692
|
-
}
|
|
131693
|
-
};
|
|
131694
|
-
eventBus.publish("indexing:started", { jobId, projectId, projectPath });
|
|
131695
|
-
let graphGenerationLease;
|
|
131696
|
-
let graphHeartbeat;
|
|
131697
|
-
let graphHeartbeatFailure;
|
|
131698
|
-
const graphAbortController = new AbortController;
|
|
131699
|
-
const heartbeatTimerController = new AbortController;
|
|
131700
|
-
let stopGraphHeartbeat = false;
|
|
131701
|
-
let managedRunHeartbeat;
|
|
131702
|
-
let managedRunLeaseLost;
|
|
131703
|
-
let stopManagedRunHeartbeat = false;
|
|
131704
|
-
const managedRunTimerController = new AbortController;
|
|
131705
|
-
if (managedRunLease && managedRunRepository) {
|
|
131706
|
-
managedRunHeartbeat = (async () => {
|
|
131707
|
-
while (!stopManagedRunHeartbeat) {
|
|
131708
|
-
try {
|
|
131709
|
-
await delay2(30000, undefined, { signal: managedRunTimerController.signal });
|
|
131710
|
-
} catch {
|
|
131711
|
-
return;
|
|
131712
|
-
}
|
|
131713
|
-
if (stopManagedRunHeartbeat || !managedRunLease)
|
|
131714
|
-
return;
|
|
131715
|
-
try {
|
|
131716
|
-
const outcome2 = await managedRunRepository.heartbeat(managedRunLease);
|
|
131717
|
-
if (outcome2.status === "lease_lost") {
|
|
131718
|
-
managedRunLeaseLost = new Error("managed_run_lease_lost");
|
|
131719
|
-
graphAbortController.abort(managedRunLeaseLost);
|
|
131720
|
-
return;
|
|
131721
|
-
}
|
|
131722
|
-
} catch (heartbeatError) {
|
|
131723
|
-
managedRunLeaseLost = heartbeatError;
|
|
131724
|
-
graphAbortController.abort(managedRunLeaseLost);
|
|
131725
|
-
return;
|
|
131726
|
-
}
|
|
131727
|
-
}
|
|
131728
|
-
})();
|
|
131729
|
-
}
|
|
131730
|
-
try {
|
|
131731
|
-
const st1 = performance.now();
|
|
131732
|
-
const discoveredSnapshot = await this.discover.run(ctx, { forceReindex, includeTests: include_tests });
|
|
131733
|
-
ctx.structuralHeaderEvidenceByFile = buildHeaderLanguageEvidence(discoveredSnapshot);
|
|
131734
|
-
stageTimings.discover = Math.round(performance.now() - st1);
|
|
131735
|
-
const activeGraph = await getSymbolRepository().getActiveGraphSnapshot(projectId);
|
|
131736
|
-
try {
|
|
131737
|
-
graphGenerationLease = await this.graphGenerations.begin({
|
|
131738
|
-
projectId,
|
|
131739
|
-
expectedActiveGenerationId: activeGraph?.generationId ?? null,
|
|
131740
|
-
fingerprint: `sha256:${createHash7("sha256").update(JSON.stringify(STRUCTURAL_FINGERPRINT_INPUTS)).digest("hex")}`,
|
|
131741
|
-
inputSnapshotHash: buildGraphInputSnapshotHash(discoveredSnapshot),
|
|
131742
|
-
expectedFilesCount: discoveredSnapshot.length
|
|
131743
|
-
});
|
|
131744
|
-
} catch (beginError) {
|
|
131745
|
-
if (beginError.message.startsWith("graph_generation_stale_active:") && generationRetry < 3) {
|
|
131746
|
-
stopManagedRunHeartbeat = true;
|
|
131747
|
-
managedRunTimerController.abort();
|
|
131748
|
-
if (managedRunHeartbeat)
|
|
131749
|
-
await managedRunHeartbeat;
|
|
131750
|
-
return this.runInternal(input, generationRetry + 1);
|
|
131751
|
-
}
|
|
131752
|
-
throw beginError;
|
|
131753
|
-
}
|
|
131754
|
-
ctx.graphGenerationLease = graphGenerationLease;
|
|
131755
|
-
ctx.abortSignal = graphAbortController.signal;
|
|
131756
|
-
graphHeartbeat = (async () => {
|
|
131757
|
-
while (!stopGraphHeartbeat) {
|
|
131758
|
-
try {
|
|
131759
|
-
await delay2(30000, undefined, { signal: heartbeatTimerController.signal });
|
|
131760
|
-
} catch {
|
|
131761
|
-
return;
|
|
131762
|
-
}
|
|
131763
|
-
if (stopGraphHeartbeat || !graphGenerationLease)
|
|
131764
|
-
return;
|
|
131765
|
-
try {
|
|
131766
|
-
await this.graphGenerations.heartbeat(graphGenerationLease);
|
|
131767
|
-
} catch (heartbeatError) {
|
|
131768
|
-
graphHeartbeatFailure = heartbeatError;
|
|
131769
|
-
graphAbortController.abort(graphHeartbeatFailure);
|
|
131770
|
-
return;
|
|
131771
|
-
}
|
|
131772
|
-
}
|
|
131773
|
-
})();
|
|
131774
|
-
const requestedPaths = new Set(filesToProcess ?? []);
|
|
131775
|
-
const preparedFiles = discoveredSnapshot.map((file2) => ({
|
|
131776
|
-
...file2,
|
|
131777
|
-
needsReparse: forceReindex || !activeGraph || file2.needsReparse || requestedPaths.has(file2.relativePath)
|
|
131778
|
-
}));
|
|
131779
|
-
if (activeGraph) {
|
|
131780
|
-
for (const file2 of preparedFiles) {
|
|
131781
|
-
if (file2.needsReparse)
|
|
131782
|
-
continue;
|
|
131783
|
-
const copied = await getSymbolRepository().copyFileGeneration(graphGenerationLease, activeGraph.generationId, file2.relativePath);
|
|
131784
|
-
if (copied.status === "lease_lost")
|
|
131785
|
-
throw new Error("graph_generation_lease_lost");
|
|
131786
|
-
if (copied.status === "missing")
|
|
131787
|
-
file2.needsReparse = true;
|
|
131788
|
-
}
|
|
131789
|
-
}
|
|
131790
|
-
const discovered = preparedFiles.map((file2) => Object.freeze(file2));
|
|
131791
|
-
eventBus.publish("indexing:started", {
|
|
131792
|
-
jobId,
|
|
131793
|
-
projectId,
|
|
131794
|
-
projectPath,
|
|
131795
|
-
totalFiles: discovered.filter((f) => f.needsReparse).length
|
|
131796
|
-
});
|
|
131797
|
-
const st2 = performance.now();
|
|
131798
|
-
let remainingFiles = [...discovered];
|
|
131799
|
-
let parsed = [];
|
|
131800
|
-
const staleFailures = new Set;
|
|
131801
|
-
while (remainingFiles.length > 0) {
|
|
131802
|
-
try {
|
|
131803
|
-
parsed.push(...await abortable(this.parse.run(ctx, remainingFiles), graphAbortController.signal));
|
|
131804
|
-
break;
|
|
131805
|
-
} catch (parseError) {
|
|
131806
|
-
if (!activeGraph || forceReindex || !filesToProcess?.length || !(parseError instanceof StructuralEtlParseError) || staleFailures.has(parseError.filePath))
|
|
131807
|
-
throw parseError;
|
|
131808
|
-
staleFailures.add(parseError.filePath);
|
|
131809
|
-
const stale = await getSymbolRepository().markFileStaleGeneration(graphGenerationLease, parseError.filePath, {
|
|
131810
|
-
lastKnownGoodGenerationId: activeGraph.generationId,
|
|
131811
|
-
diagnostics: parseError.diagnostics.length > 0 ? parseError.diagnostics.slice(0, 10).map((diagnostic2) => ({ ...diagnostic2 })) : [{ code: "incremental_structural_failure", message: parseError.message }],
|
|
131812
|
-
parserErrorCount: parseError.diagnosticCount
|
|
131813
|
-
});
|
|
131814
|
-
if (stale.status !== "stale")
|
|
131815
|
-
throw parseError;
|
|
131816
|
-
remainingFiles = remainingFiles.filter((file2) => file2.relativePath !== parseError.filePath);
|
|
131817
|
-
}
|
|
131818
|
-
}
|
|
131819
|
-
if (graphHeartbeatFailure)
|
|
131820
|
-
throw graphHeartbeatFailure;
|
|
131821
|
-
if (managedRunLeaseLost)
|
|
131822
|
-
throw managedRunLeaseLost;
|
|
131823
|
-
stageTimings.parse = Math.round(performance.now() - st2);
|
|
131824
|
-
const st3 = performance.now();
|
|
131825
|
-
const resolved = await abortable(this.resolve.run(ctx, parsed), graphAbortController.signal);
|
|
131826
|
-
if (graphHeartbeatFailure)
|
|
131827
|
-
throw graphHeartbeatFailure;
|
|
131828
|
-
if (managedRunLeaseLost)
|
|
131829
|
-
throw managedRunLeaseLost;
|
|
131830
|
-
stageTimings.resolve = Math.round(performance.now() - st3);
|
|
131831
|
-
const st4 = performance.now();
|
|
131832
|
-
const loadResult = await abortable(this.load.run(ctx, resolved), graphAbortController.signal);
|
|
131833
|
-
if (graphHeartbeatFailure)
|
|
131834
|
-
throw graphHeartbeatFailure;
|
|
131835
|
-
if (managedRunLeaseLost)
|
|
131836
|
-
throw managedRunLeaseLost;
|
|
131837
|
-
stageTimings.load = Math.round(performance.now() - st4);
|
|
131838
|
-
if (loadResult.errors > 0) {
|
|
131839
|
-
logger.warn("EtlPipeline: completed with file errors", {
|
|
131840
|
-
projectId,
|
|
131841
|
-
jobId,
|
|
131842
|
-
errors: loadResult.errors,
|
|
131843
|
-
fileErrors: (loadResult.fileErrors ?? []).slice(0, 10)
|
|
131844
|
-
});
|
|
131845
|
-
}
|
|
131846
|
-
const activationSnapshot = await abortable(this.discover.run(ctx, { forceReindex, includeTests: include_tests }), graphAbortController.signal);
|
|
131847
|
-
if (buildGraphInputSnapshotHash(activationSnapshot) !== graphGenerationLease.inputSnapshotHash) {
|
|
131848
|
-
throw new Error("graph_generation_stale_snapshot");
|
|
131849
|
-
}
|
|
131850
|
-
if (graphHeartbeatFailure)
|
|
131851
|
-
throw graphHeartbeatFailure;
|
|
131852
|
-
if (managedRunLeaseLost)
|
|
131853
|
-
throw managedRunLeaseLost;
|
|
131854
|
-
stopGraphHeartbeat = true;
|
|
131855
|
-
heartbeatTimerController.abort();
|
|
131856
|
-
await graphHeartbeat;
|
|
131857
|
-
stopManagedRunHeartbeat = true;
|
|
131858
|
-
managedRunTimerController.abort();
|
|
131859
|
-
if (managedRunHeartbeat)
|
|
131860
|
-
await managedRunHeartbeat;
|
|
131861
|
-
const activatedGraph = await this.graphGenerations.activate(graphGenerationLease);
|
|
131862
|
-
const activeGraphSummary = await getSymbolRepository().getActiveGraphSnapshot(projectId);
|
|
131863
|
-
if (!activeGraphSummary || activeGraphSummary.generationId !== activatedGraph.generationId) {
|
|
131864
|
-
throw new Error("activated_graph_summary_mismatch");
|
|
131865
|
-
}
|
|
131866
|
-
const durationMs = Math.round(performance.now() - t0);
|
|
131867
|
-
const result = {
|
|
131868
|
-
filesDiscovered: discovered.length,
|
|
131869
|
-
filesIndexed: loadResult.filesLoaded,
|
|
131870
|
-
filesSkipped: discovered.filter((f) => !f.needsReparse).length,
|
|
131871
|
-
chunksIndexed: loadResult.chunksLoaded,
|
|
131872
|
-
symbolsIndexed: loadResult.symbolsLoaded,
|
|
131873
|
-
errors: loadResult.errors,
|
|
131874
|
-
durationMs,
|
|
131875
|
-
stageTimings,
|
|
131876
|
-
activatedGraphGenerationId: activatedGraph.generationId,
|
|
131877
|
-
parserDiagnostics: {
|
|
131878
|
-
diagnosticsCount: activeGraphSummary.diagnostics.errors,
|
|
131879
|
-
recoveredFiles: activeGraphSummary.diagnostics.recovered,
|
|
131880
|
-
hardFailureFiles: activeGraphSummary.diagnostics.hardFailures,
|
|
131881
|
-
staleFiles: activeGraphSummary.diagnostics.staleFiles,
|
|
131882
|
-
languages: activeGraphSummary.languages
|
|
131883
|
-
}
|
|
131884
|
-
};
|
|
131885
|
-
await getSearchCache().invalidateProject(projectId);
|
|
131886
|
-
try {
|
|
131887
|
-
const admissionMarker = new IndexManager(await getVectorStore());
|
|
131888
|
-
await admissionMarker.updateIndexMetadata(projectId, projectPath, discovered.map((file2) => file2.relativePath));
|
|
131889
|
-
} catch (markerError) {
|
|
131890
|
-
logger.warn("EtlPipeline: search-admission marker write failed", {
|
|
131891
|
-
projectId,
|
|
131892
|
-
jobId,
|
|
131893
|
-
error: markerError
|
|
131894
|
-
});
|
|
131895
|
-
}
|
|
131896
|
-
if (forceReindex) {
|
|
131897
|
-
const liveFingerprint = currentEmbeddingFingerprint();
|
|
131898
|
-
if (liveFingerprint !== null) {
|
|
131899
|
-
try {
|
|
131900
|
-
await stampEmbeddingFingerprint(projectId, liveFingerprint);
|
|
131901
|
-
} catch (stampError) {
|
|
131902
|
-
logger.warn("EtlPipeline: embedding fingerprint stamp failed", {
|
|
131903
|
-
projectId,
|
|
131904
|
-
jobId,
|
|
131905
|
-
error: stampError
|
|
131906
|
-
});
|
|
131907
|
-
}
|
|
131908
|
-
}
|
|
131909
|
-
}
|
|
131910
|
-
indexJobTracker.updateProgress(jobId, result.filesIndexed, result.filesIndexed);
|
|
131911
|
-
await indexJobTracker.setResultAndFlush(jobId, {
|
|
131912
|
-
filesIndexed: result.filesIndexed,
|
|
131913
|
-
chunksIndexed: result.chunksIndexed,
|
|
131914
|
-
errors: result.errors,
|
|
131915
|
-
fileErrors: loadResult.fileErrors ?? [],
|
|
131916
|
-
duration: durationMs,
|
|
131917
|
-
activatedGraphGenerationId: result.activatedGraphGenerationId,
|
|
131918
|
-
parserDiagnostics: result.parserDiagnostics
|
|
131919
|
-
});
|
|
131920
|
-
eventBus.publish("indexing:completed", {
|
|
131921
|
-
jobId,
|
|
131922
|
-
projectId,
|
|
131923
|
-
filesIndexed: result.filesIndexed,
|
|
131924
|
-
chunksIndexed: result.chunksIndexed,
|
|
131925
|
-
symbolsIndexed: result.symbolsIndexed,
|
|
131926
|
-
errors: result.errors,
|
|
131927
|
-
durationMs,
|
|
131928
|
-
activatedGraphGenerationId: result.activatedGraphGenerationId
|
|
131929
|
-
});
|
|
131930
|
-
await this.graphGenerations.cleanup(graphGenerationLease);
|
|
131931
|
-
stopGraphHeartbeat = true;
|
|
131932
|
-
heartbeatTimerController.abort();
|
|
131933
|
-
await graphHeartbeat;
|
|
131934
|
-
stopManagedRunHeartbeat = true;
|
|
131935
|
-
managedRunTimerController.abort();
|
|
131936
|
-
if (managedRunHeartbeat)
|
|
131937
|
-
await managedRunHeartbeat;
|
|
131938
|
-
if (managedRunLease && managedRunRepository) {
|
|
131939
|
-
try {
|
|
131940
|
-
await managedRunRepository.complete(managedRunLease);
|
|
131941
|
-
} catch (completeError) {
|
|
131942
|
-
logger.error("EtlPipeline: managed_runs complete failed", completeError, { projectId, jobId });
|
|
131943
|
-
}
|
|
131944
|
-
}
|
|
131945
|
-
logger.info("EtlPipeline: run completed", { projectId, jobId, ...result });
|
|
131946
|
-
return result;
|
|
131947
|
-
} catch (err) {
|
|
131948
|
-
const durationMs = Math.round(performance.now() - t0);
|
|
131949
|
-
const error51 = err.message;
|
|
131950
|
-
if (graphGenerationLease) {
|
|
131951
|
-
try {
|
|
131952
|
-
await this.graphGenerations.abort(graphGenerationLease, error51);
|
|
131953
|
-
} catch (abortError) {
|
|
131954
|
-
logger.error("EtlPipeline: pending generation abort failed", abortError, { projectId, jobId });
|
|
131955
|
-
}
|
|
131956
|
-
}
|
|
131957
|
-
stopGraphHeartbeat = true;
|
|
131958
|
-
heartbeatTimerController.abort();
|
|
131959
|
-
graphAbortController.abort();
|
|
131960
|
-
await graphHeartbeat;
|
|
131961
|
-
stopManagedRunHeartbeat = true;
|
|
131962
|
-
managedRunTimerController.abort();
|
|
131963
|
-
if (managedRunHeartbeat)
|
|
131964
|
-
await managedRunHeartbeat;
|
|
131965
|
-
if (managedRunLease && managedRunRepository) {
|
|
131966
|
-
try {
|
|
131967
|
-
const outcome2 = await managedRunRepository.abort(managedRunLease);
|
|
131968
|
-
if (outcome2.status === "lease_lost") {
|
|
131969
|
-
logger.warn("EtlPipeline: managed_runs abort saw lease_lost", { projectId, jobId });
|
|
131970
|
-
}
|
|
131971
|
-
} catch (abortError) {
|
|
131972
|
-
logger.error("EtlPipeline: managed_runs abort failed", abortError, { projectId, jobId });
|
|
131973
|
-
}
|
|
131974
|
-
}
|
|
131975
|
-
eventBus.publish("indexing:failed", { jobId, projectId, error: error51, durationMs });
|
|
131976
|
-
indexJobTracker.setResult(jobId, { filesIndexed: 0, chunksIndexed: 0, errors: 1, duration: durationMs }, error51);
|
|
131977
|
-
logger.error("EtlPipeline: run failed", err, { projectId, jobId, durationMs });
|
|
131978
|
-
throw err;
|
|
131979
|
-
}
|
|
131980
|
-
}
|
|
131981
|
-
};
|
|
131982
|
-
});
|
|
131983
|
-
|
|
131984
|
-
// ../../packages/core/dist/services/indexing/execute-indexing.js
|
|
131985
|
-
async function executeIndexing(request) {
|
|
131986
|
-
const { jobId, projectId, projectPath, forceReindex, warmCache, warmupQueries, include_tests = false, managedRunLease, warmupCache: warmupCache2 } = request;
|
|
131987
|
-
const startTime = Date.now();
|
|
131988
|
-
try {
|
|
131989
|
-
indexJobTracker.updateStatus(jobId, "running");
|
|
131990
|
-
logger.info("Starting project indexing via ETL Pipeline", {
|
|
131991
|
-
jobId,
|
|
131992
|
-
projectPath,
|
|
131993
|
-
projectId,
|
|
131994
|
-
forceReindex,
|
|
131995
|
-
warmCache,
|
|
131996
|
-
include_tests
|
|
131997
|
-
});
|
|
131998
|
-
const etlResult = await EtlPipeline.getInstance().run({
|
|
131999
|
-
projectId,
|
|
132000
|
-
projectPath,
|
|
132001
|
-
jobId,
|
|
132002
|
-
forceReindex,
|
|
132003
|
-
include_tests,
|
|
132004
|
-
managedRunLease
|
|
132005
|
-
});
|
|
132006
|
-
const duration3 = Date.now() - startTime;
|
|
132007
|
-
logger.info("ETL Pipeline completed", {
|
|
132008
|
-
jobId,
|
|
132009
|
-
projectId,
|
|
132010
|
-
duration: duration3,
|
|
132011
|
-
filesIndexed: etlResult.filesIndexed,
|
|
132012
|
-
filesSkipped: etlResult.filesSkipped,
|
|
132013
|
-
chunksIndexed: etlResult.chunksIndexed,
|
|
132014
|
-
symbolsIndexed: etlResult.symbolsIndexed,
|
|
132015
|
-
errors: etlResult.errors,
|
|
132016
|
-
stageTimings: etlResult.stageTimings
|
|
132017
|
-
});
|
|
132018
|
-
if (warmCache) {
|
|
132019
|
-
logger.info("Starting cache warmup", { jobId, projectId });
|
|
132020
|
-
const warmupStats = await warmupCache2(projectId, projectPath, warmupQueries);
|
|
132021
|
-
logger.info("Cache warmup completed", { jobId, projectId, ...warmupStats });
|
|
132022
|
-
}
|
|
132023
|
-
indexJobTracker.updateProgress(jobId, etlResult.filesIndexed, etlResult.filesIndexed);
|
|
132024
|
-
await indexJobTracker.setResultAndFlush(jobId, {
|
|
132025
|
-
filesIndexed: etlResult.filesIndexed,
|
|
132026
|
-
chunksIndexed: etlResult.chunksIndexed,
|
|
132027
|
-
errors: etlResult.errors,
|
|
132028
|
-
duration: duration3,
|
|
132029
|
-
activatedGraphGenerationId: etlResult.activatedGraphGenerationId,
|
|
132030
|
-
parserDiagnostics: etlResult.parserDiagnostics
|
|
132031
|
-
});
|
|
132032
|
-
} catch (error51) {
|
|
132033
|
-
const duration3 = Date.now() - startTime;
|
|
132034
|
-
logger.error("Project indexing failed", error51, {
|
|
132035
|
-
jobId,
|
|
132036
|
-
projectPath,
|
|
132037
|
-
projectId,
|
|
132038
|
-
duration: duration3
|
|
132039
|
-
});
|
|
132040
|
-
indexJobTracker.setResult(jobId, {
|
|
132041
|
-
filesIndexed: 0,
|
|
132042
|
-
chunksIndexed: 0,
|
|
132043
|
-
errors: 1,
|
|
132044
|
-
duration: duration3
|
|
132045
|
-
}, error51.message);
|
|
132046
|
-
}
|
|
132047
|
-
}
|
|
132048
|
-
var init_execute_indexing = __esm(() => {
|
|
132049
|
-
init_dist();
|
|
132050
|
-
init_index_job_tracker();
|
|
132051
|
-
init_pipeline();
|
|
132052
|
-
});
|
|
132053
|
-
|
|
132054
|
-
// ../../packages/core/dist/services/indexing/acquire-indexing-lease.js
|
|
132055
|
-
async function acquireIndexingLease(request) {
|
|
132056
|
-
const { jobId, projectId } = request;
|
|
132057
|
-
const eventId = `index:${jobId}`;
|
|
132058
|
-
const managedRunRepo = ManagedRunRepositoryPg.getInstance();
|
|
132059
|
-
try {
|
|
132060
|
-
const beginOutcome = await managedRunRepo.begin({
|
|
132061
|
-
projectId,
|
|
132062
|
-
runKind: "indexing",
|
|
132063
|
-
eventId
|
|
132064
|
-
});
|
|
132065
|
-
if (beginOutcome.status === "busy") {
|
|
132066
|
-
indexJobTracker.setResult(jobId, { filesIndexed: 0, chunksIndexed: 0, errors: 0, duration: 0 }, `indexing_busy:${beginOutcome.activeRunId}`);
|
|
132067
|
-
return {
|
|
132068
|
-
status: "busy",
|
|
132069
|
-
activeRunId: beginOutcome.activeRunId,
|
|
132070
|
-
leaseExpiresAt: beginOutcome.leaseExpiresAt
|
|
132071
|
-
};
|
|
132072
|
-
}
|
|
132073
|
-
return { status: "acquired", lease: beginOutcome.lease };
|
|
132074
|
-
} catch (beginError) {
|
|
132075
|
-
logger.error("managed_runs begin failed", beginError, {
|
|
132076
|
-
jobId,
|
|
132077
|
-
projectId
|
|
132078
|
-
});
|
|
132079
|
-
indexJobTracker.setResult(jobId, { filesIndexed: 0, chunksIndexed: 0, errors: 1, duration: 0 }, `managed_runs_begin_failed:${beginError.message}`);
|
|
132080
|
-
return { status: "failed", message: beginError.message };
|
|
132081
|
-
}
|
|
132082
|
-
}
|
|
132083
|
-
var init_acquire_indexing_lease = __esm(() => {
|
|
132084
|
-
init_dist();
|
|
132085
|
-
init_index_job_tracker();
|
|
132086
|
-
init_managed_run_repository_pg();
|
|
132087
|
-
});
|
|
132088
|
-
|
|
132089
|
-
// ../../packages/core/dist/services/project-identity/project-root-identity.js
|
|
132090
|
-
import { realpath as realpath2 } from "fs/promises";
|
|
132091
|
-
import path29 from "path";
|
|
132092
|
-
async function canonicalizeProjectRoot(projectPath, canonicalize = realpath2) {
|
|
132093
|
-
return canonicalize(path29.resolve(projectPath));
|
|
132094
|
-
}
|
|
132095
|
-
async function assertProjectRootReuse(options) {
|
|
132096
|
-
if (!options.storedProjectPath || options.forceReindex)
|
|
132097
|
-
return;
|
|
132098
|
-
const canonicalize = options.canonicalize ?? realpath2;
|
|
132099
|
-
let storedCanonical;
|
|
132100
|
-
try {
|
|
132101
|
-
storedCanonical = await canonicalize(path29.resolve(options.storedProjectPath));
|
|
132102
|
-
} catch {
|
|
132103
|
-
storedCanonical = path29.resolve(options.storedProjectPath);
|
|
132104
|
-
}
|
|
132105
|
-
if (storedCanonical !== options.canonicalProjectPath) {
|
|
132106
|
-
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");
|
|
132107
|
-
}
|
|
132108
|
-
}
|
|
132109
|
-
var init_project_root_identity = () => {};
|
|
132110
|
-
|
|
132111
131610
|
// ../../packages/core/dist/services/symbol/definition-lookup.js
|
|
132112
131611
|
function toSymbolIdentityResolution(result) {
|
|
132113
131612
|
switch (result.status) {
|
|
@@ -132128,8 +131627,8 @@ function toSymbolIdentityResolution(result) {
|
|
|
132128
131627
|
|
|
132129
131628
|
class DefinitionLookupService {
|
|
132130
131629
|
repository;
|
|
132131
|
-
constructor(
|
|
132132
|
-
this.repository =
|
|
131630
|
+
constructor(repository2 = getSymbolRepository) {
|
|
131631
|
+
this.repository = repository2;
|
|
132133
131632
|
}
|
|
132134
131633
|
async lookup(projectId, query) {
|
|
132135
131634
|
const repo = this.repository();
|
|
@@ -132843,16 +132342,16 @@ function detectRoutes(httpEdges, defs, opts = {}) {
|
|
|
132843
132342
|
const seen = new Set;
|
|
132844
132343
|
const out = [];
|
|
132845
132344
|
for (const e of httpEdges) {
|
|
132846
|
-
const
|
|
132847
|
-
if (!
|
|
132345
|
+
const path29 = e.route;
|
|
132346
|
+
if (!path29)
|
|
132848
132347
|
continue;
|
|
132849
132348
|
const method = (e.method ?? "ANY").toUpperCase();
|
|
132850
|
-
const key = method + " " +
|
|
132349
|
+
const key = method + " " + path29;
|
|
132851
132350
|
if (seen.has(key))
|
|
132852
132351
|
continue;
|
|
132853
132352
|
seen.add(key);
|
|
132854
132353
|
out.push({
|
|
132855
|
-
path:
|
|
132354
|
+
path: path29,
|
|
132856
132355
|
method: e.method,
|
|
132857
132356
|
file: e.fromFile,
|
|
132858
132357
|
handler: e.targetFqn ?? e.symbolName
|
|
@@ -132863,12 +132362,12 @@ function detectRoutes(httpEdges, defs, opts = {}) {
|
|
|
132863
132362
|
continue;
|
|
132864
132363
|
const parsed = parseRouteName(d.name);
|
|
132865
132364
|
const method = parsed?.method ?? "ANY";
|
|
132866
|
-
const
|
|
132867
|
-
const key = method + " " +
|
|
132365
|
+
const path29 = parsed?.path ?? d.name;
|
|
132366
|
+
const key = method + " " + path29;
|
|
132868
132367
|
if (seen.has(key))
|
|
132869
132368
|
continue;
|
|
132870
132369
|
seen.add(key);
|
|
132871
|
-
out.push({ path:
|
|
132370
|
+
out.push({ path: path29, method: parsed?.method, file: d.filePath, handler: d.name });
|
|
132872
132371
|
}
|
|
132873
132372
|
for (const d of defs) {
|
|
132874
132373
|
const parsed = parseRouteName(d.name);
|
|
@@ -133089,7 +132588,7 @@ __export(exports_symbol_graph_service, {
|
|
|
133089
132588
|
symbolGraphService: () => symbolGraphService,
|
|
133090
132589
|
SymbolGraphService: () => SymbolGraphService
|
|
133091
132590
|
});
|
|
133092
|
-
import
|
|
132591
|
+
import path29 from "path";
|
|
133093
132592
|
import fs19 from "fs/promises";
|
|
133094
132593
|
|
|
133095
132594
|
class SymbolGraphService {
|
|
@@ -133443,7 +132942,7 @@ class SymbolGraphService {
|
|
|
133443
132942
|
}
|
|
133444
132943
|
async resolveToAbsolute(relativePath, projectId) {
|
|
133445
132944
|
const root = await this.getProjectRoot(projectId);
|
|
133446
|
-
return root ?
|
|
132945
|
+
return root ? path29.resolve(root, relativePath) : relativePath;
|
|
133447
132946
|
}
|
|
133448
132947
|
async getProjectRoot(projectId) {
|
|
133449
132948
|
const cached2 = this.projectRootCache.get(projectId);
|
|
@@ -133557,7 +133056,7 @@ class WorkspaceManager {
|
|
|
133557
133056
|
return matches[0];
|
|
133558
133057
|
}
|
|
133559
133058
|
async removeWorkspace(projectId) {
|
|
133560
|
-
await getSymbolRepository().clearProject(projectId);
|
|
133059
|
+
await withHeavyWorkLease("maintenance", `workspace-remove:${projectId}`, () => getSymbolRepository().clearProject(projectId));
|
|
133561
133060
|
logger.info("WorkspaceManager: workspace removed", { projectId });
|
|
133562
133061
|
}
|
|
133563
133062
|
subscribeToEvents() {
|
|
@@ -133582,11 +133081,633 @@ var init_workspace_manager = __esm(() => {
|
|
|
133582
133081
|
init_symbol_repository_factory();
|
|
133583
133082
|
init_event_bus();
|
|
133584
133083
|
init_symbol_graph_service();
|
|
133084
|
+
init_heavy_work_lease();
|
|
133585
133085
|
workspaceManager = WorkspaceManager.getInstance();
|
|
133586
133086
|
});
|
|
133587
133087
|
|
|
133588
|
-
// ../../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";
|
|
133589
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";
|
|
133590
133711
|
|
|
133591
133712
|
class IndexProjectTool {
|
|
133592
133713
|
name = "index_project";
|
|
@@ -133634,7 +133755,7 @@ class IndexProjectTool {
|
|
|
133634
133755
|
try {
|
|
133635
133756
|
await assertParserReadyForIndexing();
|
|
133636
133757
|
const canonicalProjectPath = await canonicalizeProjectRoot(projectPath);
|
|
133637
|
-
const finalProjectId = projectId ||
|
|
133758
|
+
const finalProjectId = projectId || path32.basename(canonicalProjectPath) || "default";
|
|
133638
133759
|
const existing = await workspaceManager.getWorkspace(finalProjectId);
|
|
133639
133760
|
await assertProjectRootReuse({
|
|
133640
133761
|
projectId: finalProjectId,
|
|
@@ -134187,17 +134308,17 @@ function applyReplacer(root, replacer) {
|
|
|
134187
134308
|
return transformChildren(root, replacer, []);
|
|
134188
134309
|
return transformChildren(normalizeValue(replacedRoot), replacer, []);
|
|
134189
134310
|
}
|
|
134190
|
-
function transformChildren(value, replacer,
|
|
134311
|
+
function transformChildren(value, replacer, path33) {
|
|
134191
134312
|
if (isJsonObject(value))
|
|
134192
|
-
return transformObject(value, replacer,
|
|
134313
|
+
return transformObject(value, replacer, path33);
|
|
134193
134314
|
if (isJsonArray(value))
|
|
134194
|
-
return transformArray(value, replacer,
|
|
134315
|
+
return transformArray(value, replacer, path33);
|
|
134195
134316
|
return value;
|
|
134196
134317
|
}
|
|
134197
|
-
function transformObject(obj, replacer,
|
|
134318
|
+
function transformObject(obj, replacer, path33) {
|
|
134198
134319
|
const result = {};
|
|
134199
134320
|
for (const [key, value] of Object.entries(obj)) {
|
|
134200
|
-
const childPath = [...
|
|
134321
|
+
const childPath = [...path33, key];
|
|
134201
134322
|
const replacedValue = replacer(key, value, childPath);
|
|
134202
134323
|
if (replacedValue === undefined)
|
|
134203
134324
|
continue;
|
|
@@ -134205,11 +134326,11 @@ function transformObject(obj, replacer, path32) {
|
|
|
134205
134326
|
}
|
|
134206
134327
|
return result;
|
|
134207
134328
|
}
|
|
134208
|
-
function transformArray(arr, replacer,
|
|
134329
|
+
function transformArray(arr, replacer, path33) {
|
|
134209
134330
|
const result = [];
|
|
134210
134331
|
for (let i = 0;i < arr.length; i++) {
|
|
134211
134332
|
const value = arr[i];
|
|
134212
|
-
const childPath = [...
|
|
134333
|
+
const childPath = [...path33, i];
|
|
134213
134334
|
const replacedValue = replacer(String(i), value, childPath);
|
|
134214
134335
|
if (replacedValue === undefined)
|
|
134215
134336
|
continue;
|
|
@@ -135647,7 +135768,7 @@ __export(exports_memory_consolidation_job, {
|
|
|
135647
135768
|
memoryConsolidationJob: () => memoryConsolidationJob,
|
|
135648
135769
|
MemoryConsolidationJob: () => MemoryConsolidationJob
|
|
135649
135770
|
});
|
|
135650
|
-
import { randomUUID as
|
|
135771
|
+
import { randomUUID as randomUUID7 } from "crypto";
|
|
135651
135772
|
async function addSupercedesEdge(store3, newId, sourceId, batchId) {
|
|
135652
135773
|
const evidence = JSON.stringify({ batchId, consolidated: true });
|
|
135653
135774
|
await store3.createEdge({
|
|
@@ -135791,11 +135912,11 @@ class MemoryConsolidationJob {
|
|
|
135791
135912
|
});
|
|
135792
135913
|
return { merged: 0, batchesCreated: 0 };
|
|
135793
135914
|
}
|
|
135794
|
-
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);
|
|
135795
135916
|
if (!batch)
|
|
135796
135917
|
return { merged: 0, batchesCreated: 0 };
|
|
135797
135918
|
const sourceRows = candidates2.filter((c) => batch.sourceIds.includes(c.id));
|
|
135798
|
-
const newId = `mem-${now2}-${
|
|
135919
|
+
const newId = `mem-${now2}-${randomUUID7().slice(0, 8)}`;
|
|
135799
135920
|
const importance = sourceRows.length ? Math.min(1, Math.max(...sourceRows.map((r) => r.importance))) : 0.7;
|
|
135800
135921
|
const projectId = sourceRows.find((r) => r.project_id)?.project_id ?? null;
|
|
135801
135922
|
try {
|
|
@@ -139302,7 +139423,7 @@ var init_session_pin_store = __esm(() => {
|
|
|
139302
139423
|
// ../../packages/core/dist/services/hooks/attribution-resolver.js
|
|
139303
139424
|
import fs20 from "fs";
|
|
139304
139425
|
import os9 from "os";
|
|
139305
|
-
import
|
|
139426
|
+
import path33 from "path";
|
|
139306
139427
|
|
|
139307
139428
|
class PgWorkspaceRootProvider {
|
|
139308
139429
|
cache = null;
|
|
@@ -139352,7 +139473,7 @@ class AttributionResolver {
|
|
|
139352
139473
|
this.pins = options.pins ?? new SessionPinStore;
|
|
139353
139474
|
this.canonicalize = options.canonicalize ?? defaultCanonicalize;
|
|
139354
139475
|
this.homedir = options.homedir ?? os9.homedir;
|
|
139355
|
-
this.fsRoot = options.fsRoot ?? (() =>
|
|
139476
|
+
this.fsRoot = options.fsRoot ?? (() => path33.parse(path33.sep).root);
|
|
139356
139477
|
}
|
|
139357
139478
|
async resolve(input) {
|
|
139358
139479
|
const caller = input.callerProjectId;
|
|
@@ -139403,7 +139524,7 @@ class AttributionResolver {
|
|
|
139403
139524
|
}
|
|
139404
139525
|
let bestPath = null;
|
|
139405
139526
|
for (const candidate2 of byPath.keys()) {
|
|
139406
|
-
if (canonicalCwd === candidate2 || canonicalCwd.startsWith(candidate2.endsWith(
|
|
139527
|
+
if (canonicalCwd === candidate2 || canonicalCwd.startsWith(candidate2.endsWith(path33.sep) ? candidate2 : candidate2 + path33.sep)) {
|
|
139407
139528
|
if (bestPath === null || candidate2.length > bestPath.length) {
|
|
139408
139529
|
bestPath = candidate2;
|
|
139409
139530
|
}
|
|
@@ -139426,7 +139547,7 @@ class AttributionResolver {
|
|
|
139426
139547
|
return projectPath2;
|
|
139427
139548
|
const fsRoot = this.fsRoot();
|
|
139428
139549
|
let normalized = projectPath2;
|
|
139429
|
-
while (normalized.length > fsRoot.length && normalized.endsWith(
|
|
139550
|
+
while (normalized.length > fsRoot.length && normalized.endsWith(path33.sep)) {
|
|
139430
139551
|
normalized = normalized.slice(0, -1);
|
|
139431
139552
|
}
|
|
139432
139553
|
return normalized;
|
|
@@ -139437,7 +139558,7 @@ function defaultCanonicalize(cwd) {
|
|
|
139437
139558
|
return fs20.realpathSync(cwd);
|
|
139438
139559
|
} catch {
|
|
139439
139560
|
try {
|
|
139440
|
-
return
|
|
139561
|
+
return path33.resolve(cwd);
|
|
139441
139562
|
} catch {
|
|
139442
139563
|
return;
|
|
139443
139564
|
}
|
|
@@ -140186,31 +140307,31 @@ class TracePathService {
|
|
|
140186
140307
|
const chains = [];
|
|
140187
140308
|
const seen = new Set;
|
|
140188
140309
|
let walks = 0;
|
|
140189
|
-
const walk = (fqn,
|
|
140310
|
+
const walk = (fqn, path34) => {
|
|
140190
140311
|
if (chains.length >= CHAIN_CAP)
|
|
140191
140312
|
return;
|
|
140192
140313
|
if (walks >= MAX_WALKS)
|
|
140193
140314
|
return;
|
|
140194
140315
|
walks++;
|
|
140195
|
-
const key =
|
|
140316
|
+
const key = path34.join("\u2192");
|
|
140196
140317
|
if (seen.has(key))
|
|
140197
140318
|
return;
|
|
140198
140319
|
seen.add(key);
|
|
140199
140320
|
const next = adj.get(fqn);
|
|
140200
140321
|
if (!next || next.length === 0 || !whoHasChild.has(fqn)) {
|
|
140201
|
-
if (
|
|
140202
|
-
chains.push(
|
|
140322
|
+
if (path34.length > 1)
|
|
140323
|
+
chains.push(path34.map((n) => this.fqnToName(n)).join(" \u2192 "));
|
|
140203
140324
|
return;
|
|
140204
140325
|
}
|
|
140205
140326
|
for (const child of next) {
|
|
140206
140327
|
if (chains.length >= CHAIN_CAP || walks >= MAX_WALKS)
|
|
140207
140328
|
return;
|
|
140208
|
-
if (
|
|
140209
|
-
const cycled = [...
|
|
140329
|
+
if (path34.includes(child)) {
|
|
140330
|
+
const cycled = [...path34, `${this.fqnToName(child)}\u21BA`];
|
|
140210
140331
|
chains.push(cycled.map((n) => n).join(" \u2192 "));
|
|
140211
140332
|
continue;
|
|
140212
140333
|
}
|
|
140213
|
-
walk(child, [...
|
|
140334
|
+
walk(child, [...path34, child]);
|
|
140214
140335
|
}
|
|
140215
140336
|
};
|
|
140216
140337
|
for (const seed of seeds) {
|
|
@@ -141093,7 +141214,7 @@ var init_file_content_cache = __esm(() => {
|
|
|
141093
141214
|
});
|
|
141094
141215
|
|
|
141095
141216
|
// ../../packages/core/dist/services/file-read/file-metadata.js
|
|
141096
|
-
import
|
|
141217
|
+
import path34 from "path";
|
|
141097
141218
|
|
|
141098
141219
|
class FileMetadataExtractor {
|
|
141099
141220
|
symbolGraph;
|
|
@@ -141129,7 +141250,7 @@ class FileMetadataExtractor {
|
|
|
141129
141250
|
return metadata;
|
|
141130
141251
|
}
|
|
141131
141252
|
detectLanguage(filePath) {
|
|
141132
|
-
const ext2 =
|
|
141253
|
+
const ext2 = path34.extname(filePath).toLowerCase();
|
|
141133
141254
|
const languageMap2 = {
|
|
141134
141255
|
".ts": "TypeScript",
|
|
141135
141256
|
".tsx": "TypeScript",
|
|
@@ -141251,7 +141372,7 @@ var init_line_range = __esm(() => {
|
|
|
141251
141372
|
});
|
|
141252
141373
|
|
|
141253
141374
|
// ../../packages/core/dist/services/file-read/path-containment.js
|
|
141254
|
-
import
|
|
141375
|
+
import path35 from "path";
|
|
141255
141376
|
|
|
141256
141377
|
class PathContainment {
|
|
141257
141378
|
projectRoots;
|
|
@@ -141259,14 +141380,14 @@ class PathContainment {
|
|
|
141259
141380
|
this.projectRoots = projectRoots;
|
|
141260
141381
|
}
|
|
141261
141382
|
async resolveFilePath(filePath, projectId) {
|
|
141262
|
-
if (
|
|
141263
|
-
return
|
|
141383
|
+
if (path35.isAbsolute(filePath)) {
|
|
141384
|
+
return path35.resolve(filePath);
|
|
141264
141385
|
}
|
|
141265
141386
|
if (projectId) {
|
|
141266
141387
|
const root = await this.projectRoots.getProjectRoot(projectId);
|
|
141267
141388
|
if (root) {
|
|
141268
141389
|
const cleaned = sanitizeFilePath(filePath);
|
|
141269
|
-
return
|
|
141390
|
+
return path35.resolve(root, cleaned);
|
|
141270
141391
|
}
|
|
141271
141392
|
return null;
|
|
141272
141393
|
}
|
|
@@ -141277,17 +141398,17 @@ class PathContainment {
|
|
|
141277
141398
|
if (projectId) {
|
|
141278
141399
|
const root = await this.projectRoots.getProjectRoot(projectId);
|
|
141279
141400
|
if (root)
|
|
141280
|
-
roots.push(
|
|
141401
|
+
roots.push(path35.resolve(root));
|
|
141281
141402
|
}
|
|
141282
|
-
roots.push(
|
|
141403
|
+
roots.push(path35.resolve(process.cwd()));
|
|
141283
141404
|
const envRoots = (process.env.MASSA_AI_READ_FILE_ROOTS ?? "").split(":").map((s) => s.trim()).filter((s) => s.length > 0);
|
|
141284
141405
|
for (const extra of envRoots) {
|
|
141285
|
-
roots.push(
|
|
141406
|
+
roots.push(path35.resolve(extra));
|
|
141286
141407
|
}
|
|
141287
|
-
const target =
|
|
141408
|
+
const target = path35.resolve(absoluteFilePath);
|
|
141288
141409
|
for (const root of roots) {
|
|
141289
|
-
const rel =
|
|
141290
|
-
if (rel !== "" && !rel.startsWith("..") && !
|
|
141410
|
+
const rel = path35.relative(root, target);
|
|
141411
|
+
if (rel !== "" && !rel.startsWith("..") && !path35.isAbsolute(rel)) {
|
|
141291
141412
|
return { allowed: true };
|
|
141292
141413
|
}
|
|
141293
141414
|
if (rel === "")
|
|
@@ -144232,12 +144353,13 @@ function createProjectIdentityService(options = {}) {
|
|
|
144232
144353
|
}
|
|
144233
144354
|
},
|
|
144234
144355
|
apply(input) {
|
|
144235
|
-
return applyService.apply(input);
|
|
144356
|
+
return withHeavyWorkLease("maintenance", "project-identity", () => applyService.apply(input));
|
|
144236
144357
|
}
|
|
144237
144358
|
};
|
|
144238
144359
|
}
|
|
144239
144360
|
var init_service = __esm(() => {
|
|
144240
144361
|
init_db_connection();
|
|
144362
|
+
init_heavy_work_lease();
|
|
144241
144363
|
init_apply();
|
|
144242
144364
|
init_errors4();
|
|
144243
144365
|
init_planner();
|
|
@@ -144535,7 +144657,7 @@ var init_inference_probe = __esm(() => {
|
|
|
144535
144657
|
// ../../packages/core/dist/services/health/local-health-checker.js
|
|
144536
144658
|
import fs22 from "fs/promises";
|
|
144537
144659
|
import { existsSync as existsSync3 } from "fs";
|
|
144538
|
-
import
|
|
144660
|
+
import path36 from "path";
|
|
144539
144661
|
|
|
144540
144662
|
class LocalHealthChecker {
|
|
144541
144663
|
dataDir = config2.get("dataDir");
|
|
@@ -144614,7 +144736,7 @@ class LocalHealthChecker {
|
|
|
144614
144736
|
try {
|
|
144615
144737
|
if (!existsSync3(this.dataDir))
|
|
144616
144738
|
await fs22.mkdir(this.dataDir, { recursive: true });
|
|
144617
|
-
const probe2 =
|
|
144739
|
+
const probe2 = path36.join(this.dataDir, ".health-check-test");
|
|
144618
144740
|
await fs22.writeFile(probe2, "ok");
|
|
144619
144741
|
await fs22.unlink(probe2);
|
|
144620
144742
|
return { available: true, latency: Date.now() - start, details: { path: this.dataDir, writable: true } };
|
|
@@ -144960,6 +145082,9 @@ class PgScheduledJobStore {
|
|
|
144960
145082
|
}, "save");
|
|
144961
145083
|
this.ensureHydrated();
|
|
144962
145084
|
}
|
|
145085
|
+
async ready() {
|
|
145086
|
+
await this.ensureHydrated();
|
|
145087
|
+
}
|
|
144963
145088
|
get(id) {
|
|
144964
145089
|
this.ensureHydrated();
|
|
144965
145090
|
return this.mirror.get(id) ?? null;
|
|
@@ -145036,10 +145161,18 @@ class Scheduler {
|
|
|
145036
145161
|
handlers = new Map;
|
|
145037
145162
|
cronCache = new Map;
|
|
145038
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;
|
|
145039
145171
|
timer = null;
|
|
145040
145172
|
started = false;
|
|
145041
145173
|
constructor(opts = {}) {
|
|
145042
145174
|
this.store = opts.store ?? getScheduledJobStore();
|
|
145175
|
+
this.heavyWorkProbe = opts.heavyWorkProbe ?? probeHeavyWork;
|
|
145043
145176
|
const schedulerConfig = config2.get("scheduler");
|
|
145044
145177
|
this.tickIntervalMs = opts.tickIntervalMs ?? envPositiveInt(process.env.MASSA_AI_SCHEDULER_TICK_MS) ?? schedulerConfig?.tickMs ?? DEFAULTS.tickMs;
|
|
145045
145178
|
this.maxConcurrent = opts.maxConcurrent ?? envPositiveInt(process.env.MASSA_AI_SCHEDULER_MAX_CONCURRENT) ?? schedulerConfig?.maxConcurrent ?? DEFAULTS.maxConcurrent;
|
|
@@ -145140,31 +145273,43 @@ class Scheduler {
|
|
|
145140
145273
|
this.timer.unref?.();
|
|
145141
145274
|
this.tick().catch(() => {});
|
|
145142
145275
|
}
|
|
145143
|
-
catchUpMissedJobs(now2 = Date.now()) {
|
|
145144
|
-
if (!this.enabled)
|
|
145145
|
-
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) {
|
|
145146
145287
|
const jobs = this.store.listEnabled();
|
|
145147
|
-
let caughtUp = 0;
|
|
145148
145288
|
let skipped = 0;
|
|
145289
|
+
const missed = [];
|
|
145149
145290
|
for (const job of jobs) {
|
|
145150
145291
|
if (this.running.has(job.jobKind)) {
|
|
145151
145292
|
skipped++;
|
|
145152
145293
|
continue;
|
|
145153
145294
|
}
|
|
145154
|
-
|
|
145155
|
-
|
|
145156
|
-
|
|
145157
|
-
|
|
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) {
|
|
145158
145304
|
logger.info("Scheduler: catch-up tick for missed job", {
|
|
145159
145305
|
id: job.id,
|
|
145160
145306
|
name: job.name,
|
|
145161
145307
|
jobKind: job.jobKind,
|
|
145162
|
-
overdueMs
|
|
145308
|
+
overdueMs: now2 - job.nextRunAt
|
|
145163
145309
|
});
|
|
145164
145310
|
this.fireJob(job, now2);
|
|
145165
|
-
caughtUp++;
|
|
145166
145311
|
}
|
|
145167
|
-
return { caughtUp, skipped };
|
|
145312
|
+
return { caughtUp: missed.length, skipped, deferred: 0 };
|
|
145168
145313
|
}
|
|
145169
145314
|
stop() {
|
|
145170
145315
|
if (this.timer) {
|
|
@@ -145172,17 +145317,47 @@ class Scheduler {
|
|
|
145172
145317
|
this.timer = null;
|
|
145173
145318
|
}
|
|
145174
145319
|
this.started = false;
|
|
145320
|
+
this.pendingTickAt = null;
|
|
145175
145321
|
logger.info("Scheduler stopped");
|
|
145176
145322
|
}
|
|
145177
145323
|
isRunning() {
|
|
145178
145324
|
return this.started && this.timer !== null;
|
|
145179
145325
|
}
|
|
145180
145326
|
async tick(now2 = Date.now()) {
|
|
145181
|
-
const result = { evaluated: 0, fired: 0, skipped: 0, errors: 0 };
|
|
145327
|
+
const result = { evaluated: 0, fired: 0, skipped: 0, errors: 0, deferred: 0 };
|
|
145182
145328
|
if (!this.enabled)
|
|
145183
145329
|
return result;
|
|
145184
|
-
|
|
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();
|
|
145185
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
|
+
}
|
|
145186
145361
|
for (const job of jobs) {
|
|
145187
145362
|
if (this.running.has(job.jobKind)) {
|
|
145188
145363
|
result.skipped++;
|
|
@@ -145192,7 +145367,7 @@ class Scheduler {
|
|
|
145192
145367
|
continue;
|
|
145193
145368
|
}
|
|
145194
145369
|
const overdueMs = now2 - job.nextRunAt;
|
|
145195
|
-
const isMissed = overdueMs > this.tickIntervalMs;
|
|
145370
|
+
const isMissed = overdueMs > this.tickIntervalMs && !this.deferred.has(job.id);
|
|
145196
145371
|
if (isMissed) {
|
|
145197
145372
|
logger.warn("Scheduler: missed run (skipping, rescheduling)", {
|
|
145198
145373
|
id: job.id,
|
|
@@ -145214,7 +145389,42 @@ class Scheduler {
|
|
|
145214
145389
|
}
|
|
145215
145390
|
return result;
|
|
145216
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
|
+
}
|
|
145217
145426
|
fireJob(job, firedAt) {
|
|
145427
|
+
this.deferred.delete(job.id);
|
|
145218
145428
|
const handler = this.handlers.get(job.jobKind);
|
|
145219
145429
|
if (!handler) {
|
|
145220
145430
|
logger.warn("Scheduler: no handler registered for jobKind", {
|
|
@@ -145274,6 +145484,9 @@ class Scheduler {
|
|
|
145274
145484
|
}
|
|
145275
145485
|
})();
|
|
145276
145486
|
}
|
|
145487
|
+
async ready() {
|
|
145488
|
+
await this.store.ready?.();
|
|
145489
|
+
}
|
|
145277
145490
|
status(now2 = Date.now()) {
|
|
145278
145491
|
const jobs = this.store.listAll();
|
|
145279
145492
|
return {
|
|
@@ -145288,10 +145501,17 @@ class Scheduler {
|
|
|
145288
145501
|
nextRunAt: j.nextRunAt,
|
|
145289
145502
|
lastRunAt: j.lastRunAt,
|
|
145290
145503
|
lastSuccessAt: j.lastSuccessAt ?? null,
|
|
145504
|
+
lastFailureAt: j.lastFailureAt ?? null,
|
|
145291
145505
|
consecutiveFailures: j.consecutiveFailures ?? 0,
|
|
145506
|
+
lastError: j.lastError ?? null,
|
|
145292
145507
|
due: j.enabled && j.nextRunAt <= now2,
|
|
145293
|
-
currentlyRunning: this.running.has(j.jobKind)
|
|
145294
|
-
|
|
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
|
+
}
|
|
145295
145515
|
};
|
|
145296
145516
|
}
|
|
145297
145517
|
isJobRunning(jobKind) {
|
|
@@ -145310,12 +145530,13 @@ function resetScheduler() {
|
|
|
145310
145530
|
}
|
|
145311
145531
|
resetScheduledJobStore();
|
|
145312
145532
|
}
|
|
145313
|
-
var DEFAULTS, cachedScheduler = null;
|
|
145533
|
+
var DEFAULTS, PROBE_FAILURE_WARN_EVERY = 5, cachedScheduler = null;
|
|
145314
145534
|
var init_scheduler = __esm(() => {
|
|
145315
145535
|
init_dist();
|
|
145316
145536
|
init_config();
|
|
145317
145537
|
init_scheduler_cron();
|
|
145318
145538
|
init_scheduler_store_factory();
|
|
145539
|
+
init_heavy_work_lease();
|
|
145319
145540
|
DEFAULTS = {
|
|
145320
145541
|
tickMs: 60000,
|
|
145321
145542
|
maxConcurrent: 2
|
|
@@ -146004,7 +146225,7 @@ var init_auto_improve_llm = __esm(() => {
|
|
|
146004
146225
|
});
|
|
146005
146226
|
|
|
146006
146227
|
// ../../packages/core/dist/services/jobs/auto-improve-apply.js
|
|
146007
|
-
import { randomUUID as
|
|
146228
|
+
import { randomUUID as randomUUID8 } from "crypto";
|
|
146008
146229
|
function validateCreatePayload(p) {
|
|
146009
146230
|
if ("type" in p && p.type !== undefined && p.type !== null) {
|
|
146010
146231
|
if (typeof p.type !== "string" || !VALID_MEMORY_TYPES.has(p.type)) {
|
|
@@ -146045,7 +146266,7 @@ function buildUpdatePatch(p) {
|
|
|
146045
146266
|
return patch;
|
|
146046
146267
|
}
|
|
146047
146268
|
async function applyProposal(job, record3) {
|
|
146048
|
-
const memId = record3.targetMemoryId ?? `proposal-mem-${record3.id}-${
|
|
146269
|
+
const memId = record3.targetMemoryId ?? `proposal-mem-${record3.id}-${randomUUID8().slice(0, 8)}`;
|
|
146049
146270
|
const p = record3.payload;
|
|
146050
146271
|
if (record3.kind === "memory.create") {
|
|
146051
146272
|
validateCreatePayload(p);
|
|
@@ -146312,8 +146533,8 @@ __export(exports_auto_improve_job, {
|
|
|
146312
146533
|
|
|
146313
146534
|
class AutoImproveJob {
|
|
146314
146535
|
llm;
|
|
146315
|
-
|
|
146316
|
-
|
|
146536
|
+
injectedObservationStore;
|
|
146537
|
+
injectedProposalStore;
|
|
146317
146538
|
memoryRepo;
|
|
146318
146539
|
thresholds;
|
|
146319
146540
|
minObservations;
|
|
@@ -146324,10 +146545,16 @@ class AutoImproveJob {
|
|
|
146324
146545
|
lastRunAt = 0;
|
|
146325
146546
|
newSinceRun = 0;
|
|
146326
146547
|
runCalls = 0;
|
|
146548
|
+
get observationStore() {
|
|
146549
|
+
return this.injectedObservationStore ?? getObservationStore();
|
|
146550
|
+
}
|
|
146551
|
+
get proposalStore() {
|
|
146552
|
+
return this.injectedProposalStore ?? getProposalStore();
|
|
146553
|
+
}
|
|
146327
146554
|
constructor(opts = {}) {
|
|
146328
146555
|
this.llm = opts.llm ?? llm;
|
|
146329
|
-
this.
|
|
146330
|
-
this.
|
|
146556
|
+
this.injectedObservationStore = opts.observationStore;
|
|
146557
|
+
this.injectedProposalStore = opts.proposalStore;
|
|
146331
146558
|
this.thresholds = { ...DEFAULT_THRESHOLDS, ...opts.thresholds };
|
|
146332
146559
|
this.reviewGateOverride = opts.reviewGate;
|
|
146333
146560
|
this.idFactory = opts.idFactory ?? (() => newProposalId());
|
|
@@ -146407,7 +146634,7 @@ __export(exports_observation_consolidation_job, {
|
|
|
146407
146634
|
observationConsolidationJob: () => observationConsolidationJob,
|
|
146408
146635
|
ObservationConsolidationJob: () => ObservationConsolidationJob
|
|
146409
146636
|
});
|
|
146410
|
-
import { randomUUID as
|
|
146637
|
+
import { randomUUID as randomUUID9 } from "crypto";
|
|
146411
146638
|
function readBridgeConfig() {
|
|
146412
146639
|
try {
|
|
146413
146640
|
const c = config2.get("hooks")?.bridge;
|
|
@@ -146425,7 +146652,7 @@ function readBridgeConfig() {
|
|
|
146425
146652
|
|
|
146426
146653
|
class ObservationConsolidationJob {
|
|
146427
146654
|
llm;
|
|
146428
|
-
|
|
146655
|
+
injectedStore;
|
|
146429
146656
|
memoryRepo;
|
|
146430
146657
|
minObservations;
|
|
146431
146658
|
minIntervalMs;
|
|
@@ -146433,9 +146660,12 @@ class ObservationConsolidationJob {
|
|
|
146433
146660
|
lastRunAt = 0;
|
|
146434
146661
|
newSinceRun = 0;
|
|
146435
146662
|
runCalls = 0;
|
|
146663
|
+
get store() {
|
|
146664
|
+
return this.injectedStore ?? getObservationStore();
|
|
146665
|
+
}
|
|
146436
146666
|
constructor(opts = {}) {
|
|
146437
146667
|
this.llm = opts.llm ?? llm;
|
|
146438
|
-
this.
|
|
146668
|
+
this.injectedStore = opts.store;
|
|
146439
146669
|
const injected = opts.memoryRepo;
|
|
146440
146670
|
this.memoryRepo = injected ?? { insert: (i) => getMemoryRepository().insert(i) };
|
|
146441
146671
|
const cfg = readBridgeConfig();
|
|
@@ -146497,7 +146727,7 @@ class ObservationConsolidationJob {
|
|
|
146497
146727
|
if (observations.length < 2)
|
|
146498
146728
|
return noop2;
|
|
146499
146729
|
const window2 = observations.slice(0, this.maxWindow);
|
|
146500
|
-
const batchId = `obs-batch-${Date.now()}-${
|
|
146730
|
+
const batchId = `obs-batch-${Date.now()}-${randomUUID9().slice(0, 8)}`;
|
|
146501
146731
|
const prompt = buildObservationPrompt(window2);
|
|
146502
146732
|
let batch;
|
|
146503
146733
|
try {
|
|
@@ -146523,7 +146753,7 @@ class ObservationConsolidationJob {
|
|
|
146523
146753
|
}
|
|
146524
146754
|
if (!batch)
|
|
146525
146755
|
return noop2;
|
|
146526
|
-
const newId = `mem-${Date.now()}-${
|
|
146756
|
+
const newId = `mem-${Date.now()}-${randomUUID9().slice(0, 8)}`;
|
|
146527
146757
|
const importance = 0.7;
|
|
146528
146758
|
try {
|
|
146529
146759
|
await Promise.resolve(this.memoryRepo.insert({
|
|
@@ -146755,7 +146985,7 @@ var init_scheduler2 = __esm(() => {
|
|
|
146755
146985
|
// ../../packages/core/dist/services/pricing/models-dev-client.js
|
|
146756
146986
|
import fs23 from "fs/promises";
|
|
146757
146987
|
import { existsSync as existsSync4 } from "fs";
|
|
146758
|
-
import
|
|
146988
|
+
import path37 from "path";
|
|
146759
146989
|
function getModelsDevClient() {
|
|
146760
146990
|
if (!clientInstance) {
|
|
146761
146991
|
clientInstance = new ModelsDevClient;
|
|
@@ -146775,7 +147005,7 @@ var init_models_dev_client = __esm(() => {
|
|
|
146775
147005
|
memoryCacheTimestamp = 0;
|
|
146776
147006
|
getLocalCachePath() {
|
|
146777
147007
|
const dataDir = config2.get("dataDir");
|
|
146778
|
-
return
|
|
147008
|
+
return path37.join(dataDir, ModelsDevClient.LOCAL_CACHE_FILE);
|
|
146779
147009
|
}
|
|
146780
147010
|
async loadLocalCache() {
|
|
146781
147011
|
const cachePath = this.getLocalCachePath();
|
|
@@ -146810,7 +147040,7 @@ var init_models_dev_client = __esm(() => {
|
|
|
146810
147040
|
async saveLocalCache(models) {
|
|
146811
147041
|
const cachePath = this.getLocalCachePath();
|
|
146812
147042
|
try {
|
|
146813
|
-
const dir =
|
|
147043
|
+
const dir = path37.dirname(cachePath);
|
|
146814
147044
|
await fs23.mkdir(dir, { recursive: true });
|
|
146815
147045
|
const data = {
|
|
146816
147046
|
timestamp: Date.now(),
|
|
@@ -152706,33 +152936,33 @@ var require_URL = __commonJS((exports, module) => {
|
|
|
152706
152936
|
else
|
|
152707
152937
|
return basepath.substring(0, lastslash + 1) + refpath;
|
|
152708
152938
|
}
|
|
152709
|
-
function remove_dot_segments(
|
|
152710
|
-
if (!
|
|
152711
|
-
return
|
|
152939
|
+
function remove_dot_segments(path38) {
|
|
152940
|
+
if (!path38)
|
|
152941
|
+
return path38;
|
|
152712
152942
|
var output = "";
|
|
152713
|
-
while (
|
|
152714
|
-
if (
|
|
152715
|
-
|
|
152943
|
+
while (path38.length > 0) {
|
|
152944
|
+
if (path38 === "." || path38 === "..") {
|
|
152945
|
+
path38 = "";
|
|
152716
152946
|
break;
|
|
152717
152947
|
}
|
|
152718
|
-
var twochars =
|
|
152719
|
-
var threechars =
|
|
152720
|
-
var fourchars =
|
|
152948
|
+
var twochars = path38.substring(0, 2);
|
|
152949
|
+
var threechars = path38.substring(0, 3);
|
|
152950
|
+
var fourchars = path38.substring(0, 4);
|
|
152721
152951
|
if (threechars === "../") {
|
|
152722
|
-
|
|
152952
|
+
path38 = path38.substring(3);
|
|
152723
152953
|
} else if (twochars === "./") {
|
|
152724
|
-
|
|
152954
|
+
path38 = path38.substring(2);
|
|
152725
152955
|
} else if (threechars === "/./") {
|
|
152726
|
-
|
|
152727
|
-
} else if (twochars === "/." &&
|
|
152728
|
-
|
|
152729
|
-
} else if (fourchars === "/../" || threechars === "/.." &&
|
|
152730
|
-
|
|
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);
|
|
152731
152961
|
output = output.replace(/\/?[^\/]*$/, "");
|
|
152732
152962
|
} else {
|
|
152733
|
-
var segment =
|
|
152963
|
+
var segment = path38.match(/(\/?([^\/]*))/)[0];
|
|
152734
152964
|
output += segment;
|
|
152735
|
-
|
|
152965
|
+
path38 = path38.substring(segment.length);
|
|
152736
152966
|
}
|
|
152737
152967
|
}
|
|
152738
152968
|
return output;
|
|
@@ -164802,21 +165032,21 @@ function jsonToKeyPathChunks(value, label = "$") {
|
|
|
164802
165032
|
walk(value, label, out);
|
|
164803
165033
|
return out;
|
|
164804
165034
|
}
|
|
164805
|
-
function walk(val,
|
|
165035
|
+
function walk(val, path38, out) {
|
|
164806
165036
|
if (val === null || val === undefined)
|
|
164807
165037
|
return;
|
|
164808
165038
|
if (Array.isArray(val)) {
|
|
164809
165039
|
if (val.length === 0) {
|
|
164810
|
-
out.push({ path:
|
|
165040
|
+
out.push({ path: path38, content: `**${path38}** = _[]_` });
|
|
164811
165041
|
return;
|
|
164812
165042
|
}
|
|
164813
165043
|
if (val.every((v) => v !== null && typeof v === "object")) {
|
|
164814
|
-
val.forEach((v, i) => walk(v, `${
|
|
165044
|
+
val.forEach((v, i) => walk(v, `${path38}[${i}]`, out));
|
|
164815
165045
|
return;
|
|
164816
165046
|
}
|
|
164817
165047
|
const items = val.map((v) => `- \`${String(v)}\``).join(`
|
|
164818
165048
|
`);
|
|
164819
|
-
out.push({ path:
|
|
165049
|
+
out.push({ path: path38, content: `**${path38}**
|
|
164820
165050
|
|
|
164821
165051
|
${items}` });
|
|
164822
165052
|
return;
|
|
@@ -164824,16 +165054,16 @@ ${items}` });
|
|
|
164824
165054
|
if (typeof val === "object") {
|
|
164825
165055
|
const entries = Object.entries(val);
|
|
164826
165056
|
if (entries.length === 0) {
|
|
164827
|
-
out.push({ path:
|
|
165057
|
+
out.push({ path: path38, content: `**${path38}** = _{}_` });
|
|
164828
165058
|
return;
|
|
164829
165059
|
}
|
|
164830
165060
|
for (const [k, v] of entries) {
|
|
164831
165061
|
const safeKey = /^[A-Za-z_$][\w$]*$/.test(k) ? k : JSON.stringify(k);
|
|
164832
|
-
walk(v, `${
|
|
165062
|
+
walk(v, `${path38}.${safeKey}`, out);
|
|
164833
165063
|
}
|
|
164834
165064
|
return;
|
|
164835
165065
|
}
|
|
164836
|
-
out.push({ path:
|
|
165066
|
+
out.push({ path: path38, content: `**${path38}** = \`${String(val)}\`` });
|
|
164837
165067
|
}
|
|
164838
165068
|
var gfm, STRIP_SELECTORS, tdCache = null;
|
|
164839
165069
|
var init_html_to_md = __esm(() => {
|
|
@@ -165173,6 +165403,7 @@ var init_services = __esm(() => {
|
|
|
165173
165403
|
init_embeddings();
|
|
165174
165404
|
init_local_health_checker();
|
|
165175
165405
|
init_index_job_tracker();
|
|
165406
|
+
init_heavy_work_lease();
|
|
165176
165407
|
init_scheduler2();
|
|
165177
165408
|
init_models_dev_client();
|
|
165178
165409
|
init_memory_graph_service();
|
|
@@ -165599,9 +165830,9 @@ var init_hook_service = __esm(() => {
|
|
|
165599
165830
|
});
|
|
165600
165831
|
|
|
165601
165832
|
// ../../packages/core/dist/services/bootstrap/bootstrap-service.js
|
|
165602
|
-
import { randomUUID as
|
|
165833
|
+
import { randomUUID as randomUUID10 } from "crypto";
|
|
165603
165834
|
import fs24 from "fs";
|
|
165604
|
-
import
|
|
165835
|
+
import path38 from "path";
|
|
165605
165836
|
import { spawn as spawn2 } from "child_process";
|
|
165606
165837
|
function readBootstrapConfig() {
|
|
165607
165838
|
try {
|
|
@@ -165701,7 +165932,7 @@ class BootstrapService {
|
|
|
165701
165932
|
return { ...noopResult("no-signals"), signalCount };
|
|
165702
165933
|
}
|
|
165703
165934
|
const capped = seeds.slice(0, cfg.maxSeedMemories);
|
|
165704
|
-
const bootstrapId = `boot-${Date.now()}-${
|
|
165935
|
+
const bootstrapId = `boot-${Date.now()}-${randomUUID10().slice(0, 8)}`;
|
|
165705
165936
|
let ids;
|
|
165706
165937
|
try {
|
|
165707
165938
|
ids = await storeSeeds(this.memoryRepo, projectId, bootstrapId, capped, signals);
|
|
@@ -165761,7 +165992,7 @@ async function scanSignals(_projectId, projectRoot, caps, symbolGraph, gitRunner
|
|
|
165761
165992
|
}
|
|
165762
165993
|
try {
|
|
165763
165994
|
for (const name26 of README_CANDIDATES) {
|
|
165764
|
-
const p =
|
|
165995
|
+
const p = path38.join(projectRoot, name26);
|
|
165765
165996
|
if (fs24.existsSync(p) && fs24.statSync(p).isFile()) {
|
|
165766
165997
|
const buf = fs24.readFileSync(p);
|
|
165767
165998
|
signals.readme = buf.slice(0, MAX_README_BYTES).toString("utf8");
|
|
@@ -165772,14 +166003,14 @@ async function scanSignals(_projectId, projectRoot, caps, symbolGraph, gitRunner
|
|
|
165772
166003
|
logger.debug("bootstrap scan: README read failed", { error: e.message });
|
|
165773
166004
|
}
|
|
165774
166005
|
try {
|
|
165775
|
-
const docsDir =
|
|
166006
|
+
const docsDir = path38.join(projectRoot, "docs");
|
|
165776
166007
|
if (fs24.existsSync(docsDir) && fs24.statSync(docsDir).isDirectory()) {
|
|
165777
166008
|
const entries = walkMarkdown(docsDir).slice(0, MAX_DOCS);
|
|
165778
166009
|
for (const rel of entries) {
|
|
165779
166010
|
try {
|
|
165780
166011
|
const buf = fs24.readFileSync(rel);
|
|
165781
166012
|
signals.docs.push({
|
|
165782
|
-
path:
|
|
166013
|
+
path: path38.relative(projectRoot, rel),
|
|
165783
166014
|
snippet: buf.slice(0, MAX_DOC_BYTES).toString("utf8")
|
|
165784
166015
|
});
|
|
165785
166016
|
} catch {}
|
|
@@ -165790,7 +166021,7 @@ async function scanSignals(_projectId, projectRoot, caps, symbolGraph, gitRunner
|
|
|
165790
166021
|
}
|
|
165791
166022
|
try {
|
|
165792
166023
|
for (const name26 of MANIFEST_FILES) {
|
|
165793
|
-
const p =
|
|
166024
|
+
const p = path38.join(projectRoot, name26);
|
|
165794
166025
|
if (!fs24.existsSync(p) || !fs24.statSync(p).isFile())
|
|
165795
166026
|
continue;
|
|
165796
166027
|
const raw2 = fs24.readFileSync(p).slice(0, MAX_MANIFEST_BYTES).toString("utf8");
|
|
@@ -165838,7 +166069,7 @@ function walkMarkdown(dir) {
|
|
|
165838
166069
|
continue;
|
|
165839
166070
|
}
|
|
165840
166071
|
for (const e of entries) {
|
|
165841
|
-
const full =
|
|
166072
|
+
const full = path38.join(cur, e.name);
|
|
165842
166073
|
if (e.isDirectory()) {
|
|
165843
166074
|
if (e.name === "node_modules" || e.name.startsWith("."))
|
|
165844
166075
|
continue;
|
|
@@ -165955,7 +166186,7 @@ async function storeSeeds(memoryRepo, projectId, bootstrapId, seeds, signals) {
|
|
|
165955
166186
|
const ids = [];
|
|
165956
166187
|
const signalCount = countSignals(signals);
|
|
165957
166188
|
for (const seed of seeds) {
|
|
165958
|
-
const id = `seed-${Date.now()}-${
|
|
166189
|
+
const id = `seed-${Date.now()}-${randomUUID10().slice(0, 8)}`;
|
|
165959
166190
|
const input = {
|
|
165960
166191
|
id,
|
|
165961
166192
|
content: truncate3(seed.summary, MAX_SUMMARY_CHARS),
|
|
@@ -166069,7 +166300,7 @@ var init_bootstrap_service = __esm(() => {
|
|
|
166069
166300
|
MAX_DOC_BYTES = 2 * 1024;
|
|
166070
166301
|
MAX_MANIFEST_BYTES = 2 * 1024;
|
|
166071
166302
|
SeedMemorySchema = exports_external.object({
|
|
166072
|
-
summary: exports_external.string().min(1)
|
|
166303
|
+
summary: exports_external.string().min(1),
|
|
166073
166304
|
type: exports_external.enum(["pattern", "code", "decision"]),
|
|
166074
166305
|
level: exports_external.union([exports_external.literal(0), exports_external.literal(1), exports_external.literal(2)]),
|
|
166075
166306
|
importance: exports_external.number().min(0).max(1),
|
|
@@ -166662,7 +166893,9 @@ var init_handoff_auto_injector = __esm(() => {
|
|
|
166662
166893
|
var exports_dist = {};
|
|
166663
166894
|
__export(exports_dist, {
|
|
166664
166895
|
workspaceManager: () => workspaceManager,
|
|
166896
|
+
withHeavyWorkLease: () => withHeavyWorkLease,
|
|
166665
166897
|
validateEvent: () => validateEvent,
|
|
166898
|
+
validateEnum: () => validateEnum,
|
|
166666
166899
|
validateAllGrammars: () => validateAllGrammars,
|
|
166667
166900
|
tracePathService: () => tracePathService,
|
|
166668
166901
|
toSymbolIdentityResolution: () => toSymbolIdentityResolution,
|
|
@@ -166706,6 +166939,7 @@ __export(exports_dist, {
|
|
|
166706
166939
|
recordSearchDegradation: () => recordSearchDegradation,
|
|
166707
166940
|
quoteDiscoveredIdentifier: () => quoteDiscoveredIdentifier,
|
|
166708
166941
|
projectNotIndexed: () => projectNotIndexed,
|
|
166942
|
+
probeHeavyWork: () => probeHeavyWork,
|
|
166709
166943
|
payloadStorePolicies: () => payloadStorePolicies,
|
|
166710
166944
|
parseStructuralFqn: () => parseStructuralFqn,
|
|
166711
166945
|
parseProjectIdentityPreviewRequest: () => parseProjectIdentityPreviewRequest,
|
|
@@ -166836,6 +167070,7 @@ __export(exports_dist, {
|
|
|
166836
167070
|
UNKNOWN_ACTOR: () => UNKNOWN_ACTOR,
|
|
166837
167071
|
TracePathTool: () => TracePathTool,
|
|
166838
167072
|
TracePathService: () => TracePathService,
|
|
167073
|
+
ToolError: () => ToolError,
|
|
166839
167074
|
TokenMetrics: () => TokenMetrics,
|
|
166840
167075
|
TaskEnvelopeService: () => TaskEnvelopeService,
|
|
166841
167076
|
TYPESCRIPT_RESOLVER_VERSION: () => TYPESCRIPT_RESOLVER_VERSION,
|
|
@@ -167012,6 +167247,7 @@ var init_dist15 = __esm(() => {
|
|
|
167012
167247
|
init_proposal_repository();
|
|
167013
167248
|
init_proposal_payload_validation();
|
|
167014
167249
|
init_auto_improve_job();
|
|
167250
|
+
init_enum_validation();
|
|
167015
167251
|
init_tools();
|
|
167016
167252
|
init_services();
|
|
167017
167253
|
init_graph_generation();
|
|
@@ -169479,7 +169715,7 @@ init_dist();
|
|
|
169479
169715
|
init_dist15();
|
|
169480
169716
|
init_dist();
|
|
169481
169717
|
import fs25 from "fs/promises";
|
|
169482
|
-
import
|
|
169718
|
+
import path39 from "path";
|
|
169483
169719
|
var _indexProjectTool = null;
|
|
169484
169720
|
function indexProjectTool() {
|
|
169485
169721
|
if (!_indexProjectTool)
|
|
@@ -169782,7 +170018,7 @@ class EmbeddedApiClient {
|
|
|
169782
170018
|
} else {
|
|
169783
170019
|
end = start + 20;
|
|
169784
170020
|
}
|
|
169785
|
-
const absolutePath =
|
|
170021
|
+
const absolutePath = path39.join(workspace.project_path, file2);
|
|
169786
170022
|
const content = await fs25.readFile(absolutePath, "utf-8");
|
|
169787
170023
|
const lines = content.split(/\r?\n/);
|
|
169788
170024
|
const slice = lines.slice(start - 1, Math.min(lines.length, end));
|
|
@@ -170038,21 +170274,21 @@ class EmbeddedApiClient {
|
|
|
170038
170274
|
async uploadAndIndex(params) {
|
|
170039
170275
|
const rawBase = params.projectId || params.projectPath.replace(/\\/g, "/").split("/").filter(Boolean).pop() || "default";
|
|
170040
170276
|
const finalProjectId = rawBase.replace(/[^a-zA-Z0-9_.-]/g, "_").slice(0, 128);
|
|
170041
|
-
const uploadRoot = process.env.MASSA_AI_UPLOAD_DIR ||
|
|
170042
|
-
const stagingDir =
|
|
170277
|
+
const uploadRoot = process.env.MASSA_AI_UPLOAD_DIR || path39.join(getGlobalDataDir(), "uploads");
|
|
170278
|
+
const stagingDir = path39.resolve(uploadRoot, finalProjectId);
|
|
170043
170279
|
await fs25.rm(stagingDir, { recursive: true, force: true });
|
|
170044
170280
|
await fs25.mkdir(stagingDir, { recursive: true });
|
|
170045
170281
|
const WRITE_BATCH = 20;
|
|
170046
170282
|
for (let i = 0;i < params.files.length; i += WRITE_BATCH) {
|
|
170047
170283
|
await Promise.all(params.files.slice(i, i + WRITE_BATCH).map(async (file2) => {
|
|
170048
|
-
if (
|
|
170284
|
+
if (path39.isAbsolute(file2.relativePath) || file2.relativePath.includes("..")) {
|
|
170049
170285
|
throw new Error(`Invalid file path: ${file2.relativePath}`);
|
|
170050
170286
|
}
|
|
170051
|
-
const dest =
|
|
170052
|
-
if (!dest.startsWith(stagingDir +
|
|
170287
|
+
const dest = path39.resolve(stagingDir, file2.relativePath.replace(/\//g, path39.sep));
|
|
170288
|
+
if (!dest.startsWith(stagingDir + path39.sep)) {
|
|
170053
170289
|
throw new Error(`Path escapes staging directory: ${file2.relativePath}`);
|
|
170054
170290
|
}
|
|
170055
|
-
await fs25.mkdir(
|
|
170291
|
+
await fs25.mkdir(path39.dirname(dest), { recursive: true });
|
|
170056
170292
|
await fs25.writeFile(dest, file2.content, "utf-8");
|
|
170057
170293
|
}));
|
|
170058
170294
|
}
|
|
@@ -170112,37 +170348,39 @@ class EmbeddedApiClient {
|
|
|
170112
170348
|
return { success: false, error: "projectId is required" };
|
|
170113
170349
|
const result = {};
|
|
170114
170350
|
const errors4 = [];
|
|
170115
|
-
|
|
170116
|
-
|
|
170117
|
-
|
|
170118
|
-
|
|
170119
|
-
|
|
170120
|
-
|
|
170121
|
-
|
|
170122
|
-
|
|
170123
|
-
|
|
170124
|
-
|
|
170125
|
-
|
|
170126
|
-
|
|
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
|
+
}
|
|
170127
170365
|
}
|
|
170128
|
-
|
|
170129
|
-
|
|
170130
|
-
|
|
170131
|
-
|
|
170132
|
-
|
|
170133
|
-
|
|
170134
|
-
|
|
170366
|
+
if (clearSymbols) {
|
|
170367
|
+
try {
|
|
170368
|
+
await workspaceManager.removeWorkspace(projectId);
|
|
170369
|
+
result.symbolsDeleted = "ok";
|
|
170370
|
+
} catch (e) {
|
|
170371
|
+
errors4.push(`symbols: ${e.message}`);
|
|
170372
|
+
}
|
|
170135
170373
|
}
|
|
170136
|
-
|
|
170137
|
-
|
|
170138
|
-
|
|
170139
|
-
|
|
170140
|
-
|
|
170141
|
-
|
|
170142
|
-
|
|
170143
|
-
|
|
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
|
+
}
|
|
170144
170382
|
}
|
|
170145
|
-
}
|
|
170383
|
+
});
|
|
170146
170384
|
return {
|
|
170147
170385
|
success: errors4.length === 0,
|
|
170148
170386
|
data: { projectId, ...result, errors: errors4, message: `Project '${projectId}' reset complete.` }
|
|
@@ -170554,7 +170792,7 @@ class EmbeddedApiClient {
|
|
|
170554
170792
|
// src/file-collector.ts
|
|
170555
170793
|
init_config();
|
|
170556
170794
|
import fs26 from "fs/promises";
|
|
170557
|
-
import
|
|
170795
|
+
import path40 from "path";
|
|
170558
170796
|
var SKIP_DIRS = new Set([
|
|
170559
170797
|
"node_modules",
|
|
170560
170798
|
".git",
|
|
@@ -170570,11 +170808,21 @@ var SKIP_DIRS = new Set([
|
|
|
170570
170808
|
".cache",
|
|
170571
170809
|
"vendor",
|
|
170572
170810
|
".svn",
|
|
170573
|
-
".hg"
|
|
170811
|
+
".hg",
|
|
170812
|
+
"Pods"
|
|
170574
170813
|
]);
|
|
170575
170814
|
var MAX_FILE_BYTES = 512 * 1024;
|
|
170576
|
-
var MAX_TOTAL_BYTES =
|
|
170577
|
-
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
|
+
}
|
|
170578
170826
|
function getAllowedExtensions() {
|
|
170579
170827
|
try {
|
|
170580
170828
|
const list = config2.get("security").allowedExtensions;
|
|
@@ -170587,7 +170835,16 @@ async function collectFiles(projectPath2) {
|
|
|
170587
170835
|
const files = [];
|
|
170588
170836
|
const state = { totalBytes: 0 };
|
|
170589
170837
|
const allowed = getAllowedExtensions();
|
|
170590
|
-
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
|
+
}
|
|
170591
170848
|
return files;
|
|
170592
170849
|
}
|
|
170593
170850
|
async function walk2(root2, dir, files, state, allowed) {
|
|
@@ -170604,13 +170861,13 @@ async function walk2(root2, dir, files, state, allowed) {
|
|
|
170604
170861
|
break;
|
|
170605
170862
|
if (entry2.isDirectory()) {
|
|
170606
170863
|
if (!SKIP_DIRS.has(entry2.name) && !entry2.name.startsWith(".")) {
|
|
170607
|
-
await walk2(root2,
|
|
170864
|
+
await walk2(root2, path40.join(dir, entry2.name), files, state, allowed);
|
|
170608
170865
|
}
|
|
170609
170866
|
} else if (entry2.isFile()) {
|
|
170610
|
-
const ext2 =
|
|
170867
|
+
const ext2 = path40.extname(entry2.name).toLowerCase();
|
|
170611
170868
|
if (!allowed.has(ext2))
|
|
170612
170869
|
continue;
|
|
170613
|
-
const fullPath =
|
|
170870
|
+
const fullPath = path40.join(dir, entry2.name);
|
|
170614
170871
|
try {
|
|
170615
170872
|
const stat = await fs26.stat(fullPath);
|
|
170616
170873
|
if (stat.size > MAX_FILE_BYTES)
|
|
@@ -170619,7 +170876,7 @@ async function walk2(root2, dir, files, state, allowed) {
|
|
|
170619
170876
|
continue;
|
|
170620
170877
|
const content = await fs26.readFile(fullPath, "utf-8");
|
|
170621
170878
|
state.totalBytes += stat.size;
|
|
170622
|
-
const relativePath =
|
|
170879
|
+
const relativePath = path40.relative(root2, fullPath).split(path40.sep).join("/");
|
|
170623
170880
|
files.push({ relativePath, content });
|
|
170624
170881
|
} catch {}
|
|
170625
170882
|
}
|