@massa-ai/tools-api 1.35.0 → 1.36.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.
Files changed (2) hide show
  1. package/dist/index.js +33 -12
  2. package/package.json +3 -3
package/dist/index.js CHANGED
@@ -116739,6 +116739,7 @@ class IndexJobTracker {
116739
116739
  filesIndexed: r2?.filesIndexed ?? 0,
116740
116740
  chunksIndexed: r2?.chunksIndexed ?? 0,
116741
116741
  symbolsIndexed: 0,
116742
+ errors: r2?.errors ?? 0,
116742
116743
  durationMs: r2?.duration ?? 0,
116743
116744
  activatedGraphGenerationId: r2?.activatedGraphGenerationId ?? ""
116744
116745
  });
@@ -116760,6 +116761,11 @@ var init_index_job_tracker = __esm(() => {
116760
116761
  indexJobTracker = IndexJobTracker.getInstance();
116761
116762
  });
116762
116763
 
116764
+ // ../../packages/core/dist/kernel/sanitize/strip-nul.js
116765
+ function stripNul(content) {
116766
+ return content.includes("\x00") ? content.replaceAll("\x00", "") : content;
116767
+ }
116768
+
116763
116769
  // ../../packages/core/dist/services/etl/stages/discover.js
116764
116770
  import fs9 from "fs/promises";
116765
116771
  import path15 from "path";
@@ -116850,7 +116856,7 @@ class DiscoverStage {
116850
116856
  const absolutePath = path15.join(ctx.projectPath, relativePath);
116851
116857
  try {
116852
116858
  const stat2 = await fs9.stat(absolutePath);
116853
- const content = await fs9.readFile(absolutePath, "utf-8");
116859
+ const content = stripNul(await fs9.readFile(absolutePath, "utf-8"));
116854
116860
  const contentHash = createHash5("sha256").update(content).digest("hex");
116855
116861
  let needsReparse = forceReindex;
116856
116862
  if (!forceReindex) {
@@ -120911,6 +120917,7 @@ class LoadStage {
120911
120917
  let chunksLoaded = 0;
120912
120918
  let symbolsLoaded = 0;
120913
120919
  let errors5 = 0;
120920
+ const fileErrors = [];
120914
120921
  let processedSinceStart = 0;
120915
120922
  let lastEtaLogAt = 0;
120916
120923
  const BATCH = 10;
@@ -120981,6 +120988,12 @@ class LoadStage {
120981
120988
  } catch (err) {
120982
120989
  errors5++;
120983
120990
  processedSinceStart++;
120991
+ if (fileErrors.length < MAX_FILE_ERRORS) {
120992
+ fileErrors.push({
120993
+ filePath: file3.file.relativePath,
120994
+ error: err.message
120995
+ });
120996
+ }
120984
120997
  if (emitLifecycle)
120985
120998
  ctx.emit({
120986
120999
  type: "file_error",
@@ -121046,7 +121059,7 @@ class LoadStage {
121046
121059
  duration: formatDuration(durationMs),
121047
121060
  filesPerSec: filesLoaded > 0 && durationMs > 0 ? Number((filesLoaded / durationMs * 1000).toFixed(2)) : 0
121048
121061
  });
121049
- return { filesLoaded, chunksLoaded, symbolsLoaded, errors: errors5 };
121062
+ return { filesLoaded, chunksLoaded, symbolsLoaded, errors: errors5, fileErrors };
121050
121063
  }
121051
121064
  async loadToSearchStores(ctx, file3) {
121052
121065
  if (file3.chunks.length === 0)
@@ -121118,6 +121131,7 @@ class LoadStage {
121118
121131
  return batch.definitions.length;
121119
121132
  }
121120
121133
  }
121134
+ var MAX_FILE_ERRORS = 50;
121121
121135
  var init_load = __esm(() => {
121122
121136
  init_dist();
121123
121137
  init_with_deadlock_retry();
@@ -121298,8 +121312,8 @@ class GraphGenerationRepositoryPg {
121298
121312
  async heartbeat(lease, leaseTtlMs) {
121299
121313
  const ttl = validateTtl2(leaseTtlMs);
121300
121314
  return getPrismaClient2().$transaction(async (tx) => {
121301
- const workspace = await lockWorkspace(tx, lease.projectId);
121302
121315
  const generation = await lockGeneration(tx, lease.projectId, lease.generationId);
121316
+ const workspace = await lockWorkspace(tx, lease.projectId);
121303
121317
  if (!leaseMatches(workspace, generation, lease))
121304
121318
  return { status: "lease_lost" };
121305
121319
  const renewed = await tx.$queryRaw`
@@ -121322,8 +121336,8 @@ class GraphGenerationRepositoryPg {
121322
121336
  }
121323
121337
  async complete(lease) {
121324
121338
  return getPrismaClient2().$transaction(async (tx) => {
121325
- const workspace = await lockWorkspace(tx, lease.projectId);
121326
121339
  const generation = await lockGeneration(tx, lease.projectId, lease.generationId);
121340
+ const workspace = await lockWorkspace(tx, lease.projectId);
121327
121341
  if (!leaseMatches(workspace, generation, lease))
121328
121342
  return { status: "lease_lost" };
121329
121343
  const live = await tx.$queryRaw`
@@ -121352,8 +121366,8 @@ class GraphGenerationRepositoryPg {
121352
121366
  }
121353
121367
  async activate(lease) {
121354
121368
  return getPrismaClient2().$transaction(async (tx) => {
121355
- const workspace = await lockWorkspace(tx, lease.projectId);
121356
121369
  const generation = await lockGeneration(tx, lease.projectId, lease.generationId);
121370
+ const workspace = await lockWorkspace(tx, lease.projectId);
121357
121371
  if (!leaseMatches(workspace, generation, lease))
121358
121372
  return { status: "lease_lost" };
121359
121373
  if (workspace.active_graph_generation_id !== generation.expected_active_id) {
@@ -121403,8 +121417,8 @@ class GraphGenerationRepositoryPg {
121403
121417
  async abort(lease, reason) {
121404
121418
  const failureReason = boundedText2(reason, "reason", MAX_FAILURE_REASON);
121405
121419
  return getPrismaClient2().$transaction(async (tx) => {
121406
- const workspace = await lockWorkspace(tx, lease.projectId);
121407
121420
  const generation = await lockGeneration(tx, lease.projectId, lease.generationId);
121421
+ const workspace = await lockWorkspace(tx, lease.projectId);
121408
121422
  if (!leaseMatches(workspace, generation, lease))
121409
121423
  return { status: "lease_lost" };
121410
121424
  const live = await tx.$queryRaw`
@@ -121480,7 +121494,7 @@ class GraphGenerationCoordinator {
121480
121494
  async begin(input) {
121481
121495
  const deadline = Date.now() + GRAPH_GENERATION_LEASE_TTL_MS;
121482
121496
  for (;; ) {
121483
- const outcome2 = await this.repository.begin({ ...input, leaseTtlMs: GRAPH_GENERATION_LEASE_TTL_MS });
121497
+ const outcome2 = await withDeadlockRetry(() => this.repository.begin({ ...input, leaseTtlMs: GRAPH_GENERATION_LEASE_TTL_MS }), { operation: "graph_generation.begin", maxAttempts: 5 });
121484
121498
  if (outcome2.status === "acquired")
121485
121499
  return outcome2.lease;
121486
121500
  if (outcome2.status === "stale_active") {
@@ -121492,12 +121506,12 @@ class GraphGenerationCoordinator {
121492
121506
  }
121493
121507
  }
121494
121508
  async heartbeat(lease) {
121495
- const outcome2 = await withDeadlockRetry(() => this.repository.heartbeat(lease, GRAPH_GENERATION_LEASE_TTL_MS), { operation: "graph_generation.heartbeat", maxAttempts: 3 });
121509
+ const outcome2 = await withDeadlockRetry(() => this.repository.heartbeat(lease, GRAPH_GENERATION_LEASE_TTL_MS), { operation: "graph_generation.heartbeat", maxAttempts: 5 });
121496
121510
  if (outcome2.status !== "renewed")
121497
121511
  throw new Error("graph_generation_lease_lost");
121498
121512
  }
121499
121513
  async activate(lease) {
121500
- const completeness = await this.repository.complete(lease);
121514
+ const completeness = await withDeadlockRetry(() => this.repository.complete(lease), { operation: "graph_generation.complete", maxAttempts: 5 });
121501
121515
  if (completeness.status === "incomplete") {
121502
121516
  throw new Error(`graph_generation_incomplete:${completeness.reasons.join(",")}`);
121503
121517
  }
@@ -121506,7 +121520,7 @@ class GraphGenerationCoordinator {
121506
121520
  if (completeness.status === "stale_active") {
121507
121521
  throw new Error(`graph_generation_stale_active:${completeness.activeGenerationId ?? "none"}`);
121508
121522
  }
121509
- const activation = await this.repository.activate(lease);
121523
+ const activation = await withDeadlockRetry(() => this.repository.activate(lease), { operation: "graph_generation.activate", maxAttempts: 5 });
121510
121524
  if (activation.status === "activated")
121511
121525
  return activation;
121512
121526
  if (activation.status === "incomplete") {
@@ -121517,7 +121531,7 @@ class GraphGenerationCoordinator {
121517
121531
  throw new Error(`graph_generation_stale_active:${activation.activeGenerationId ?? "none"}`);
121518
121532
  }
121519
121533
  async abort(lease, reason) {
121520
- const outcome2 = await this.repository.abort(lease, reason);
121534
+ const outcome2 = await withDeadlockRetry(() => this.repository.abort(lease, reason), { operation: "graph_generation.abort", maxAttempts: 5 });
121521
121535
  if (outcome2.status === "lease_lost")
121522
121536
  throw new Error("graph_generation_lease_lost_during_abort");
121523
121537
  }
@@ -121860,7 +121874,12 @@ var init_pipeline = __esm(() => {
121860
121874
  throw managedRunLeaseLost;
121861
121875
  stageTimings.load = Math.round(performance.now() - st4);
121862
121876
  if (loadResult.errors > 0) {
121863
- throw new Error(`ETL completed with ${loadResult.errors} file error${loadResult.errors === 1 ? "" : "s"}`);
121877
+ logger.warn("EtlPipeline: completed with file errors", {
121878
+ projectId,
121879
+ jobId,
121880
+ errors: loadResult.errors,
121881
+ fileErrors: (loadResult.fileErrors ?? []).slice(0, 10)
121882
+ });
121864
121883
  }
121865
121884
  const activationSnapshot = await abortable(this.discover.run(ctx, { forceReindex, includeTests: include_tests }), graphAbortController.signal);
121866
121885
  if (buildGraphInputSnapshotHash(activationSnapshot) !== graphGenerationLease.inputSnapshotHash) {
@@ -121917,6 +121936,7 @@ var init_pipeline = __esm(() => {
121917
121936
  filesIndexed: result.filesIndexed,
121918
121937
  chunksIndexed: result.chunksIndexed,
121919
121938
  errors: result.errors,
121939
+ fileErrors: loadResult.fileErrors ?? [],
121920
121940
  duration: durationMs,
121921
121941
  activatedGraphGenerationId: result.activatedGraphGenerationId,
121922
121942
  parserDiagnostics: result.parserDiagnostics
@@ -121927,6 +121947,7 @@ var init_pipeline = __esm(() => {
121927
121947
  filesIndexed: result.filesIndexed,
121928
121948
  chunksIndexed: result.chunksIndexed,
121929
121949
  symbolsIndexed: result.symbolsIndexed,
121950
+ errors: result.errors,
121930
121951
  durationMs,
121931
121952
  activatedGraphGenerationId: result.activatedGraphGenerationId
121932
121953
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@massa-ai/tools-api",
3
- "version": "1.35.0",
3
+ "version": "1.36.0",
4
4
  "author": "luizgmassa",
5
5
  "description": "massa-ai REST API server - Semantic code search, memory, and context compression",
6
6
  "type": "module",
@@ -21,8 +21,8 @@
21
21
  "test": "bun scripts/run-tests-isolated.ts"
22
22
  },
23
23
  "dependencies": {
24
- "@massa-ai/core": "^1.35.0",
25
- "@massa-ai/shared": "^1.35.0",
24
+ "@massa-ai/core": "^1.36.0",
25
+ "@massa-ai/shared": "^1.36.0",
26
26
  "elysia": "^1.2.25",
27
27
  "@elysiajs/swagger": "^1.2.0",
28
28
  "@elysiajs/cors": "^1.2.0",