@massa-ai/mcp-client 1.10.0 → 1.11.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 (3) hide show
  1. package/dist/config-cli.js +120 -120
  2. package/dist/index.js +120 -120
  3. package/package.json +3 -3
@@ -115877,122 +115877,6 @@ var init_search_diagnostics = __esm(() => {
115877
115877
  };
115878
115878
  });
115879
115879
 
115880
- // ../../packages/core/dist/services/search/rlm-fusion.js
115881
- function fuseResultsImpl(rlm, resultSets, query, explainScores = false) {
115882
- const scoreMap = new Map;
115883
- const hasCodePattern = (text2) => {
115884
- const codePatterns = [
115885
- /\w+\(\)/,
115886
- /\bfunction\b/i,
115887
- /\bclass\b/i,
115888
- /\binterface\b/i,
115889
- /\benum\b/i,
115890
- /\btype\b/i,
115891
- /\bconst\b/i,
115892
- /\bimport\b/i,
115893
- /\bexport\b/i
115894
- ];
115895
- return codePatterns.some((pattern) => pattern.test(text2));
115896
- };
115897
- const isCodeQuery = hasCodePattern(query);
115898
- const codeKeywordBoostRaw = Number(process.env.RRF_KEYWORD_BOOST ?? "2.5");
115899
- const codeKeywordBoost = Number.isFinite(codeKeywordBoostRaw) && codeKeywordBoostRaw > 0 ? codeKeywordBoostRaw : 2.5;
115900
- const KEYWORD_BOOST = isCodeQuery ? codeKeywordBoost : 1;
115901
- logger.debug("RRF fusion parameters", {
115902
- query,
115903
- isCodeQuery,
115904
- keywordBoost: KEYWORD_BOOST,
115905
- vectorResults: resultSets[0]?.length || 0,
115906
- keywordResults: resultSets[1]?.length || 0
115907
- });
115908
- for (let i = 0;i < resultSets.length; i++) {
115909
- const results = resultSets[i];
115910
- const isVector = i === 0;
115911
- const isMemoryStream = results.some((r) => r.source === "memory" || r.metadata?.context?.graphNeighbor === true);
115912
- const boost = isVector ? 1 : isMemoryStream ? 1 : KEYWORD_BOOST;
115913
- results.forEach((result, rank) => {
115914
- const rrfScore = 1 / (rlm.RRF_K + rank + 1) * boost;
115915
- if (scoreMap.has(result.id)) {
115916
- const existing = scoreMap.get(result.id);
115917
- if (isVector) {
115918
- existing.vectorRrfScore += rrfScore;
115919
- existing.vectorRank = rank;
115920
- existing.vectorScore = result.score;
115921
- } else if (isMemoryStream) {
115922
- existing.memoryRrfScore += rrfScore;
115923
- } else {
115924
- existing.lexicalRrfScore = Math.max(existing.lexicalRrfScore, rrfScore);
115925
- if (existing.keywordRank === undefined || rank < existing.keywordRank) {
115926
- existing.keywordRank = rank;
115927
- existing.keywordScore = result.score;
115928
- }
115929
- }
115930
- existing.rrfScore = existing.vectorRrfScore + existing.lexicalRrfScore + existing.memoryRrfScore;
115931
- } else {
115932
- const vectorRrfScore = isVector ? rrfScore : 0;
115933
- const lexicalRrfScore = !isVector && !isMemoryStream ? rrfScore : 0;
115934
- const memoryRrfScore = isMemoryStream ? rrfScore : 0;
115935
- scoreMap.set(result.id, {
115936
- result: { ...result },
115937
- rrfScore: vectorRrfScore + lexicalRrfScore + memoryRrfScore,
115938
- vectorRrfScore,
115939
- lexicalRrfScore,
115940
- memoryRrfScore,
115941
- vectorRank: isVector ? rank : undefined,
115942
- keywordRank: !isVector && !isMemoryStream ? rank : undefined,
115943
- vectorScore: isVector ? result.score : undefined,
115944
- keywordScore: !isVector && !isMemoryStream ? result.score : undefined
115945
- });
115946
- }
115947
- });
115948
- }
115949
- const sorted = Array.from(scoreMap.values()).sort((a, b) => b.rrfScore - a.rrfScore);
115950
- const maxRrfScore = sorted[0]?.rrfScore || 1;
115951
- const vectorWeightRaw = Number(process.env.RRF_VECTOR_WEIGHT ?? "0.3");
115952
- const vectorWeight = Number.isFinite(vectorWeightRaw) ? Math.min(1, Math.max(0, vectorWeightRaw)) : 0.3;
115953
- return sorted.map(({ result, rrfScore, vectorRank, keywordRank, vectorScore, keywordScore, vectorRrfScore, lexicalRrfScore, memoryRrfScore }, index) => {
115954
- const rrfNormalized = rrfScore / maxRrfScore;
115955
- const vectorSimilarity = vectorScore || 0;
115956
- const combinedScore = rrfNormalized * (1 - vectorWeight) + vectorSimilarity * vectorWeight;
115957
- const centralityScore = typeof result.metadata?.centralityScore === "number" ? result.metadata.centralityScore : 0;
115958
- const normalizedScore = Math.min(1, combinedScore * (1 + 0.2 * centralityScore));
115959
- const memoryOnly = memoryRrfScore > 0 && vectorRrfScore === 0 && lexicalRrfScore === 0;
115960
- const explanation = explainScores ? generateScoreExplanationImpl(normalizedScore, rrfScore, vectorScore, keywordScore, vectorRank, keywordRank, index) : undefined;
115961
- return {
115962
- ...result,
115963
- score: normalizedScore,
115964
- explanation,
115965
- metadata: {
115966
- ...result.metadata,
115967
- _rrfRawVectorScore: vectorScore ?? (memoryOnly ? 0 : undefined)
115968
- }
115969
- };
115970
- });
115971
- }
115972
- function generateScoreExplanationImpl(finalScore, rrfScore, vectorScore, keywordScore, vectorRank, keywordRank, combinedRank) {
115973
- const parts = [];
115974
- if (vectorScore != null && vectorRank != null) {
115975
- parts.push(`Vector: ${(vectorScore * 100).toFixed(1)}% (rank #${vectorRank + 1})`);
115976
- }
115977
- if (keywordScore != null && keywordRank != null) {
115978
- parts.push(`Keyword: ${(keywordScore * 100).toFixed(1)}% (rank #${keywordRank + 1})`);
115979
- }
115980
- const breakdown = parts.join(" + ") + ` \u2192 RRF: ${rrfScore.toFixed(4)} \u2192 Final: ${(finalScore * 100).toFixed(1)}%`;
115981
- return {
115982
- finalScore,
115983
- vectorScore: vectorScore ?? undefined,
115984
- keywordScore: keywordScore ?? undefined,
115985
- rrfScore,
115986
- vectorRank: vectorRank != null ? vectorRank + 1 : undefined,
115987
- keywordRank: keywordRank != null ? keywordRank + 1 : undefined,
115988
- combinedRank: combinedRank != null ? combinedRank + 1 : undefined,
115989
- breakdown
115990
- };
115991
- }
115992
- var init_rlm_fusion = __esm(() => {
115993
- init_dist();
115994
- });
115995
-
115996
115880
  // ../../packages/core/dist/services/search/rlm-search.js
115997
115881
  async function searchImpl(rlm, query, projectId, options = {}) {
115998
115882
  try {
@@ -116377,7 +116261,123 @@ var init_rlm_search = __esm(() => {
116377
116261
  init_lexical_search();
116378
116262
  init_event_bus();
116379
116263
  init_search_diagnostics();
116380
- init_rlm_fusion();
116264
+ });
116265
+
116266
+ // ../../packages/core/dist/services/search/result-fusion.js
116267
+ function fuseResults(resultSets, query, explainScores = false) {
116268
+ const scoreMap = new Map;
116269
+ const hasCodePattern = (text2) => {
116270
+ const codePatterns = [
116271
+ /\w+\(\)/,
116272
+ /\bfunction\b/i,
116273
+ /\bclass\b/i,
116274
+ /\binterface\b/i,
116275
+ /\benum\b/i,
116276
+ /\btype\b/i,
116277
+ /\bconst\b/i,
116278
+ /\bimport\b/i,
116279
+ /\bexport\b/i
116280
+ ];
116281
+ return codePatterns.some((pattern) => pattern.test(text2));
116282
+ };
116283
+ const isCodeQuery = hasCodePattern(query);
116284
+ const codeKeywordBoostRaw = Number(process.env.RRF_KEYWORD_BOOST ?? "2.5");
116285
+ const codeKeywordBoost = Number.isFinite(codeKeywordBoostRaw) && codeKeywordBoostRaw > 0 ? codeKeywordBoostRaw : 2.5;
116286
+ const KEYWORD_BOOST = isCodeQuery ? codeKeywordBoost : 1;
116287
+ logger.debug("RRF fusion parameters", {
116288
+ query,
116289
+ isCodeQuery,
116290
+ keywordBoost: KEYWORD_BOOST,
116291
+ vectorResults: resultSets[0]?.length || 0,
116292
+ keywordResults: resultSets[1]?.length || 0
116293
+ });
116294
+ for (let i = 0;i < resultSets.length; i++) {
116295
+ const results = resultSets[i];
116296
+ const isVector = i === 0;
116297
+ const isMemoryStream = results.some((r) => r.source === "memory" || r.metadata?.context?.graphNeighbor === true);
116298
+ const boost = isVector ? 1 : isMemoryStream ? 1 : KEYWORD_BOOST;
116299
+ results.forEach((result, rank) => {
116300
+ const rrfScore = 1 / (RRF_K + rank + 1) * boost;
116301
+ if (scoreMap.has(result.id)) {
116302
+ const existing = scoreMap.get(result.id);
116303
+ if (isVector) {
116304
+ existing.vectorRrfScore += rrfScore;
116305
+ existing.vectorRank = rank;
116306
+ existing.vectorScore = result.score;
116307
+ } else if (isMemoryStream) {
116308
+ existing.memoryRrfScore += rrfScore;
116309
+ } else {
116310
+ existing.lexicalRrfScore = Math.max(existing.lexicalRrfScore, rrfScore);
116311
+ if (existing.keywordRank === undefined || rank < existing.keywordRank) {
116312
+ existing.keywordRank = rank;
116313
+ existing.keywordScore = result.score;
116314
+ }
116315
+ }
116316
+ existing.rrfScore = existing.vectorRrfScore + existing.lexicalRrfScore + existing.memoryRrfScore;
116317
+ } else {
116318
+ const vectorRrfScore = isVector ? rrfScore : 0;
116319
+ const lexicalRrfScore = !isVector && !isMemoryStream ? rrfScore : 0;
116320
+ const memoryRrfScore = isMemoryStream ? rrfScore : 0;
116321
+ scoreMap.set(result.id, {
116322
+ result: { ...result },
116323
+ rrfScore: vectorRrfScore + lexicalRrfScore + memoryRrfScore,
116324
+ vectorRrfScore,
116325
+ lexicalRrfScore,
116326
+ memoryRrfScore,
116327
+ vectorRank: isVector ? rank : undefined,
116328
+ keywordRank: !isVector && !isMemoryStream ? rank : undefined,
116329
+ vectorScore: isVector ? result.score : undefined,
116330
+ keywordScore: !isVector && !isMemoryStream ? result.score : undefined
116331
+ });
116332
+ }
116333
+ });
116334
+ }
116335
+ const sorted = Array.from(scoreMap.values()).sort((a, b) => b.rrfScore - a.rrfScore);
116336
+ const maxRrfScore = sorted[0]?.rrfScore || 1;
116337
+ const vectorWeightRaw = Number(process.env.RRF_VECTOR_WEIGHT ?? "0.3");
116338
+ const vectorWeight = Number.isFinite(vectorWeightRaw) ? Math.min(1, Math.max(0, vectorWeightRaw)) : 0.3;
116339
+ return sorted.map(({ result, rrfScore, vectorRank, keywordRank, vectorScore, keywordScore, vectorRrfScore, lexicalRrfScore, memoryRrfScore }, index) => {
116340
+ const rrfNormalized = rrfScore / maxRrfScore;
116341
+ const vectorSimilarity = vectorScore || 0;
116342
+ const combinedScore = rrfNormalized * (1 - vectorWeight) + vectorSimilarity * vectorWeight;
116343
+ const centralityScore = typeof result.metadata?.centralityScore === "number" ? result.metadata.centralityScore : 0;
116344
+ const normalizedScore = Math.min(1, combinedScore * (1 + 0.2 * centralityScore));
116345
+ const memoryOnly = memoryRrfScore > 0 && vectorRrfScore === 0 && lexicalRrfScore === 0;
116346
+ const explanation = explainScores ? generateScoreExplanation(normalizedScore, rrfScore, vectorScore, keywordScore, vectorRank, keywordRank, index) : undefined;
116347
+ return {
116348
+ ...result,
116349
+ score: normalizedScore,
116350
+ explanation,
116351
+ metadata: {
116352
+ ...result.metadata,
116353
+ _rrfRawVectorScore: vectorScore ?? (memoryOnly ? 0 : undefined)
116354
+ }
116355
+ };
116356
+ });
116357
+ }
116358
+ function generateScoreExplanation(finalScore, rrfScore, vectorScore, keywordScore, vectorRank, keywordRank, combinedRank) {
116359
+ const parts = [];
116360
+ if (vectorScore != null && vectorRank != null) {
116361
+ parts.push(`Vector: ${(vectorScore * 100).toFixed(1)}% (rank #${vectorRank + 1})`);
116362
+ }
116363
+ if (keywordScore != null && keywordRank != null) {
116364
+ parts.push(`Keyword: ${(keywordScore * 100).toFixed(1)}% (rank #${keywordRank + 1})`);
116365
+ }
116366
+ const breakdown = parts.join(" + ") + ` \u2192 RRF: ${rrfScore.toFixed(4)} \u2192 Final: ${(finalScore * 100).toFixed(1)}%`;
116367
+ return {
116368
+ finalScore,
116369
+ vectorScore: vectorScore ?? undefined,
116370
+ keywordScore: keywordScore ?? undefined,
116371
+ rrfScore,
116372
+ vectorRank: vectorRank != null ? vectorRank + 1 : undefined,
116373
+ keywordRank: keywordRank != null ? keywordRank + 1 : undefined,
116374
+ combinedRank: combinedRank != null ? combinedRank + 1 : undefined,
116375
+ breakdown
116376
+ };
116377
+ }
116378
+ var RRF_K = 60;
116379
+ var init_result_fusion = __esm(() => {
116380
+ init_dist();
116381
116381
  });
116382
116382
 
116383
116383
  // ../../packages/core/dist/services/search/rlm-admin.js
@@ -116469,6 +116469,7 @@ var init_contextual_search_rlm = __esm(() => {
116469
116469
  init_rlm_indexing();
116470
116470
  init_rlm_synapse();
116471
116471
  init_rlm_search();
116472
+ init_result_fusion();
116472
116473
  init_rlm_admin();
116473
116474
  ContextualSearchRLM = class ContextualSearchRLM {
116474
116475
  keywordSearch;
@@ -116479,7 +116480,6 @@ var init_contextual_search_rlm = __esm(() => {
116479
116480
  symbolRepo;
116480
116481
  fileFilterCache;
116481
116482
  queryUnderstanding;
116482
- RRF_K = 60;
116483
116483
  initialized = false;
116484
116484
  static indexingLocks = new Map;
116485
116485
  injectedDeps;
@@ -116523,10 +116523,10 @@ var init_contextual_search_rlm = __esm(() => {
116523
116523
  return buildGraphStreamImpl(this, resultSets, maxResults, projectId, reportDegradation);
116524
116524
  }
116525
116525
  fuseResults(resultSets, query, explainScores = false) {
116526
- return fuseResultsImpl(this, resultSets, query, explainScores);
116526
+ return fuseResults(resultSets, query, explainScores);
116527
116527
  }
116528
116528
  generateScoreExplanation(finalScore, rrfScore, vectorScore, keywordScore, vectorRank, keywordRank, combinedRank) {
116529
- return generateScoreExplanationImpl(finalScore, rrfScore, vectorScore, keywordScore, vectorRank, keywordRank, combinedRank);
116529
+ return generateScoreExplanation(finalScore, rrfScore, vectorScore, keywordScore, vectorRank, keywordRank, combinedRank);
116530
116530
  }
116531
116531
  async addContextToResults(results, _projectId) {
116532
116532
  return addContextToResultsImpl(this, results, _projectId);
package/dist/index.js CHANGED
@@ -122436,122 +122436,6 @@ var init_search_diagnostics = __esm(() => {
122436
122436
  };
122437
122437
  });
122438
122438
 
122439
- // ../../packages/core/dist/services/search/rlm-fusion.js
122440
- function fuseResultsImpl(rlm, resultSets, query, explainScores = false) {
122441
- const scoreMap = new Map;
122442
- const hasCodePattern = (text2) => {
122443
- const codePatterns = [
122444
- /\w+\(\)/,
122445
- /\bfunction\b/i,
122446
- /\bclass\b/i,
122447
- /\binterface\b/i,
122448
- /\benum\b/i,
122449
- /\btype\b/i,
122450
- /\bconst\b/i,
122451
- /\bimport\b/i,
122452
- /\bexport\b/i
122453
- ];
122454
- return codePatterns.some((pattern) => pattern.test(text2));
122455
- };
122456
- const isCodeQuery = hasCodePattern(query);
122457
- const codeKeywordBoostRaw = Number(process.env.RRF_KEYWORD_BOOST ?? "2.5");
122458
- const codeKeywordBoost = Number.isFinite(codeKeywordBoostRaw) && codeKeywordBoostRaw > 0 ? codeKeywordBoostRaw : 2.5;
122459
- const KEYWORD_BOOST = isCodeQuery ? codeKeywordBoost : 1;
122460
- logger.debug("RRF fusion parameters", {
122461
- query,
122462
- isCodeQuery,
122463
- keywordBoost: KEYWORD_BOOST,
122464
- vectorResults: resultSets[0]?.length || 0,
122465
- keywordResults: resultSets[1]?.length || 0
122466
- });
122467
- for (let i = 0;i < resultSets.length; i++) {
122468
- const results = resultSets[i];
122469
- const isVector = i === 0;
122470
- const isMemoryStream = results.some((r) => r.source === "memory" || r.metadata?.context?.graphNeighbor === true);
122471
- const boost = isVector ? 1 : isMemoryStream ? 1 : KEYWORD_BOOST;
122472
- results.forEach((result, rank) => {
122473
- const rrfScore = 1 / (rlm.RRF_K + rank + 1) * boost;
122474
- if (scoreMap.has(result.id)) {
122475
- const existing = scoreMap.get(result.id);
122476
- if (isVector) {
122477
- existing.vectorRrfScore += rrfScore;
122478
- existing.vectorRank = rank;
122479
- existing.vectorScore = result.score;
122480
- } else if (isMemoryStream) {
122481
- existing.memoryRrfScore += rrfScore;
122482
- } else {
122483
- existing.lexicalRrfScore = Math.max(existing.lexicalRrfScore, rrfScore);
122484
- if (existing.keywordRank === undefined || rank < existing.keywordRank) {
122485
- existing.keywordRank = rank;
122486
- existing.keywordScore = result.score;
122487
- }
122488
- }
122489
- existing.rrfScore = existing.vectorRrfScore + existing.lexicalRrfScore + existing.memoryRrfScore;
122490
- } else {
122491
- const vectorRrfScore = isVector ? rrfScore : 0;
122492
- const lexicalRrfScore = !isVector && !isMemoryStream ? rrfScore : 0;
122493
- const memoryRrfScore = isMemoryStream ? rrfScore : 0;
122494
- scoreMap.set(result.id, {
122495
- result: { ...result },
122496
- rrfScore: vectorRrfScore + lexicalRrfScore + memoryRrfScore,
122497
- vectorRrfScore,
122498
- lexicalRrfScore,
122499
- memoryRrfScore,
122500
- vectorRank: isVector ? rank : undefined,
122501
- keywordRank: !isVector && !isMemoryStream ? rank : undefined,
122502
- vectorScore: isVector ? result.score : undefined,
122503
- keywordScore: !isVector && !isMemoryStream ? result.score : undefined
122504
- });
122505
- }
122506
- });
122507
- }
122508
- const sorted = Array.from(scoreMap.values()).sort((a, b) => b.rrfScore - a.rrfScore);
122509
- const maxRrfScore = sorted[0]?.rrfScore || 1;
122510
- const vectorWeightRaw = Number(process.env.RRF_VECTOR_WEIGHT ?? "0.3");
122511
- const vectorWeight = Number.isFinite(vectorWeightRaw) ? Math.min(1, Math.max(0, vectorWeightRaw)) : 0.3;
122512
- return sorted.map(({ result, rrfScore, vectorRank, keywordRank, vectorScore, keywordScore, vectorRrfScore, lexicalRrfScore, memoryRrfScore }, index) => {
122513
- const rrfNormalized = rrfScore / maxRrfScore;
122514
- const vectorSimilarity = vectorScore || 0;
122515
- const combinedScore = rrfNormalized * (1 - vectorWeight) + vectorSimilarity * vectorWeight;
122516
- const centralityScore = typeof result.metadata?.centralityScore === "number" ? result.metadata.centralityScore : 0;
122517
- const normalizedScore = Math.min(1, combinedScore * (1 + 0.2 * centralityScore));
122518
- const memoryOnly = memoryRrfScore > 0 && vectorRrfScore === 0 && lexicalRrfScore === 0;
122519
- const explanation = explainScores ? generateScoreExplanationImpl(normalizedScore, rrfScore, vectorScore, keywordScore, vectorRank, keywordRank, index) : undefined;
122520
- return {
122521
- ...result,
122522
- score: normalizedScore,
122523
- explanation,
122524
- metadata: {
122525
- ...result.metadata,
122526
- _rrfRawVectorScore: vectorScore ?? (memoryOnly ? 0 : undefined)
122527
- }
122528
- };
122529
- });
122530
- }
122531
- function generateScoreExplanationImpl(finalScore, rrfScore, vectorScore, keywordScore, vectorRank, keywordRank, combinedRank) {
122532
- const parts = [];
122533
- if (vectorScore != null && vectorRank != null) {
122534
- parts.push(`Vector: ${(vectorScore * 100).toFixed(1)}% (rank #${vectorRank + 1})`);
122535
- }
122536
- if (keywordScore != null && keywordRank != null) {
122537
- parts.push(`Keyword: ${(keywordScore * 100).toFixed(1)}% (rank #${keywordRank + 1})`);
122538
- }
122539
- const breakdown = parts.join(" + ") + ` \u2192 RRF: ${rrfScore.toFixed(4)} \u2192 Final: ${(finalScore * 100).toFixed(1)}%`;
122540
- return {
122541
- finalScore,
122542
- vectorScore: vectorScore ?? undefined,
122543
- keywordScore: keywordScore ?? undefined,
122544
- rrfScore,
122545
- vectorRank: vectorRank != null ? vectorRank + 1 : undefined,
122546
- keywordRank: keywordRank != null ? keywordRank + 1 : undefined,
122547
- combinedRank: combinedRank != null ? combinedRank + 1 : undefined,
122548
- breakdown
122549
- };
122550
- }
122551
- var init_rlm_fusion = __esm(() => {
122552
- init_dist();
122553
- });
122554
-
122555
122439
  // ../../packages/core/dist/services/search/rlm-search.js
122556
122440
  async function searchImpl(rlm, query, projectId, options = {}) {
122557
122441
  try {
@@ -122936,7 +122820,123 @@ var init_rlm_search = __esm(() => {
122936
122820
  init_lexical_search();
122937
122821
  init_event_bus();
122938
122822
  init_search_diagnostics();
122939
- init_rlm_fusion();
122823
+ });
122824
+
122825
+ // ../../packages/core/dist/services/search/result-fusion.js
122826
+ function fuseResults(resultSets, query, explainScores = false) {
122827
+ const scoreMap = new Map;
122828
+ const hasCodePattern = (text2) => {
122829
+ const codePatterns = [
122830
+ /\w+\(\)/,
122831
+ /\bfunction\b/i,
122832
+ /\bclass\b/i,
122833
+ /\binterface\b/i,
122834
+ /\benum\b/i,
122835
+ /\btype\b/i,
122836
+ /\bconst\b/i,
122837
+ /\bimport\b/i,
122838
+ /\bexport\b/i
122839
+ ];
122840
+ return codePatterns.some((pattern) => pattern.test(text2));
122841
+ };
122842
+ const isCodeQuery = hasCodePattern(query);
122843
+ const codeKeywordBoostRaw = Number(process.env.RRF_KEYWORD_BOOST ?? "2.5");
122844
+ const codeKeywordBoost = Number.isFinite(codeKeywordBoostRaw) && codeKeywordBoostRaw > 0 ? codeKeywordBoostRaw : 2.5;
122845
+ const KEYWORD_BOOST = isCodeQuery ? codeKeywordBoost : 1;
122846
+ logger.debug("RRF fusion parameters", {
122847
+ query,
122848
+ isCodeQuery,
122849
+ keywordBoost: KEYWORD_BOOST,
122850
+ vectorResults: resultSets[0]?.length || 0,
122851
+ keywordResults: resultSets[1]?.length || 0
122852
+ });
122853
+ for (let i = 0;i < resultSets.length; i++) {
122854
+ const results = resultSets[i];
122855
+ const isVector = i === 0;
122856
+ const isMemoryStream = results.some((r) => r.source === "memory" || r.metadata?.context?.graphNeighbor === true);
122857
+ const boost = isVector ? 1 : isMemoryStream ? 1 : KEYWORD_BOOST;
122858
+ results.forEach((result, rank) => {
122859
+ const rrfScore = 1 / (RRF_K + rank + 1) * boost;
122860
+ if (scoreMap.has(result.id)) {
122861
+ const existing = scoreMap.get(result.id);
122862
+ if (isVector) {
122863
+ existing.vectorRrfScore += rrfScore;
122864
+ existing.vectorRank = rank;
122865
+ existing.vectorScore = result.score;
122866
+ } else if (isMemoryStream) {
122867
+ existing.memoryRrfScore += rrfScore;
122868
+ } else {
122869
+ existing.lexicalRrfScore = Math.max(existing.lexicalRrfScore, rrfScore);
122870
+ if (existing.keywordRank === undefined || rank < existing.keywordRank) {
122871
+ existing.keywordRank = rank;
122872
+ existing.keywordScore = result.score;
122873
+ }
122874
+ }
122875
+ existing.rrfScore = existing.vectorRrfScore + existing.lexicalRrfScore + existing.memoryRrfScore;
122876
+ } else {
122877
+ const vectorRrfScore = isVector ? rrfScore : 0;
122878
+ const lexicalRrfScore = !isVector && !isMemoryStream ? rrfScore : 0;
122879
+ const memoryRrfScore = isMemoryStream ? rrfScore : 0;
122880
+ scoreMap.set(result.id, {
122881
+ result: { ...result },
122882
+ rrfScore: vectorRrfScore + lexicalRrfScore + memoryRrfScore,
122883
+ vectorRrfScore,
122884
+ lexicalRrfScore,
122885
+ memoryRrfScore,
122886
+ vectorRank: isVector ? rank : undefined,
122887
+ keywordRank: !isVector && !isMemoryStream ? rank : undefined,
122888
+ vectorScore: isVector ? result.score : undefined,
122889
+ keywordScore: !isVector && !isMemoryStream ? result.score : undefined
122890
+ });
122891
+ }
122892
+ });
122893
+ }
122894
+ const sorted = Array.from(scoreMap.values()).sort((a, b) => b.rrfScore - a.rrfScore);
122895
+ const maxRrfScore = sorted[0]?.rrfScore || 1;
122896
+ const vectorWeightRaw = Number(process.env.RRF_VECTOR_WEIGHT ?? "0.3");
122897
+ const vectorWeight = Number.isFinite(vectorWeightRaw) ? Math.min(1, Math.max(0, vectorWeightRaw)) : 0.3;
122898
+ return sorted.map(({ result, rrfScore, vectorRank, keywordRank, vectorScore, keywordScore, vectorRrfScore, lexicalRrfScore, memoryRrfScore }, index) => {
122899
+ const rrfNormalized = rrfScore / maxRrfScore;
122900
+ const vectorSimilarity = vectorScore || 0;
122901
+ const combinedScore = rrfNormalized * (1 - vectorWeight) + vectorSimilarity * vectorWeight;
122902
+ const centralityScore = typeof result.metadata?.centralityScore === "number" ? result.metadata.centralityScore : 0;
122903
+ const normalizedScore = Math.min(1, combinedScore * (1 + 0.2 * centralityScore));
122904
+ const memoryOnly = memoryRrfScore > 0 && vectorRrfScore === 0 && lexicalRrfScore === 0;
122905
+ const explanation = explainScores ? generateScoreExplanation(normalizedScore, rrfScore, vectorScore, keywordScore, vectorRank, keywordRank, index) : undefined;
122906
+ return {
122907
+ ...result,
122908
+ score: normalizedScore,
122909
+ explanation,
122910
+ metadata: {
122911
+ ...result.metadata,
122912
+ _rrfRawVectorScore: vectorScore ?? (memoryOnly ? 0 : undefined)
122913
+ }
122914
+ };
122915
+ });
122916
+ }
122917
+ function generateScoreExplanation(finalScore, rrfScore, vectorScore, keywordScore, vectorRank, keywordRank, combinedRank) {
122918
+ const parts = [];
122919
+ if (vectorScore != null && vectorRank != null) {
122920
+ parts.push(`Vector: ${(vectorScore * 100).toFixed(1)}% (rank #${vectorRank + 1})`);
122921
+ }
122922
+ if (keywordScore != null && keywordRank != null) {
122923
+ parts.push(`Keyword: ${(keywordScore * 100).toFixed(1)}% (rank #${keywordRank + 1})`);
122924
+ }
122925
+ const breakdown = parts.join(" + ") + ` \u2192 RRF: ${rrfScore.toFixed(4)} \u2192 Final: ${(finalScore * 100).toFixed(1)}%`;
122926
+ return {
122927
+ finalScore,
122928
+ vectorScore: vectorScore ?? undefined,
122929
+ keywordScore: keywordScore ?? undefined,
122930
+ rrfScore,
122931
+ vectorRank: vectorRank != null ? vectorRank + 1 : undefined,
122932
+ keywordRank: keywordRank != null ? keywordRank + 1 : undefined,
122933
+ combinedRank: combinedRank != null ? combinedRank + 1 : undefined,
122934
+ breakdown
122935
+ };
122936
+ }
122937
+ var RRF_K = 60;
122938
+ var init_result_fusion = __esm(() => {
122939
+ init_dist();
122940
122940
  });
122941
122941
 
122942
122942
  // ../../packages/core/dist/services/search/rlm-admin.js
@@ -123028,6 +123028,7 @@ var init_contextual_search_rlm = __esm(() => {
123028
123028
  init_rlm_indexing();
123029
123029
  init_rlm_synapse();
123030
123030
  init_rlm_search();
123031
+ init_result_fusion();
123031
123032
  init_rlm_admin();
123032
123033
  ContextualSearchRLM = class ContextualSearchRLM {
123033
123034
  keywordSearch;
@@ -123038,7 +123039,6 @@ var init_contextual_search_rlm = __esm(() => {
123038
123039
  symbolRepo;
123039
123040
  fileFilterCache;
123040
123041
  queryUnderstanding;
123041
- RRF_K = 60;
123042
123042
  initialized = false;
123043
123043
  static indexingLocks = new Map;
123044
123044
  injectedDeps;
@@ -123082,10 +123082,10 @@ var init_contextual_search_rlm = __esm(() => {
123082
123082
  return buildGraphStreamImpl(this, resultSets, maxResults, projectId, reportDegradation);
123083
123083
  }
123084
123084
  fuseResults(resultSets, query, explainScores = false) {
123085
- return fuseResultsImpl(this, resultSets, query, explainScores);
123085
+ return fuseResults(resultSets, query, explainScores);
123086
123086
  }
123087
123087
  generateScoreExplanation(finalScore, rrfScore, vectorScore, keywordScore, vectorRank, keywordRank, combinedRank) {
123088
- return generateScoreExplanationImpl(finalScore, rrfScore, vectorScore, keywordScore, vectorRank, keywordRank, combinedRank);
123088
+ return generateScoreExplanation(finalScore, rrfScore, vectorScore, keywordScore, vectorRank, keywordRank, combinedRank);
123089
123089
  }
123090
123090
  async addContextToResults(results, _projectId) {
123091
123091
  return addContextToResultsImpl(this, results, _projectId);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@massa-ai/mcp-client",
3
- "version": "1.10.0",
3
+ "version": "1.11.0",
4
4
  "description": "massa-ai MCP server - Semantic code search, memory, and context compression via Model Context Protocol",
5
5
  "author": "luizgmassa",
6
6
  "type": "module",
@@ -20,8 +20,8 @@
20
20
  "type-check": "tsc --noEmit"
21
21
  },
22
22
  "dependencies": {
23
- "@massa-ai/core": "^1.10.0",
24
- "@massa-ai/shared": "^1.10.0",
23
+ "@massa-ai/core": "^1.11.0",
24
+ "@massa-ai/shared": "^1.11.0",
25
25
  "@modelcontextprotocol/sdk": "^1.0.0"
26
26
  },
27
27
  "devDependencies": {