@massa-ai/mcp-client 1.9.0 → 1.9.2

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.
@@ -837,6 +837,20 @@ function validateCapturePolicyConfig(raw2) {
837
837
  ...p.maxIgnorePatterns !== undefined && { maxIgnorePatterns: p.maxIgnorePatterns }
838
838
  };
839
839
  }
840
+ function validateAllowedExtensionsConfig(raw2) {
841
+ if (!Array.isArray(raw2)) {
842
+ throw new TypeError("security.allowedExtensions must be an array of strings");
843
+ }
844
+ if (raw2.length === 0) {
845
+ throw new TypeError("security.allowedExtensions must not be empty \u2014 an empty allow-list indexes nothing; omit the key to use the defaults");
846
+ }
847
+ for (const ext of raw2) {
848
+ if (typeof ext !== "string" || !ext.startsWith(".") || ext.length < 2) {
849
+ throw new TypeError(`security.allowedExtensions[] must be dot-prefixed extensions (got ${JSON.stringify(ext)})`);
850
+ }
851
+ }
852
+ return [...raw2];
853
+ }
840
854
  function getGlobalDataDir() {
841
855
  const envOverride = process.env.MASSA_AI_DATA_DIR;
842
856
  if (envOverride && envOverride.trim())
@@ -1132,7 +1146,7 @@ var init_config = __esm(() => {
1132
1146
  sanitizeInputs: process.env.SANITIZE_INPUTS !== "false",
1133
1147
  maxIndexSize: 1e5,
1134
1148
  maxFileSize: 1024 * 1024,
1135
- allowedExtensions: [...DEFAULT_ALLOWED_EXTENSIONS],
1149
+ allowedExtensions: fileConfig.security?.allowedExtensions ? validateAllowedExtensionsConfig(fileConfig.security.allowedExtensions) : [...DEFAULT_ALLOWED_EXTENSIONS],
1136
1150
  excludePatterns: [
1137
1151
  "node_modules/**",
1138
1152
  ".git/**",
@@ -107584,14 +107598,140 @@ var require_ignore = __commonJS((exports, module) => {
107584
107598
  });
107585
107599
 
107586
107600
  // ../../packages/core/dist/services/search/capture-policy.js
107587
- var regexCache;
107601
+ function globToRegex(pattern) {
107602
+ let re = "^";
107603
+ let i = 0;
107604
+ while (i < pattern.length) {
107605
+ const ch = pattern[i];
107606
+ if (ch === "*") {
107607
+ if (pattern[i + 1] === "*") {
107608
+ re += ".*";
107609
+ i += 2;
107610
+ if (pattern[i] === "/")
107611
+ i += 1;
107612
+ } else {
107613
+ re += "[^/]*";
107614
+ i += 1;
107615
+ }
107616
+ } else if (ch === "?") {
107617
+ re += "[^/]";
107618
+ i += 1;
107619
+ } else if (ch === ".") {
107620
+ re += "\\.";
107621
+ i += 1;
107622
+ } else if ("+()^${}|[]\\".includes(ch)) {
107623
+ re += "\\" + ch;
107624
+ i += 1;
107625
+ } else {
107626
+ re += ch;
107627
+ i += 1;
107628
+ }
107629
+ }
107630
+ re += "$";
107631
+ return new RegExp(re);
107632
+ }
107633
+ function validatePolicy(policy, opts = {}) {
107634
+ if (!policy || typeof policy !== "object")
107635
+ throw new TypeError("policy must be an object");
107636
+ const p = policy;
107637
+ const allowedKeys = new Set(["rules", "maxMatchWork", "maxIgnorePatterns"]);
107638
+ if (opts.denyUnknownFields) {
107639
+ for (const key of Object.keys(p)) {
107640
+ if (!allowedKeys.has(key)) {
107641
+ throw new TypeError(`policy: unknown field "${key}" (denyUnknownFields=true)`);
107642
+ }
107643
+ }
107644
+ }
107645
+ if (!Array.isArray(p.rules))
107646
+ throw new TypeError("policy.rules must be an array");
107647
+ const dropCount = p.rules.filter((r) => r?.disposition === "Drop").length;
107648
+ const maxIgnore = typeof p.maxIgnorePatterns === "number" ? p.maxIgnorePatterns : MAX_IGNORE_PATTERNS2;
107649
+ if (dropCount > maxIgnore) {
107650
+ throw new TypeError(`policy: ${dropCount} Drop rules exceed maxIgnorePatterns=${maxIgnore}`);
107651
+ }
107652
+ if (p.maxMatchWork !== undefined) {
107653
+ if (typeof p.maxMatchWork !== "number" || p.maxMatchWork < 0) {
107654
+ throw new TypeError("policy.maxMatchWork must be a non-negative number");
107655
+ }
107656
+ }
107657
+ }
107658
+ function matchesGlob(path7, pattern) {
107659
+ let re = regexCache.get(pattern);
107660
+ if (!re) {
107661
+ re = globToRegex(pattern);
107662
+ regexCache.set(pattern, re);
107663
+ }
107664
+ return re.test(path7);
107665
+ }
107666
+ var MAX_MATCH_WORK = 1e5, MAX_IGNORE_PATTERNS2 = 1024, DEFAULT_POLICY, applyPolicy = (filePath, policy) => {
107667
+ const normalized = filePath.trim();
107668
+ for (const rule of policy.rules) {
107669
+ if (matchesGlob(normalized, rule.pattern))
107670
+ return rule.disposition;
107671
+ }
107672
+ return "Keep";
107673
+ }, regexCache;
107588
107674
  var init_capture_policy = __esm(() => {
107675
+ DEFAULT_POLICY = {
107676
+ rules: [
107677
+ { pattern: "**/node_modules/**", disposition: "Drop" },
107678
+ { pattern: "**/.git/**", disposition: "Drop" },
107679
+ { pattern: "**/dist/**", disposition: "Drop" },
107680
+ { pattern: "**/build/**", disposition: "Drop" },
107681
+ { pattern: "**/coverage/**", disposition: "Drop" },
107682
+ { pattern: ".env", disposition: "Drop" },
107683
+ { pattern: ".env.*", disposition: "Drop" },
107684
+ { pattern: "**/generated/**", disposition: "Drop" },
107685
+ { pattern: "**/*.generated.*", disposition: "Drop" },
107686
+ { pattern: "**/*.d.ts", disposition: "Drop" },
107687
+ { pattern: "**/__tests__/**", disposition: "Drop" },
107688
+ { pattern: "**/tests/**", disposition: "Drop" },
107689
+ { pattern: "**/*.test.ts", disposition: "Drop" },
107690
+ { pattern: "**/*.test.tsx", disposition: "Drop" },
107691
+ { pattern: "**/*.test.js", disposition: "Drop" },
107692
+ { pattern: "**/*.test.jsx", disposition: "Drop" },
107693
+ { pattern: "**/*.spec.ts", disposition: "Drop" },
107694
+ { pattern: "**/*.spec.tsx", disposition: "Drop" },
107695
+ { pattern: "**/*.spec.js", disposition: "Drop" },
107696
+ { pattern: "**/*.spec.jsx", disposition: "Drop" },
107697
+ { pattern: "**/benchmarks/**", disposition: "Drop" },
107698
+ { pattern: "**/fixtures/**", disposition: "Drop" },
107699
+ { pattern: "**/*.wasm*", disposition: "Drop" },
107700
+ { pattern: "**/*.min.*", disposition: "Drop" },
107701
+ { pattern: "**/*.map", disposition: "Drop" },
107702
+ { pattern: "**/lock.yaml", disposition: "Drop" },
107703
+ { pattern: "**/pnpm-lock.yaml", disposition: "Drop" },
107704
+ { pattern: "**/package-lock.json", disposition: "Drop" },
107705
+ { pattern: "**/bun.lockb", disposition: "Drop" },
107706
+ { pattern: "**/yarn.lock", disposition: "Drop" }
107707
+ ],
107708
+ maxMatchWork: MAX_MATCH_WORK,
107709
+ maxIgnorePatterns: MAX_IGNORE_PATTERNS2
107710
+ };
107589
107711
  regexCache = new Map;
107590
107712
  });
107591
107713
 
107592
107714
  // ../../packages/core/dist/services/search/ignore-patterns.js
107593
107715
  import fs2 from "fs/promises";
107594
107716
  import path7 from "path";
107717
+ function buildExtensionGlob(extensions) {
107718
+ return extensions.map((ext2) => `**/*${ext2}`);
107719
+ }
107720
+ function getActivePolicy() {
107721
+ if (cachedPolicy)
107722
+ return cachedPolicy;
107723
+ const fromConfig = config.get("capturePolicy");
107724
+ if (!fromConfig) {
107725
+ cachedPolicy = DEFAULT_POLICY;
107726
+ return cachedPolicy;
107727
+ }
107728
+ validatePolicy(fromConfig, { denyUnknownFields: true });
107729
+ cachedPolicy = fromConfig;
107730
+ return cachedPolicy;
107731
+ }
107732
+ function getActiveCapturePolicy() {
107733
+ return getActivePolicy();
107734
+ }
107595
107735
  async function loadProjectIgnore(projectPath) {
107596
107736
  const ig = ignore();
107597
107737
  ig.add(DEFAULT_IGNORES);
@@ -107610,7 +107750,7 @@ async function loadProjectIgnore(projectPath) {
107610
107750
  }
107611
107751
  return ig;
107612
107752
  }
107613
- var import_ignore3, ignore, DEFAULT_EXTENSIONS, DEFAULT_IGNORES;
107753
+ var import_ignore3, ignore, DEFAULT_EXTENSIONS, DEFAULT_IGNORES, cachedPolicy;
107614
107754
  var init_ignore_patterns = __esm(() => {
107615
107755
  init_dist();
107616
107756
  init_capture_policy();
@@ -107935,9 +108075,9 @@ class IndexManager {
107935
108075
  try {
107936
108076
  const securityConfig = config.get("security");
107937
108077
  const allowedExtensions = securityConfig.allowedExtensions || DEFAULT_ALLOWED_EXTENSIONS;
107938
- const combinedPattern = `**/*{${allowedExtensions.join(",")}}`;
108078
+ const patterns = buildExtensionGlob(allowedExtensions);
107939
108079
  const ig = await this.loadGitignore(projectPath);
107940
- const matches = await globAsync(combinedPattern, {
108080
+ const matches = await globAsync(patterns, {
107941
108081
  cwd: projectPath,
107942
108082
  nodir: true,
107943
108083
  dot: false
@@ -112242,7 +112382,7 @@ async function _indexProjectInternalImpl(rlm, projectPath, projectId, options =
112242
112382
  ];
112243
112383
  try {
112244
112384
  const ig = await loadGitignoreImpl(projectPath);
112245
- const files = await globAsync2(`**/*{${allowedExtensions.join(",")}}`, {
112385
+ const files = await globAsync2(buildExtensionGlob(allowedExtensions), {
112246
112386
  cwd: projectPath,
112247
112387
  absolute: true,
112248
112388
  nodir: true,
@@ -112694,6 +112834,9 @@ class MemoryRepositoryPg {
112694
112834
  if (filters.types && filters.types.length > 0) {
112695
112835
  conditions.push(import_prisma2.Prisma.sql`type = ANY(${filters.types}::text[])`);
112696
112836
  }
112837
+ if (filters.includePersistent === false) {
112838
+ conditions.push(import_prisma2.Prisma.sql`level <> ${MemoryLevel.PERSISTENT}`);
112839
+ }
112697
112840
  const whereClause = import_prisma2.Prisma.sql`WHERE ${import_prisma2.Prisma.join(conditions, " AND ")}`;
112698
112841
  const rows = await this.prisma.$queryRaw`
112699
112842
  SELECT id, content, type, level,
@@ -112728,6 +112871,8 @@ class MemoryRepositoryPg {
112728
112871
  conditions.push(import_prisma2.Prisma.sql`importance >= ${filters.minImportance}`);
112729
112872
  if (filters?.types && filters.types.length > 0)
112730
112873
  conditions.push(import_prisma2.Prisma.sql`type = ANY(${filters.types}::text[])`);
112874
+ if (filters?.includePersistent === false)
112875
+ conditions.push(import_prisma2.Prisma.sql`level <> ${MemoryLevel.PERSISTENT}`);
112731
112876
  const whereClause = import_prisma2.Prisma.sql`WHERE ${import_prisma2.Prisma.join(conditions, " AND ")}
112732
112877
  AND NOT EXISTS (
112733
112878
  SELECT 1 FROM memory_edges me
@@ -125339,20 +125484,21 @@ class DiscoverStage {
125339
125484
  payload: { projectId: ctx.projectId, projectPath: ctx.projectPath },
125340
125485
  timestamp: Date.now()
125341
125486
  });
125342
- const ig = await this.loadIgnore(ctx.projectPath, opts.includeTests ?? false);
125487
+ const includeTests = opts.includeTests ?? false;
125488
+ const ig = await this.loadIgnore(ctx.projectPath, includeTests);
125489
+ const policy = this.loadPolicy(includeTests);
125343
125490
  const allowedExts = config.get("security").allowedExtensions ?? DEFAULT_EXTENSIONS;
125344
125491
  let relPaths;
125345
125492
  if (opts.filesToProcess && opts.filesToProcess.length > 0) {
125346
125493
  relPaths = opts.filesToProcess;
125347
125494
  } else {
125348
- const pattern = `**/*{${allowedExts.join(",")}}`;
125349
- const found = await glob(pattern, {
125495
+ const found = await glob(buildExtensionGlob(allowedExts), {
125350
125496
  cwd: ctx.projectPath,
125351
125497
  nodir: true,
125352
125498
  dot: false,
125353
125499
  absolute: false
125354
125500
  });
125355
- relPaths = found.map((p) => path13.isAbsolute(p) ? path13.relative(ctx.projectPath, p) : p).filter((p) => !ig.ignores(p));
125501
+ relPaths = found.map((p) => path13.isAbsolute(p) ? path13.relative(ctx.projectPath, p) : p).filter((p) => !ig.ignores(p) && applyPolicy(p, policy) !== "Drop");
125356
125502
  }
125357
125503
  if (ctx.resumeCursor?.path) {
125358
125504
  const cursorPath = ctx.resumeCursor.path;
@@ -125438,6 +125584,15 @@ class DiscoverStage {
125438
125584
  throw new Error(`required_file_unreadable:${relativePath}:${err.message}`);
125439
125585
  }
125440
125586
  }
125587
+ loadPolicy(includeTests) {
125588
+ const policy = getActiveCapturePolicy();
125589
+ if (!includeTests)
125590
+ return policy;
125591
+ return {
125592
+ ...policy,
125593
+ rules: policy.rules.filter((rule) => !(rule.disposition === "Drop" && TEST_IGNORE_PATTERNS.has(rule.pattern)))
125594
+ };
125595
+ }
125441
125596
  async loadIgnore(projectPath, includeTests) {
125442
125597
  if (!includeTests)
125443
125598
  return loadProjectIgnore(projectPath);
@@ -125463,6 +125618,7 @@ var init_discover = __esm(() => {
125463
125618
  init_dist();
125464
125619
  init_symbol_repository_factory();
125465
125620
  init_ignore_patterns();
125621
+ init_capture_policy();
125466
125622
  import_ignore4 = __toESM(require_ignore(), 1);
125467
125623
  ignore2 = import_ignore4.default.default ?? import_ignore4.default;
125468
125624
  TEST_IGNORE_PATTERNS = new Set([
@@ -128292,19 +128448,22 @@ class StructuralResolverRegistry {
128292
128448
  return resolver;
128293
128449
  }
128294
128450
  }
128451
+ function declarationGroupKey(file2, qualifiedName) {
128452
+ return `${file2}\x00${qualifiedName}`;
128453
+ }
128295
128454
  function buildStructuralResolverDefinitions(documents) {
128296
128455
  const groups = new Map;
128297
128456
  const exportedRoots = new Set;
128298
128457
  for (const document2 of documents)
128299
128458
  for (const symbol27 of document2.structure.symbols) {
128300
- const key = `${document2.file}\x00${symbol27.qualifiedName}\x00${symbol27.kind}`;
128459
+ const key = declarationGroupKey(document2.file, symbol27.qualifiedName);
128301
128460
  groups.set(key, (groups.get(key) ?? 0) + 1);
128302
128461
  if (symbol27.exported && symbol27.qualifiedName === symbol27.name) {
128303
128462
  exportedRoots.add(`${document2.file}\x00${symbol27.qualifiedName.split(".")[0]}`);
128304
128463
  }
128305
128464
  }
128306
128465
  return Object.freeze(documents.flatMap((document2) => document2.structure.symbols.map((symbol27) => {
128307
- const key = `${document2.file}\x00${symbol27.qualifiedName}\x00${symbol27.kind}`;
128466
+ const key = declarationGroupKey(document2.file, symbol27.qualifiedName);
128308
128467
  const visibleNested = document2.dialect === "java" ? symbol27.signatureMaterial.modifiers.includes("public") && (["class", "interface", "enum"].includes(symbol27.kind) || symbol27.signatureMaterial.modifiers.includes("static")) : !symbol27.signatureMaterial.modifiers.includes("private");
128309
128468
  const isExportMarker = symbol27.kind === "export";
128310
128469
  return Object.freeze({
@@ -131481,7 +131640,7 @@ class MemoryController {
131481
131640
  types: types6,
131482
131641
  minImportance = 0.3,
131483
131642
  limit = 10,
131484
- includePersistent: _includePersistent = true,
131643
+ includePersistent = true,
131485
131644
  includeRelated = false
131486
131645
  } = input;
131487
131646
  logger.info("Searching memories", {
@@ -131499,7 +131658,8 @@ class MemoryController {
131499
131658
  projectId,
131500
131659
  agentId,
131501
131660
  minImportance,
131502
- types: types6
131661
+ types: types6,
131662
+ includePersistent
131503
131663
  });
131504
131664
  logger.info("FTS search completed", {
131505
131665
  foundResults: ftsRows.length,
package/dist/index.js CHANGED
@@ -25834,6 +25834,20 @@ function validateCapturePolicyConfig(raw2) {
25834
25834
  ...p.maxIgnorePatterns !== undefined && { maxIgnorePatterns: p.maxIgnorePatterns }
25835
25835
  };
25836
25836
  }
25837
+ function validateAllowedExtensionsConfig(raw2) {
25838
+ if (!Array.isArray(raw2)) {
25839
+ throw new TypeError("security.allowedExtensions must be an array of strings");
25840
+ }
25841
+ if (raw2.length === 0) {
25842
+ throw new TypeError("security.allowedExtensions must not be empty \u2014 an empty allow-list indexes nothing; omit the key to use the defaults");
25843
+ }
25844
+ for (const ext of raw2) {
25845
+ if (typeof ext !== "string" || !ext.startsWith(".") || ext.length < 2) {
25846
+ throw new TypeError(`security.allowedExtensions[] must be dot-prefixed extensions (got ${JSON.stringify(ext)})`);
25847
+ }
25848
+ }
25849
+ return [...raw2];
25850
+ }
25837
25851
  function getGlobalDataDir() {
25838
25852
  const envOverride = process.env.MASSA_AI_DATA_DIR;
25839
25853
  if (envOverride && envOverride.trim())
@@ -26129,7 +26143,7 @@ var init_config = __esm(() => {
26129
26143
  sanitizeInputs: process.env.SANITIZE_INPUTS !== "false",
26130
26144
  maxIndexSize: 1e5,
26131
26145
  maxFileSize: 1024 * 1024,
26132
- allowedExtensions: [...DEFAULT_ALLOWED_EXTENSIONS],
26146
+ allowedExtensions: fileConfig.security?.allowedExtensions ? validateAllowedExtensionsConfig(fileConfig.security.allowedExtensions) : [...DEFAULT_ALLOWED_EXTENSIONS],
26133
26147
  excludePatterns: [
26134
26148
  "node_modules/**",
26135
26149
  ".git/**",
@@ -114143,14 +114157,140 @@ var require_ignore = __commonJS((exports, module) => {
114143
114157
  });
114144
114158
 
114145
114159
  // ../../packages/core/dist/services/search/capture-policy.js
114146
- var regexCache;
114160
+ function globToRegex(pattern) {
114161
+ let re = "^";
114162
+ let i = 0;
114163
+ while (i < pattern.length) {
114164
+ const ch = pattern[i];
114165
+ if (ch === "*") {
114166
+ if (pattern[i + 1] === "*") {
114167
+ re += ".*";
114168
+ i += 2;
114169
+ if (pattern[i] === "/")
114170
+ i += 1;
114171
+ } else {
114172
+ re += "[^/]*";
114173
+ i += 1;
114174
+ }
114175
+ } else if (ch === "?") {
114176
+ re += "[^/]";
114177
+ i += 1;
114178
+ } else if (ch === ".") {
114179
+ re += "\\.";
114180
+ i += 1;
114181
+ } else if ("+()^${}|[]\\".includes(ch)) {
114182
+ re += "\\" + ch;
114183
+ i += 1;
114184
+ } else {
114185
+ re += ch;
114186
+ i += 1;
114187
+ }
114188
+ }
114189
+ re += "$";
114190
+ return new RegExp(re);
114191
+ }
114192
+ function validatePolicy(policy, opts = {}) {
114193
+ if (!policy || typeof policy !== "object")
114194
+ throw new TypeError("policy must be an object");
114195
+ const p = policy;
114196
+ const allowedKeys = new Set(["rules", "maxMatchWork", "maxIgnorePatterns"]);
114197
+ if (opts.denyUnknownFields) {
114198
+ for (const key of Object.keys(p)) {
114199
+ if (!allowedKeys.has(key)) {
114200
+ throw new TypeError(`policy: unknown field "${key}" (denyUnknownFields=true)`);
114201
+ }
114202
+ }
114203
+ }
114204
+ if (!Array.isArray(p.rules))
114205
+ throw new TypeError("policy.rules must be an array");
114206
+ const dropCount = p.rules.filter((r) => r?.disposition === "Drop").length;
114207
+ const maxIgnore = typeof p.maxIgnorePatterns === "number" ? p.maxIgnorePatterns : MAX_IGNORE_PATTERNS2;
114208
+ if (dropCount > maxIgnore) {
114209
+ throw new TypeError(`policy: ${dropCount} Drop rules exceed maxIgnorePatterns=${maxIgnore}`);
114210
+ }
114211
+ if (p.maxMatchWork !== undefined) {
114212
+ if (typeof p.maxMatchWork !== "number" || p.maxMatchWork < 0) {
114213
+ throw new TypeError("policy.maxMatchWork must be a non-negative number");
114214
+ }
114215
+ }
114216
+ }
114217
+ function matchesGlob(path7, pattern) {
114218
+ let re = regexCache.get(pattern);
114219
+ if (!re) {
114220
+ re = globToRegex(pattern);
114221
+ regexCache.set(pattern, re);
114222
+ }
114223
+ return re.test(path7);
114224
+ }
114225
+ var MAX_MATCH_WORK = 1e5, MAX_IGNORE_PATTERNS2 = 1024, DEFAULT_POLICY, applyPolicy = (filePath, policy) => {
114226
+ const normalized = filePath.trim();
114227
+ for (const rule of policy.rules) {
114228
+ if (matchesGlob(normalized, rule.pattern))
114229
+ return rule.disposition;
114230
+ }
114231
+ return "Keep";
114232
+ }, regexCache;
114147
114233
  var init_capture_policy = __esm(() => {
114234
+ DEFAULT_POLICY = {
114235
+ rules: [
114236
+ { pattern: "**/node_modules/**", disposition: "Drop" },
114237
+ { pattern: "**/.git/**", disposition: "Drop" },
114238
+ { pattern: "**/dist/**", disposition: "Drop" },
114239
+ { pattern: "**/build/**", disposition: "Drop" },
114240
+ { pattern: "**/coverage/**", disposition: "Drop" },
114241
+ { pattern: ".env", disposition: "Drop" },
114242
+ { pattern: ".env.*", disposition: "Drop" },
114243
+ { pattern: "**/generated/**", disposition: "Drop" },
114244
+ { pattern: "**/*.generated.*", disposition: "Drop" },
114245
+ { pattern: "**/*.d.ts", disposition: "Drop" },
114246
+ { pattern: "**/__tests__/**", disposition: "Drop" },
114247
+ { pattern: "**/tests/**", disposition: "Drop" },
114248
+ { pattern: "**/*.test.ts", disposition: "Drop" },
114249
+ { pattern: "**/*.test.tsx", disposition: "Drop" },
114250
+ { pattern: "**/*.test.js", disposition: "Drop" },
114251
+ { pattern: "**/*.test.jsx", disposition: "Drop" },
114252
+ { pattern: "**/*.spec.ts", disposition: "Drop" },
114253
+ { pattern: "**/*.spec.tsx", disposition: "Drop" },
114254
+ { pattern: "**/*.spec.js", disposition: "Drop" },
114255
+ { pattern: "**/*.spec.jsx", disposition: "Drop" },
114256
+ { pattern: "**/benchmarks/**", disposition: "Drop" },
114257
+ { pattern: "**/fixtures/**", disposition: "Drop" },
114258
+ { pattern: "**/*.wasm*", disposition: "Drop" },
114259
+ { pattern: "**/*.min.*", disposition: "Drop" },
114260
+ { pattern: "**/*.map", disposition: "Drop" },
114261
+ { pattern: "**/lock.yaml", disposition: "Drop" },
114262
+ { pattern: "**/pnpm-lock.yaml", disposition: "Drop" },
114263
+ { pattern: "**/package-lock.json", disposition: "Drop" },
114264
+ { pattern: "**/bun.lockb", disposition: "Drop" },
114265
+ { pattern: "**/yarn.lock", disposition: "Drop" }
114266
+ ],
114267
+ maxMatchWork: MAX_MATCH_WORK,
114268
+ maxIgnorePatterns: MAX_IGNORE_PATTERNS2
114269
+ };
114148
114270
  regexCache = new Map;
114149
114271
  });
114150
114272
 
114151
114273
  // ../../packages/core/dist/services/search/ignore-patterns.js
114152
114274
  import fs2 from "fs/promises";
114153
114275
  import path7 from "path";
114276
+ function buildExtensionGlob(extensions) {
114277
+ return extensions.map((ext2) => `**/*${ext2}`);
114278
+ }
114279
+ function getActivePolicy() {
114280
+ if (cachedPolicy)
114281
+ return cachedPolicy;
114282
+ const fromConfig = config2.get("capturePolicy");
114283
+ if (!fromConfig) {
114284
+ cachedPolicy = DEFAULT_POLICY;
114285
+ return cachedPolicy;
114286
+ }
114287
+ validatePolicy(fromConfig, { denyUnknownFields: true });
114288
+ cachedPolicy = fromConfig;
114289
+ return cachedPolicy;
114290
+ }
114291
+ function getActiveCapturePolicy() {
114292
+ return getActivePolicy();
114293
+ }
114154
114294
  async function loadProjectIgnore(projectPath) {
114155
114295
  const ig = ignore();
114156
114296
  ig.add(DEFAULT_IGNORES);
@@ -114169,7 +114309,7 @@ async function loadProjectIgnore(projectPath) {
114169
114309
  }
114170
114310
  return ig;
114171
114311
  }
114172
- var import_ignore3, ignore, DEFAULT_EXTENSIONS, DEFAULT_IGNORES;
114312
+ var import_ignore3, ignore, DEFAULT_EXTENSIONS, DEFAULT_IGNORES, cachedPolicy;
114173
114313
  var init_ignore_patterns = __esm(() => {
114174
114314
  init_dist();
114175
114315
  init_capture_policy();
@@ -114494,9 +114634,9 @@ class IndexManager {
114494
114634
  try {
114495
114635
  const securityConfig = config2.get("security");
114496
114636
  const allowedExtensions = securityConfig.allowedExtensions || DEFAULT_ALLOWED_EXTENSIONS;
114497
- const combinedPattern = `**/*{${allowedExtensions.join(",")}}`;
114637
+ const patterns = buildExtensionGlob(allowedExtensions);
114498
114638
  const ig = await this.loadGitignore(projectPath);
114499
- const matches = await globAsync(combinedPattern, {
114639
+ const matches = await globAsync(patterns, {
114500
114640
  cwd: projectPath,
114501
114641
  nodir: true,
114502
114642
  dot: false
@@ -118801,7 +118941,7 @@ async function _indexProjectInternalImpl(rlm, projectPath, projectId, options =
118801
118941
  ];
118802
118942
  try {
118803
118943
  const ig = await loadGitignoreImpl(projectPath);
118804
- const files = await globAsync2(`**/*{${allowedExtensions.join(",")}}`, {
118944
+ const files = await globAsync2(buildExtensionGlob(allowedExtensions), {
118805
118945
  cwd: projectPath,
118806
118946
  absolute: true,
118807
118947
  nodir: true,
@@ -119253,6 +119393,9 @@ class MemoryRepositoryPg {
119253
119393
  if (filters.types && filters.types.length > 0) {
119254
119394
  conditions.push(import_prisma2.Prisma.sql`type = ANY(${filters.types}::text[])`);
119255
119395
  }
119396
+ if (filters.includePersistent === false) {
119397
+ conditions.push(import_prisma2.Prisma.sql`level <> ${MemoryLevel.PERSISTENT}`);
119398
+ }
119256
119399
  const whereClause = import_prisma2.Prisma.sql`WHERE ${import_prisma2.Prisma.join(conditions, " AND ")}`;
119257
119400
  const rows = await this.prisma.$queryRaw`
119258
119401
  SELECT id, content, type, level,
@@ -119287,6 +119430,8 @@ class MemoryRepositoryPg {
119287
119430
  conditions.push(import_prisma2.Prisma.sql`importance >= ${filters.minImportance}`);
119288
119431
  if (filters?.types && filters.types.length > 0)
119289
119432
  conditions.push(import_prisma2.Prisma.sql`type = ANY(${filters.types}::text[])`);
119433
+ if (filters?.includePersistent === false)
119434
+ conditions.push(import_prisma2.Prisma.sql`level <> ${MemoryLevel.PERSISTENT}`);
119290
119435
  const whereClause = import_prisma2.Prisma.sql`WHERE ${import_prisma2.Prisma.join(conditions, " AND ")}
119291
119436
  AND NOT EXISTS (
119292
119437
  SELECT 1 FROM memory_edges me
@@ -123534,20 +123679,21 @@ class DiscoverStage {
123534
123679
  payload: { projectId: ctx.projectId, projectPath: ctx.projectPath },
123535
123680
  timestamp: Date.now()
123536
123681
  });
123537
- const ig = await this.loadIgnore(ctx.projectPath, opts.includeTests ?? false);
123682
+ const includeTests = opts.includeTests ?? false;
123683
+ const ig = await this.loadIgnore(ctx.projectPath, includeTests);
123684
+ const policy = this.loadPolicy(includeTests);
123538
123685
  const allowedExts = config2.get("security").allowedExtensions ?? DEFAULT_EXTENSIONS;
123539
123686
  let relPaths;
123540
123687
  if (opts.filesToProcess && opts.filesToProcess.length > 0) {
123541
123688
  relPaths = opts.filesToProcess;
123542
123689
  } else {
123543
- const pattern = `**/*{${allowedExts.join(",")}}`;
123544
- const found = await glob(pattern, {
123690
+ const found = await glob(buildExtensionGlob(allowedExts), {
123545
123691
  cwd: ctx.projectPath,
123546
123692
  nodir: true,
123547
123693
  dot: false,
123548
123694
  absolute: false
123549
123695
  });
123550
- relPaths = found.map((p) => path10.isAbsolute(p) ? path10.relative(ctx.projectPath, p) : p).filter((p) => !ig.ignores(p));
123696
+ relPaths = found.map((p) => path10.isAbsolute(p) ? path10.relative(ctx.projectPath, p) : p).filter((p) => !ig.ignores(p) && applyPolicy(p, policy) !== "Drop");
123551
123697
  }
123552
123698
  if (ctx.resumeCursor?.path) {
123553
123699
  const cursorPath = ctx.resumeCursor.path;
@@ -123633,6 +123779,15 @@ class DiscoverStage {
123633
123779
  throw new Error(`required_file_unreadable:${relativePath}:${err.message}`);
123634
123780
  }
123635
123781
  }
123782
+ loadPolicy(includeTests) {
123783
+ const policy = getActiveCapturePolicy();
123784
+ if (!includeTests)
123785
+ return policy;
123786
+ return {
123787
+ ...policy,
123788
+ rules: policy.rules.filter((rule) => !(rule.disposition === "Drop" && TEST_IGNORE_PATTERNS.has(rule.pattern)))
123789
+ };
123790
+ }
123636
123791
  async loadIgnore(projectPath, includeTests) {
123637
123792
  if (!includeTests)
123638
123793
  return loadProjectIgnore(projectPath);
@@ -123658,6 +123813,7 @@ var init_discover = __esm(() => {
123658
123813
  init_dist();
123659
123814
  init_symbol_repository_factory();
123660
123815
  init_ignore_patterns();
123816
+ init_capture_policy();
123661
123817
  import_ignore4 = __toESM(require_ignore(), 1);
123662
123818
  ignore2 = import_ignore4.default.default ?? import_ignore4.default;
123663
123819
  TEST_IGNORE_PATTERNS = new Set([
@@ -126487,19 +126643,22 @@ class StructuralResolverRegistry {
126487
126643
  return resolver;
126488
126644
  }
126489
126645
  }
126646
+ function declarationGroupKey(file2, qualifiedName) {
126647
+ return `${file2}\x00${qualifiedName}`;
126648
+ }
126490
126649
  function buildStructuralResolverDefinitions(documents) {
126491
126650
  const groups = new Map;
126492
126651
  const exportedRoots = new Set;
126493
126652
  for (const document2 of documents)
126494
126653
  for (const symbol27 of document2.structure.symbols) {
126495
- const key = `${document2.file}\x00${symbol27.qualifiedName}\x00${symbol27.kind}`;
126654
+ const key = declarationGroupKey(document2.file, symbol27.qualifiedName);
126496
126655
  groups.set(key, (groups.get(key) ?? 0) + 1);
126497
126656
  if (symbol27.exported && symbol27.qualifiedName === symbol27.name) {
126498
126657
  exportedRoots.add(`${document2.file}\x00${symbol27.qualifiedName.split(".")[0]}`);
126499
126658
  }
126500
126659
  }
126501
126660
  return Object.freeze(documents.flatMap((document2) => document2.structure.symbols.map((symbol27) => {
126502
- const key = `${document2.file}\x00${symbol27.qualifiedName}\x00${symbol27.kind}`;
126661
+ const key = declarationGroupKey(document2.file, symbol27.qualifiedName);
126503
126662
  const visibleNested = document2.dialect === "java" ? symbol27.signatureMaterial.modifiers.includes("public") && (["class", "interface", "enum"].includes(symbol27.kind) || symbol27.signatureMaterial.modifiers.includes("static")) : !symbol27.signatureMaterial.modifiers.includes("private");
126504
126663
  const isExportMarker = symbol27.kind === "export";
126505
126664
  return Object.freeze({
@@ -132790,7 +132949,7 @@ class MemoryController {
132790
132949
  types: types6,
132791
132950
  minImportance = 0.3,
132792
132951
  limit = 10,
132793
- includePersistent: _includePersistent = true,
132952
+ includePersistent = true,
132794
132953
  includeRelated = false
132795
132954
  } = input;
132796
132955
  logger.info("Searching memories", {
@@ -132808,7 +132967,8 @@ class MemoryController {
132808
132967
  projectId,
132809
132968
  agentId,
132810
132969
  minImportance,
132811
- types: types6
132970
+ types: types6,
132971
+ includePersistent
132812
132972
  });
132813
132973
  logger.info("FTS search completed", {
132814
132974
  foundResults: ftsRows.length,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@massa-ai/mcp-client",
3
- "version": "1.9.0",
3
+ "version": "1.9.2",
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.9.0",
24
- "@massa-ai/shared": "^1.9.0",
23
+ "@massa-ai/core": "^1.9.2",
24
+ "@massa-ai/shared": "^1.9.2",
25
25
  "@modelcontextprotocol/sdk": "^1.0.0"
26
26
  },
27
27
  "devDependencies": {