@massa-ai/mcp-client 1.7.0 → 1.8.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.
@@ -542,6 +542,9 @@ var init_massa_ai_config = __esm(() => {
542
542
  },
543
543
  handoffs: {
544
544
  enabled: true
545
+ },
546
+ security: {
547
+ corsOrigins: []
545
548
  }
546
549
  };
547
550
  });
@@ -563,6 +566,7 @@ __export(exports_config_loader, {
563
566
  import fs from "fs";
564
567
  import path3 from "path";
565
568
  import os2 from "os";
569
+ import crypto2 from "crypto";
566
570
  function getConfigDir() {
567
571
  return CONFIG_DIR;
568
572
  }
@@ -591,7 +595,8 @@ function loadConfig() {
591
595
  llm: { ...defaultMassaAiConfig.llm, ...userConfig.llm },
592
596
  memory: { ...defaultMassaAiConfig.memory, ...userConfig.memory },
593
597
  hooks: { ...defaultMassaAiConfig.hooks, ...userConfig.hooks },
594
- handoffs: { ...defaultMassaAiConfig.handoffs, ...userConfig.handoffs }
598
+ handoffs: { ...defaultMassaAiConfig.handoffs, ...userConfig.handoffs },
599
+ security: { ...defaultMassaAiConfig.security, ...userConfig.security }
595
600
  };
596
601
  } catch (error) {
597
602
  console.error(`Error loading config from ${CONFIG_FILE}:`, error);
@@ -635,7 +640,17 @@ function saveConfig(config) {
635
640
  if (!fs.existsSync(CONFIG_DIR)) {
636
641
  fs.mkdirSync(CONFIG_DIR, { recursive: true });
637
642
  }
638
- fs.writeFileSync(CONFIG_FILE, JSON.stringify(config, null, 2));
643
+ const unique = `${process.pid}.${++tempFileCounter}.${crypto2.randomBytes(6).toString("hex")}`;
644
+ const tempFile = path3.join(CONFIG_DIR, `.config.json.${unique}.tmp`);
645
+ try {
646
+ fs.writeFileSync(tempFile, JSON.stringify(config, null, 2));
647
+ fs.renameSync(tempFile, CONFIG_FILE);
648
+ } catch (error) {
649
+ try {
650
+ fs.unlinkSync(tempFile);
651
+ } catch {}
652
+ throw error;
653
+ }
639
654
  }
640
655
  function initConfig() {
641
656
  if (!fs.existsSync(CONFIG_FILE)) {
@@ -663,7 +678,7 @@ function getConfigForEnv() {
663
678
  env.ENABLE_METRICS = String(config.logging.enableMetrics);
664
679
  return env;
665
680
  }
666
- var CONFIG_DIR, CONFIG_FILE, migrationAttempted = false;
681
+ var CONFIG_DIR, CONFIG_FILE, migrationAttempted = false, tempFileCounter = 0;
667
682
  var init_config_loader = __esm(() => {
668
683
  init_massa_ai_config();
669
684
  init_xdg();
@@ -706,9 +721,18 @@ var init_env = __esm(() => {
706
721
  if (cfg.embedding?.apiKey && !process.env.OLLAMA_API_KEY) {
707
722
  process.env.OLLAMA_API_KEY = cfg.embedding.apiKey;
708
723
  }
724
+ const securityApiKey = cfg.security?.apiKey?.trim();
725
+ if (securityApiKey && !process.env.MASSA_AI_API_KEY?.trim()) {
726
+ process.env.MASSA_AI_API_KEY = securityApiKey;
727
+ }
709
728
  } catch {}
710
729
  });
711
730
 
731
+ // ../../packages/shared/dist/config/api-key.js
732
+ var init_api_key = __esm(() => {
733
+ init_config_loader();
734
+ });
735
+
712
736
  // ../../packages/shared/dist/config/db-guard.js
713
737
  function requirePostgresDatabaseUrl(databaseUrl = process.env.DATABASE_URL) {
714
738
  if (!databaseUrl?.trim()) {
@@ -765,6 +789,13 @@ function envString(key, fallback) {
765
789
  const s = process.env[key];
766
790
  return s === undefined || s === "" ? fallback : s;
767
791
  }
792
+ function envList(key, fallback) {
793
+ const s = process.env[key];
794
+ if (s === undefined)
795
+ return fallback;
796
+ const parsed = s.split(",").map((v) => v.trim()).filter((v) => v.length > 0);
797
+ return parsed.length > 0 ? parsed : fallback;
798
+ }
768
799
  function validateCapturePolicyConfig(raw2) {
769
800
  if (!raw2 || typeof raw2 !== "object")
770
801
  throw new TypeError("capturePolicy must be an object");
@@ -952,6 +983,7 @@ var init_config = __esm(() => {
952
983
  init_config_loader();
953
984
  init_massa_ai_config();
954
985
  init_config_loader();
986
+ init_api_key();
955
987
  DEFAULT_ALLOWED_EXTENSIONS = [
956
988
  ".ts",
957
989
  ".js",
@@ -1111,7 +1143,8 @@ var init_config = __esm(() => {
1111
1143
  "**/generated/**",
1112
1144
  "*.min.js",
1113
1145
  "*.min.css"
1114
- ]
1146
+ ],
1147
+ corsOrigins: envList("MASSA_AI_API_CORS_ORIGINS", fileConfig.security?.corsOrigins ?? [])
1115
1148
  },
1116
1149
  logging: {
1117
1150
  level: process.env.LOG_LEVEL || fileConfig.logging?.level || "info",
@@ -99799,7 +99832,7 @@ var require_cert_signatures = __commonJS((exports, module) => {
99799
99832
 
99800
99833
  // ../../node_modules/pg/lib/crypto/sasl.js
99801
99834
  var require_sasl = __commonJS((exports, module) => {
99802
- var crypto2 = require_utils4();
99835
+ var crypto3 = require_utils4();
99803
99836
  var { signatureAlgorithmHashFromCertificate } = require_cert_signatures();
99804
99837
  function saslprep(password) {
99805
99838
  const nonAsciiSpace = /[\u00A0\u1680\u2000-\u200B\u202F\u205F\u3000]/g;
@@ -99818,7 +99851,7 @@ var require_sasl = __commonJS((exports, module) => {
99818
99851
  if (mechanism === "SCRAM-SHA-256-PLUS" && typeof stream2.getPeerCertificate !== "function") {
99819
99852
  throw new Error("SASL: Mechanism SCRAM-SHA-256-PLUS requires a certificate");
99820
99853
  }
99821
- const clientNonce = crypto2.randomBytes(18).toString("base64");
99854
+ const clientNonce = crypto3.randomBytes(18).toString("base64");
99822
99855
  const gs2Header = mechanism === "SCRAM-SHA-256-PLUS" ? "p=tls-server-end-point" : stream2 ? "y" : "n";
99823
99856
  return {
99824
99857
  mechanism,
@@ -99859,20 +99892,20 @@ var require_sasl = __commonJS((exports, module) => {
99859
99892
  let hashName = signatureAlgorithmHashFromCertificate(peerCert);
99860
99893
  if (hashName === "MD5" || hashName === "SHA-1")
99861
99894
  hashName = "SHA-256";
99862
- const certHash = await crypto2.hashByName(hashName, peerCert);
99895
+ const certHash = await crypto3.hashByName(hashName, peerCert);
99863
99896
  const bindingData = Buffer.concat([Buffer.from("p=tls-server-end-point,,"), Buffer.from(certHash)]);
99864
99897
  channelBinding = bindingData.toString("base64");
99865
99898
  }
99866
99899
  const clientFinalMessageWithoutProof = "c=" + channelBinding + ",r=" + sv.nonce;
99867
99900
  const authMessage = clientFirstMessageBare + "," + serverFirstMessage + "," + clientFinalMessageWithoutProof;
99868
99901
  const saltBytes = Buffer.from(sv.salt, "base64");
99869
- const saltedPassword = await crypto2.deriveKey(saslprep(password), saltBytes, sv.iteration);
99870
- const clientKey = await crypto2.hmacSha256(saltedPassword, "Client Key");
99871
- const storedKey = await crypto2.sha256(clientKey);
99872
- const clientSignature = await crypto2.hmacSha256(storedKey, authMessage);
99902
+ const saltedPassword = await crypto3.deriveKey(saslprep(password), saltBytes, sv.iteration);
99903
+ const clientKey = await crypto3.hmacSha256(saltedPassword, "Client Key");
99904
+ const storedKey = await crypto3.sha256(clientKey);
99905
+ const clientSignature = await crypto3.hmacSha256(storedKey, authMessage);
99873
99906
  const clientProof = xorBuffers(Buffer.from(clientKey), Buffer.from(clientSignature)).toString("base64");
99874
- const serverKey = await crypto2.hmacSha256(saltedPassword, "Server Key");
99875
- const serverSignatureBytes = await crypto2.hmacSha256(serverKey, authMessage);
99907
+ const serverKey = await crypto3.hmacSha256(saltedPassword, "Server Key");
99908
+ const serverSignatureBytes = await crypto3.hmacSha256(serverKey, authMessage);
99876
99909
  session.message = "SASLResponse";
99877
99910
  session.serverSignature = Buffer.from(serverSignatureBytes).toString("base64");
99878
99911
  session.response = clientFinalMessageWithoutProof + ",p=" + clientProof;
@@ -101980,7 +102013,7 @@ var require_client2 = __commonJS((exports, module) => {
101980
102013
  var Query = require_query();
101981
102014
  var defaults2 = require_defaults();
101982
102015
  var Connection = require_connection();
101983
- var crypto2 = require_utils4();
102016
+ var crypto3 = require_utils4();
101984
102017
  var activeQueryDeprecationNotice = nodeUtils.deprecate(() => {}, "Client.activeQuery is deprecated and will be removed in pg@9.0");
101985
102018
  var queryQueueDeprecationNotice = nodeUtils.deprecate(() => {}, "Client.queryQueue is deprecated and will be removed in pg@9.0.");
101986
102019
  var pgPassDeprecationNotice = nodeUtils.deprecate(() => {}, "pgpass support is deprecated and will be removed in pg@9.0. " + "You can provide an async function as the password property to the Client/Pool constructor that returns a password instead. Within this function you can call the pgpass module in your own code.");
@@ -102212,7 +102245,7 @@ var require_client2 = __commonJS((exports, module) => {
102212
102245
  _handleAuthMD5Password(msg) {
102213
102246
  this._getPassword(async () => {
102214
102247
  try {
102215
- const hashedPassword = await crypto2.postgresMd5PasswordHash(this.user, this.password, msg.salt);
102248
+ const hashedPassword = await crypto3.postgresMd5PasswordHash(this.user, this.password, msg.salt);
102216
102249
  this.connection.password(hashedPassword);
102217
102250
  } catch (e) {
102218
102251
  this.emit("error", e);
@@ -105267,10 +105300,7 @@ class EmbeddingService {
105267
105300
  async embed(text2) {
105268
105301
  await this.ensureInitialized();
105269
105302
  if (!this.provider) {
105270
- const msg = "No embedding provider available. Configure OLLAMA_BASE_URL or an API key.";
105271
- if (false) {}
105272
- logger.warn(msg + " Using random embeddings (dev only).");
105273
- return new Array(384).fill(0).map(() => Math.random());
105303
+ throw new Error(NO_PROVIDER_MESSAGE);
105274
105304
  }
105275
105305
  try {
105276
105306
  return await this.provider.embedQuery(text2);
@@ -105284,10 +105314,7 @@ class EmbeddingService {
105284
105314
  async embedBatch(texts) {
105285
105315
  await this.ensureInitialized();
105286
105316
  if (!this.provider) {
105287
- const msg = "No embedding provider available. Configure OLLAMA_BASE_URL or an API key.";
105288
- if (false) {}
105289
- logger.warn(msg + " Using random embeddings (dev only).");
105290
- return texts.map(() => new Array(384).fill(0).map(() => Math.random()));
105317
+ throw new Error(NO_PROVIDER_MESSAGE);
105291
105318
  }
105292
105319
  try {
105293
105320
  return await this.provider.embedBatch(texts);
@@ -105299,7 +105326,10 @@ class EmbeddingService {
105299
105326
  }
105300
105327
  }
105301
105328
  getDimensions() {
105302
- return this.provider?.dimensions || 384;
105329
+ if (!this.provider) {
105330
+ throw new Error(NO_PROVIDER_MESSAGE);
105331
+ }
105332
+ return this.provider.dimensions;
105303
105333
  }
105304
105334
  getProviderInfo() {
105305
105335
  if (!this.provider)
@@ -105316,6 +105346,7 @@ class EmbeddingService {
105316
105346
  return dotProduct / (magnitude1 * magnitude2);
105317
105347
  }
105318
105348
  }
105349
+ var NO_PROVIDER_MESSAGE = "No embedding provider available. Configure OLLAMA_BASE_URL or an API key.";
105319
105350
  var init_embedding_service = __esm(() => {
105320
105351
  init_dist();
105321
105352
  init_embeddings();
@@ -107714,6 +107745,12 @@ class ProjectIdentityAliasResolver {
107714
107745
  return projectId;
107715
107746
  }
107716
107747
  }
107748
+ resolveCached(projectId) {
107749
+ if (!projectId)
107750
+ return;
107751
+ const cached2 = this.cache.get(projectId);
107752
+ return cached2 && cached2.expiresAt > this.now() ? cached2.canonical : undefined;
107753
+ }
107717
107754
  async resolveWithTimeout(projectId) {
107718
107755
  let timer;
107719
107756
  try {
@@ -109473,7 +109510,7 @@ var init_vector_store_factory = __esm(() => {
109473
109510
  });
109474
109511
 
109475
109512
  // ../../packages/core/dist/services/search/search-cache-pg.js
109476
- import crypto2 from "crypto";
109513
+ import crypto3 from "crypto";
109477
109514
 
109478
109515
  class SearchCachePg {
109479
109516
  pool = null;
@@ -109530,7 +109567,7 @@ class SearchCachePg {
109530
109567
  projectId,
109531
109568
  options: this.normalizeOptions(options)
109532
109569
  });
109533
- return crypto2.createHash("sha256").update(payload).digest("hex");
109570
+ return crypto3.createHash("sha256").update(payload).digest("hex");
109534
109571
  }
109535
109572
  normalizeOptions(options) {
109536
109573
  const searchAffectingParams = [
@@ -112227,7 +112264,7 @@ async function _indexProjectInternalImpl(rlm, projectPath, projectId, options =
112227
112264
  projectId
112228
112265
  });
112229
112266
  options.onProgress?.(0, filteredFiles.length);
112230
- const centralityMap = await rlm.symbolRepo.getCentrality(projectId);
112267
+ const centralityMap = await rlm.symbolRepo.getCentrality(await getProjectIdentityAliasResolver().resolve(projectId));
112231
112268
  let filesIndexed = 0;
112232
112269
  let chunksIndexed = 0;
112233
112270
  let errors4 = 0;
@@ -112374,7 +112411,7 @@ async function ensureFreshIndexImpl(rlm, projectId, projectPath, options = {}) {
112374
112411
  projectId,
112375
112412
  fileCount: filesToReindex.length
112376
112413
  });
112377
- const centralityMap = await rlm.symbolRepo.getCentrality(projectId);
112414
+ const centralityMap = await rlm.symbolRepo.getCentrality(await getProjectIdentityAliasResolver().resolve(projectId));
112378
112415
  let filesIndexed = 0;
112379
112416
  let chunksIndexed = 0;
112380
112417
  let errors4 = 0;
@@ -115584,6 +115621,8 @@ async function buildGraphStreamImpl(_rlm, resultSets, maxResults, projectId, rep
115584
115621
  const row = await Promise.resolve(repo.getById(id));
115585
115622
  if (!row || row.deleted_at !== null)
115586
115623
  continue;
115624
+ if (projectId && row.project_id !== projectId)
115625
+ continue;
115587
115626
  out.push({
115588
115627
  id: row.id,
115589
115628
  content: row.content,
@@ -121755,7 +121794,8 @@ class PgObservationStore {
121755
121794
  return this.hydrating;
121756
121795
  }
121757
121796
  insert(obs) {
121758
- this.mirror.set(obs.id, obs);
121797
+ const cachedCanonical = getProjectIdentityAliasResolver().resolveCached(obs.projectId);
121798
+ this.mirror.set(obs.id, cachedCanonical && cachedCanonical !== obs.projectId ? { ...obs, projectId: cachedCanonical } : obs);
121759
121799
  this.ensureHydrated();
121760
121800
  (async () => {
121761
121801
  try {
@@ -123303,10 +123343,8 @@ var init_models_dev_client = __esm(() => {
123303
123343
 
123304
123344
  // ../../packages/core/dist/services/graph/relation-extractor.js
123305
123345
  class RelationExtractor {
123306
- embeddingService;
123307
123346
  graphStore;
123308
123347
  constructor(graphStore) {
123309
- this.embeddingService = new EmbeddingService;
123310
123348
  this.graphStore = graphStore ?? getGraphStore();
123311
123349
  }
123312
123350
  async extractRelations(memoryId, options) {
@@ -123480,7 +123518,6 @@ class RelationExtractor {
123480
123518
  var DEFAULT_OPTIONS, CONTRADICTION_SIGNALS, RESOLUTION_SIGNALS, DERIVATION_SIGNALS, SUPPORT_SIGNALS;
123481
123519
  var init_relation_extractor = __esm(() => {
123482
123520
  init_dist();
123483
- init_embeddings();
123484
123521
  init_graph_store_factory();
123485
123522
  init_memory_repository_factory();
123486
123523
  DEFAULT_OPTIONS = {
@@ -128911,7 +128948,7 @@ class ResolveStage {
128911
128948
  timestamp: Date.now()
128912
128949
  });
128913
128950
  const knownRelPaths = new Set(files.map((f) => f.file.relativePath));
128914
- const { index: symbolIndex, definitions: repositoryDefinitions } = await this.buildSymbolIndex(ctx.projectId, files);
128951
+ const { index: symbolIndex, fqns: knownFqns, definitions: repositoryDefinitions } = await this.buildSymbolIndex(ctx.projectId, files);
128915
128952
  if (ctx.abortSignal?.aborted)
128916
128953
  throw ctx.abortSignal.reason;
128917
128954
  const rootAliases = this.loadTsConfigPaths(ctx.projectPath);
@@ -128949,7 +128986,7 @@ class ResolveStage {
128949
128986
  const resolved = [];
128950
128987
  let processed = 0;
128951
128988
  for (const parsedFile of files) {
128952
- const resolvedFile = parsedFile.structure && session2 ? this.resolveStructuralFile(parsedFile, session2, knownRelPaths, rootAliases, monorepoPackages) : this.resolveFile(parsedFile, ctx.projectPath, knownRelPaths, rootAliases, monorepoPackages, symbolIndex);
128989
+ const resolvedFile = parsedFile.structure && session2 ? this.resolveStructuralFile(parsedFile, session2, knownRelPaths, rootAliases, monorepoPackages) : this.resolveFile(parsedFile, ctx.projectPath, knownRelPaths, rootAliases, monorepoPackages, symbolIndex, knownFqns);
128953
128990
  resolved.push(resolvedFile);
128954
128991
  processed++;
128955
128992
  if (processed % 50 === 0) {
@@ -129081,7 +129118,7 @@ class ResolveStage {
129081
129118
  defaultExport: false
129082
129119
  });
129083
129120
  }
129084
- resolveFile(parsed, projectPath, knownRelPaths, rootAliases, monorepoPackages, symbolIndex) {
129121
+ resolveFile(parsed, projectPath, knownRelPaths, rootAliases, monorepoPackages, symbolIndex, knownFqns) {
129085
129122
  const fromDir = path17.dirname(path17.join(projectPath, parsed.file.relativePath));
129086
129123
  const packageAliases = this.getPackageAliases(parsed.file.relativePath, monorepoPackages);
129087
129124
  const allAliases = [...packageAliases, ...rootAliases];
@@ -129108,7 +129145,7 @@ class ResolveStage {
129108
129145
  }
129109
129146
  const localNames = new Set(parsed.symbols.map((s) => s.name));
129110
129147
  const resolvedEdges = (parsed.rawEdges ?? []).map((edge) => {
129111
- const targetFqn = this.resolveEdgeTarget(edge.symbolName, parsed.file.relativePath, localNames, importNameToPath, namespaceToPath, symbolIndex);
129148
+ const targetFqn = this.resolveEdgeTarget(edge.symbolName, parsed.file.relativePath, localNames, importNameToPath, namespaceToPath, symbolIndex, knownFqns);
129112
129149
  const meta3 = { ...edge.meta ?? {} };
129113
129150
  if (edge.callerSymbol) {
129114
129151
  meta3.callerFqn = `${parsed.file.relativePath}#${edge.callerSymbol}`;
@@ -129122,7 +129159,7 @@ class ResolveStage {
129122
129159
  resolvedEdges
129123
129160
  };
129124
129161
  }
129125
- resolveEdgeTarget(name26, thisFile, localNames, importNameToPath, namespaceToPath, symbolIndex) {
129162
+ resolveEdgeTarget(name26, thisFile, localNames, importNameToPath, namespaceToPath, symbolIndex, knownFqns) {
129126
129163
  if (localNames.has(name26))
129127
129164
  return `${thisFile}#${name26}`;
129128
129165
  const importedPath = importNameToPath.get(name26);
@@ -129131,6 +129168,8 @@ class ResolveStage {
129131
129168
  const nsPath = namespaceToPath.get("*") ?? namespaceToPath.get("default");
129132
129169
  if (nsPath) {
129133
129170
  const nsFqn = `${nsPath}#${name26}`;
129171
+ if (knownFqns.has(nsFqn))
129172
+ return nsFqn;
129134
129173
  if (symbolIndex.has(name26))
129135
129174
  return symbolIndex.get(name26);
129136
129175
  return nsFqn;
@@ -129140,10 +129179,12 @@ class ResolveStage {
129140
129179
  }
129141
129180
  async buildSymbolIndex(projectId, files) {
129142
129181
  const index = new Map;
129182
+ const fqns = new Set;
129143
129183
  let repositoryDefinitions = [];
129144
129184
  try {
129145
129185
  repositoryDefinitions = await this.symbolRepository.listAllDefinitions(projectId);
129146
129186
  for (const def of repositoryDefinitions) {
129187
+ fqns.add(`${def.file_path}#${def.name}`);
129147
129188
  if (index.has(def.name))
129148
129189
  continue;
129149
129190
  index.set(def.name, `${def.file_path}#${def.name}`);
@@ -129160,6 +129201,7 @@ class ResolveStage {
129160
129201
  const inBatch = new Map;
129161
129202
  for (const f of files) {
129162
129203
  for (const sym of f.symbols) {
129204
+ fqns.add(`${f.file.relativePath}#${sym.name}`);
129163
129205
  if (inBatch.has(sym.name))
129164
129206
  continue;
129165
129207
  inBatch.set(sym.name, `${f.file.relativePath}#${sym.name}`);
@@ -129168,7 +129210,7 @@ class ResolveStage {
129168
129210
  for (const [name26, fqn] of inBatch) {
129169
129211
  index.set(name26, fqn);
129170
129212
  }
129171
- return { index, definitions: repositoryDefinitions };
129213
+ return { index, fqns, definitions: repositoryDefinitions };
129172
129214
  }
129173
129215
  resolveSpecifier(specifier, fromDir, projectPath, knownRelPaths, aliases) {
129174
129216
  if (specifier.startsWith("./") || specifier.startsWith("../")) {
@@ -130289,6 +130331,10 @@ var init_pipeline = __esm(() => {
130289
130331
  });
130290
130332
  } catch (beginError) {
130291
130333
  if (beginError.message.startsWith("graph_generation_stale_active:") && generationRetry < 3) {
130334
+ stopManagedRunHeartbeat = true;
130335
+ managedRunTimerController.abort();
130336
+ if (managedRunHeartbeat)
130337
+ await managedRunHeartbeat;
130292
130338
  return this.runInternal(input, generationRetry + 1);
130293
130339
  }
130294
130340
  throw beginError;
@@ -132372,6 +132418,13 @@ function isSeatbeltAvailable() {
132372
132418
  }
132373
132419
  return _seatbeltAvailable;
132374
132420
  }
132421
+ function warnSandboxUnavailable() {
132422
+ if (_warnedAboutNoSandbox)
132423
+ return;
132424
+ _warnedAboutNoSandbox = true;
132425
+ const missingTool = process.platform === "darwin" ? "sandbox-exec" : "docker";
132426
+ logger.warn(`sandbox: MASSA_AI_EXECUTOR_SANDBOX=auto found no '${missingTool}' on this platform, ` + `so code is executing with best-effort containment and no OS-level isolation. ` + `Install '${missingTool}', or set MASSA_AI_EXECUTOR_SANDBOX=on to fail loudly instead of falling back.`, { missingTool, platform: process.platform, effectiveMode: "none" });
132427
+ }
132375
132428
  function getSandboxMode() {
132376
132429
  const env4 = process.env.MASSA_AI_EXECUTOR_SANDBOX ?? "auto";
132377
132430
  if (env4 === "none")
@@ -132389,6 +132442,7 @@ function getSandboxMode() {
132389
132442
  return "seatbelt";
132390
132443
  if (isLinux && isDockerAvailable())
132391
132444
  return "docker";
132445
+ warnSandboxUnavailable();
132392
132446
  return "none";
132393
132447
  }
132394
132448
  function _buildSeatbeltProfile(projectRoot, tmpDir) {
@@ -132456,7 +132510,7 @@ function wrapSpawn(cmd, cwd, tmpDir, mode) {
132456
132510
  }
132457
132511
  return cmd;
132458
132512
  }
132459
- var _dockerAvailable = null, _seatbeltAvailable = null;
132513
+ var _dockerAvailable = null, _seatbeltAvailable = null, _warnedAboutNoSandbox = false;
132460
132514
  var init_sandbox = __esm(() => {
132461
132515
  init_dist();
132462
132516
  });
@@ -132618,7 +132672,8 @@ class PolyglotExecutor {
132618
132672
  stdout: "",
132619
132673
  stderr: `Blocked: path "${filePath}" resolves outside the project root (${root}).`,
132620
132674
  exitCode: 1,
132621
- timedOut: false
132675
+ timedOut: false,
132676
+ sandboxMode: getSandboxMode()
132622
132677
  };
132623
132678
  return err;
132624
132679
  }
@@ -132627,7 +132682,8 @@ class PolyglotExecutor {
132627
132682
  stdout: "",
132628
132683
  stderr: `Blocked: path "${filePath}" matches a deny-listed pattern (secrets/credentials).`,
132629
132684
  exitCode: 1,
132630
- timedOut: false
132685
+ timedOut: false,
132686
+ sandboxMode: getSandboxMode()
132631
132687
  };
132632
132688
  return err;
132633
132689
  }
@@ -132678,7 +132734,8 @@ ${body}`;
132678
132734
  stderr: `Compilation failed:
132679
132735
  ${message}`,
132680
132736
  exitCode: 1,
132681
- timedOut: false
132737
+ timedOut: false,
132738
+ sandboxMode: getSandboxMode()
132682
132739
  };
132683
132740
  }
132684
132741
  return await this.#spawn([binPath], cwd, cwd, timeout, false);
@@ -132721,7 +132778,8 @@ ${message}`,
132721
132778
  timedOut: true,
132722
132779
  backgrounded: true,
132723
132780
  command: cmd.join(" "),
132724
- cwd
132781
+ cwd,
132782
+ sandboxMode
132725
132783
  });
132726
132784
  } else {
132727
132785
  killTree(proc2);
@@ -132760,7 +132818,8 @@ ${message}`,
132760
132818
  exitCode: timedOut ? null : exitCode,
132761
132819
  timedOut,
132762
132820
  command: cmd.join(" "),
132763
- cwd
132821
+ cwd,
132822
+ sandboxMode
132764
132823
  });
132765
132824
  });
132766
132825
  proc2.on("error", (err) => {
@@ -132774,7 +132833,8 @@ ${message}`,
132774
132833
  exitCode: null,
132775
132834
  timedOut: false,
132776
132835
  command: cmd.join(" "),
132777
- cwd
132836
+ cwd,
132837
+ sandboxMode
132778
132838
  });
132779
132839
  });
132780
132840
  });
@@ -133112,6 +133172,7 @@ var init_intent_search = __esm(() => {
133112
133172
  var init_executor2 = __esm(() => {
133113
133173
  init_executor();
133114
133174
  init_executor();
133175
+ init_sandbox();
133115
133176
  init_run_pool();
133116
133177
  init_runtime();
133117
133178
  init_intent_search();
package/dist/index.js CHANGED
@@ -25539,6 +25539,9 @@ var init_massa_ai_config = __esm(() => {
25539
25539
  },
25540
25540
  handoffs: {
25541
25541
  enabled: true
25542
+ },
25543
+ security: {
25544
+ corsOrigins: []
25542
25545
  }
25543
25546
  };
25544
25547
  });
@@ -25560,6 +25563,7 @@ __export(exports_config_loader, {
25560
25563
  import fs from "fs";
25561
25564
  import path3 from "path";
25562
25565
  import os2 from "os";
25566
+ import crypto2 from "crypto";
25563
25567
  function getConfigDir() {
25564
25568
  return CONFIG_DIR;
25565
25569
  }
@@ -25588,7 +25592,8 @@ function loadConfig() {
25588
25592
  llm: { ...defaultMassaAiConfig.llm, ...userConfig.llm },
25589
25593
  memory: { ...defaultMassaAiConfig.memory, ...userConfig.memory },
25590
25594
  hooks: { ...defaultMassaAiConfig.hooks, ...userConfig.hooks },
25591
- handoffs: { ...defaultMassaAiConfig.handoffs, ...userConfig.handoffs }
25595
+ handoffs: { ...defaultMassaAiConfig.handoffs, ...userConfig.handoffs },
25596
+ security: { ...defaultMassaAiConfig.security, ...userConfig.security }
25592
25597
  };
25593
25598
  } catch (error51) {
25594
25599
  console.error(`Error loading config from ${CONFIG_FILE}:`, error51);
@@ -25632,7 +25637,17 @@ function saveConfig(config2) {
25632
25637
  if (!fs.existsSync(CONFIG_DIR)) {
25633
25638
  fs.mkdirSync(CONFIG_DIR, { recursive: true });
25634
25639
  }
25635
- fs.writeFileSync(CONFIG_FILE, JSON.stringify(config2, null, 2));
25640
+ const unique = `${process.pid}.${++tempFileCounter}.${crypto2.randomBytes(6).toString("hex")}`;
25641
+ const tempFile = path3.join(CONFIG_DIR, `.config.json.${unique}.tmp`);
25642
+ try {
25643
+ fs.writeFileSync(tempFile, JSON.stringify(config2, null, 2));
25644
+ fs.renameSync(tempFile, CONFIG_FILE);
25645
+ } catch (error51) {
25646
+ try {
25647
+ fs.unlinkSync(tempFile);
25648
+ } catch {}
25649
+ throw error51;
25650
+ }
25636
25651
  }
25637
25652
  function initConfig() {
25638
25653
  if (!fs.existsSync(CONFIG_FILE)) {
@@ -25660,7 +25675,7 @@ function getConfigForEnv() {
25660
25675
  env.ENABLE_METRICS = String(config2.logging.enableMetrics);
25661
25676
  return env;
25662
25677
  }
25663
- var CONFIG_DIR, CONFIG_FILE, migrationAttempted = false;
25678
+ var CONFIG_DIR, CONFIG_FILE, migrationAttempted = false, tempFileCounter = 0;
25664
25679
  var init_config_loader = __esm(() => {
25665
25680
  init_massa_ai_config();
25666
25681
  init_xdg();
@@ -25703,9 +25718,18 @@ var init_env = __esm(() => {
25703
25718
  if (cfg.embedding?.apiKey && !process.env.OLLAMA_API_KEY) {
25704
25719
  process.env.OLLAMA_API_KEY = cfg.embedding.apiKey;
25705
25720
  }
25721
+ const securityApiKey = cfg.security?.apiKey?.trim();
25722
+ if (securityApiKey && !process.env.MASSA_AI_API_KEY?.trim()) {
25723
+ process.env.MASSA_AI_API_KEY = securityApiKey;
25724
+ }
25706
25725
  } catch {}
25707
25726
  });
25708
25727
 
25728
+ // ../../packages/shared/dist/config/api-key.js
25729
+ var init_api_key = __esm(() => {
25730
+ init_config_loader();
25731
+ });
25732
+
25709
25733
  // ../../packages/shared/dist/config/db-guard.js
25710
25734
  function requirePostgresDatabaseUrl(databaseUrl = process.env.DATABASE_URL) {
25711
25735
  if (!databaseUrl?.trim()) {
@@ -25762,6 +25786,13 @@ function envString(key, fallback) {
25762
25786
  const s = process.env[key];
25763
25787
  return s === undefined || s === "" ? fallback : s;
25764
25788
  }
25789
+ function envList(key, fallback) {
25790
+ const s = process.env[key];
25791
+ if (s === undefined)
25792
+ return fallback;
25793
+ const parsed = s.split(",").map((v) => v.trim()).filter((v) => v.length > 0);
25794
+ return parsed.length > 0 ? parsed : fallback;
25795
+ }
25765
25796
  function validateCapturePolicyConfig(raw2) {
25766
25797
  if (!raw2 || typeof raw2 !== "object")
25767
25798
  throw new TypeError("capturePolicy must be an object");
@@ -25949,6 +25980,7 @@ var init_config = __esm(() => {
25949
25980
  init_config_loader();
25950
25981
  init_massa_ai_config();
25951
25982
  init_config_loader();
25983
+ init_api_key();
25952
25984
  DEFAULT_ALLOWED_EXTENSIONS = [
25953
25985
  ".ts",
25954
25986
  ".js",
@@ -26108,7 +26140,8 @@ var init_config = __esm(() => {
26108
26140
  "**/generated/**",
26109
26141
  "*.min.js",
26110
26142
  "*.min.css"
26111
- ]
26143
+ ],
26144
+ corsOrigins: envList("MASSA_AI_API_CORS_ORIGINS", fileConfig.security?.corsOrigins ?? [])
26112
26145
  },
26113
26146
  logging: {
26114
26147
  level: process.env.LOG_LEVEL || fileConfig.logging?.level || "info",
@@ -106358,7 +106391,7 @@ var require_cert_signatures = __commonJS((exports, module) => {
106358
106391
 
106359
106392
  // ../../node_modules/pg/lib/crypto/sasl.js
106360
106393
  var require_sasl = __commonJS((exports, module) => {
106361
- var crypto2 = require_utils5();
106394
+ var crypto3 = require_utils5();
106362
106395
  var { signatureAlgorithmHashFromCertificate } = require_cert_signatures();
106363
106396
  function saslprep(password) {
106364
106397
  const nonAsciiSpace = /[\u00A0\u1680\u2000-\u200B\u202F\u205F\u3000]/g;
@@ -106377,7 +106410,7 @@ var require_sasl = __commonJS((exports, module) => {
106377
106410
  if (mechanism === "SCRAM-SHA-256-PLUS" && typeof stream2.getPeerCertificate !== "function") {
106378
106411
  throw new Error("SASL: Mechanism SCRAM-SHA-256-PLUS requires a certificate");
106379
106412
  }
106380
- const clientNonce = crypto2.randomBytes(18).toString("base64");
106413
+ const clientNonce = crypto3.randomBytes(18).toString("base64");
106381
106414
  const gs2Header = mechanism === "SCRAM-SHA-256-PLUS" ? "p=tls-server-end-point" : stream2 ? "y" : "n";
106382
106415
  return {
106383
106416
  mechanism,
@@ -106418,20 +106451,20 @@ var require_sasl = __commonJS((exports, module) => {
106418
106451
  let hashName = signatureAlgorithmHashFromCertificate(peerCert);
106419
106452
  if (hashName === "MD5" || hashName === "SHA-1")
106420
106453
  hashName = "SHA-256";
106421
- const certHash = await crypto2.hashByName(hashName, peerCert);
106454
+ const certHash = await crypto3.hashByName(hashName, peerCert);
106422
106455
  const bindingData = Buffer.concat([Buffer.from("p=tls-server-end-point,,"), Buffer.from(certHash)]);
106423
106456
  channelBinding = bindingData.toString("base64");
106424
106457
  }
106425
106458
  const clientFinalMessageWithoutProof = "c=" + channelBinding + ",r=" + sv.nonce;
106426
106459
  const authMessage = clientFirstMessageBare + "," + serverFirstMessage + "," + clientFinalMessageWithoutProof;
106427
106460
  const saltBytes = Buffer.from(sv.salt, "base64");
106428
- const saltedPassword = await crypto2.deriveKey(saslprep(password), saltBytes, sv.iteration);
106429
- const clientKey = await crypto2.hmacSha256(saltedPassword, "Client Key");
106430
- const storedKey = await crypto2.sha256(clientKey);
106431
- const clientSignature = await crypto2.hmacSha256(storedKey, authMessage);
106461
+ const saltedPassword = await crypto3.deriveKey(saslprep(password), saltBytes, sv.iteration);
106462
+ const clientKey = await crypto3.hmacSha256(saltedPassword, "Client Key");
106463
+ const storedKey = await crypto3.sha256(clientKey);
106464
+ const clientSignature = await crypto3.hmacSha256(storedKey, authMessage);
106432
106465
  const clientProof = xorBuffers(Buffer.from(clientKey), Buffer.from(clientSignature)).toString("base64");
106433
- const serverKey = await crypto2.hmacSha256(saltedPassword, "Server Key");
106434
- const serverSignatureBytes = await crypto2.hmacSha256(serverKey, authMessage);
106466
+ const serverKey = await crypto3.hmacSha256(saltedPassword, "Server Key");
106467
+ const serverSignatureBytes = await crypto3.hmacSha256(serverKey, authMessage);
106435
106468
  session.message = "SASLResponse";
106436
106469
  session.serverSignature = Buffer.from(serverSignatureBytes).toString("base64");
106437
106470
  session.response = clientFinalMessageWithoutProof + ",p=" + clientProof;
@@ -108539,7 +108572,7 @@ var require_client2 = __commonJS((exports, module) => {
108539
108572
  var Query = require_query();
108540
108573
  var defaults2 = require_defaults2();
108541
108574
  var Connection = require_connection();
108542
- var crypto2 = require_utils5();
108575
+ var crypto3 = require_utils5();
108543
108576
  var activeQueryDeprecationNotice = nodeUtils.deprecate(() => {}, "Client.activeQuery is deprecated and will be removed in pg@9.0");
108544
108577
  var queryQueueDeprecationNotice = nodeUtils.deprecate(() => {}, "Client.queryQueue is deprecated and will be removed in pg@9.0.");
108545
108578
  var pgPassDeprecationNotice = nodeUtils.deprecate(() => {}, "pgpass support is deprecated and will be removed in pg@9.0. " + "You can provide an async function as the password property to the Client/Pool constructor that returns a password instead. Within this function you can call the pgpass module in your own code.");
@@ -108771,7 +108804,7 @@ var require_client2 = __commonJS((exports, module) => {
108771
108804
  _handleAuthMD5Password(msg) {
108772
108805
  this._getPassword(async () => {
108773
108806
  try {
108774
- const hashedPassword = await crypto2.postgresMd5PasswordHash(this.user, this.password, msg.salt);
108807
+ const hashedPassword = await crypto3.postgresMd5PasswordHash(this.user, this.password, msg.salt);
108775
108808
  this.connection.password(hashedPassword);
108776
108809
  } catch (e) {
108777
108810
  this.emit("error", e);
@@ -111826,10 +111859,7 @@ class EmbeddingService {
111826
111859
  async embed(text2) {
111827
111860
  await this.ensureInitialized();
111828
111861
  if (!this.provider) {
111829
- const msg = "No embedding provider available. Configure OLLAMA_BASE_URL or an API key.";
111830
- if (false) {}
111831
- logger.warn(msg + " Using random embeddings (dev only).");
111832
- return new Array(384).fill(0).map(() => Math.random());
111862
+ throw new Error(NO_PROVIDER_MESSAGE);
111833
111863
  }
111834
111864
  try {
111835
111865
  return await this.provider.embedQuery(text2);
@@ -111843,10 +111873,7 @@ class EmbeddingService {
111843
111873
  async embedBatch(texts) {
111844
111874
  await this.ensureInitialized();
111845
111875
  if (!this.provider) {
111846
- const msg = "No embedding provider available. Configure OLLAMA_BASE_URL or an API key.";
111847
- if (false) {}
111848
- logger.warn(msg + " Using random embeddings (dev only).");
111849
- return texts.map(() => new Array(384).fill(0).map(() => Math.random()));
111876
+ throw new Error(NO_PROVIDER_MESSAGE);
111850
111877
  }
111851
111878
  try {
111852
111879
  return await this.provider.embedBatch(texts);
@@ -111858,7 +111885,10 @@ class EmbeddingService {
111858
111885
  }
111859
111886
  }
111860
111887
  getDimensions() {
111861
- return this.provider?.dimensions || 384;
111888
+ if (!this.provider) {
111889
+ throw new Error(NO_PROVIDER_MESSAGE);
111890
+ }
111891
+ return this.provider.dimensions;
111862
111892
  }
111863
111893
  getProviderInfo() {
111864
111894
  if (!this.provider)
@@ -111875,6 +111905,7 @@ class EmbeddingService {
111875
111905
  return dotProduct / (magnitude1 * magnitude2);
111876
111906
  }
111877
111907
  }
111908
+ var NO_PROVIDER_MESSAGE = "No embedding provider available. Configure OLLAMA_BASE_URL or an API key.";
111878
111909
  var init_embedding_service = __esm(() => {
111879
111910
  init_dist();
111880
111911
  init_embeddings();
@@ -114273,6 +114304,12 @@ class ProjectIdentityAliasResolver {
114273
114304
  return projectId;
114274
114305
  }
114275
114306
  }
114307
+ resolveCached(projectId) {
114308
+ if (!projectId)
114309
+ return;
114310
+ const cached2 = this.cache.get(projectId);
114311
+ return cached2 && cached2.expiresAt > this.now() ? cached2.canonical : undefined;
114312
+ }
114276
114313
  async resolveWithTimeout(projectId) {
114277
114314
  let timer;
114278
114315
  try {
@@ -116032,7 +116069,7 @@ var init_vector_store_factory = __esm(() => {
116032
116069
  });
116033
116070
 
116034
116071
  // ../../packages/core/dist/services/search/search-cache-pg.js
116035
- import crypto2 from "crypto";
116072
+ import crypto3 from "crypto";
116036
116073
 
116037
116074
  class SearchCachePg {
116038
116075
  pool = null;
@@ -116089,7 +116126,7 @@ class SearchCachePg {
116089
116126
  projectId,
116090
116127
  options: this.normalizeOptions(options)
116091
116128
  });
116092
- return crypto2.createHash("sha256").update(payload).digest("hex");
116129
+ return crypto3.createHash("sha256").update(payload).digest("hex");
116093
116130
  }
116094
116131
  normalizeOptions(options) {
116095
116132
  const searchAffectingParams = [
@@ -118786,7 +118823,7 @@ async function _indexProjectInternalImpl(rlm, projectPath, projectId, options =
118786
118823
  projectId
118787
118824
  });
118788
118825
  options.onProgress?.(0, filteredFiles.length);
118789
- const centralityMap = await rlm.symbolRepo.getCentrality(projectId);
118826
+ const centralityMap = await rlm.symbolRepo.getCentrality(await getProjectIdentityAliasResolver().resolve(projectId));
118790
118827
  let filesIndexed = 0;
118791
118828
  let chunksIndexed = 0;
118792
118829
  let errors4 = 0;
@@ -118933,7 +118970,7 @@ async function ensureFreshIndexImpl(rlm, projectId, projectPath, options = {}) {
118933
118970
  projectId,
118934
118971
  fileCount: filesToReindex.length
118935
118972
  });
118936
- const centralityMap = await rlm.symbolRepo.getCentrality(projectId);
118973
+ const centralityMap = await rlm.symbolRepo.getCentrality(await getProjectIdentityAliasResolver().resolve(projectId));
118937
118974
  let filesIndexed = 0;
118938
118975
  let chunksIndexed = 0;
118939
118976
  let errors4 = 0;
@@ -122143,6 +122180,8 @@ async function buildGraphStreamImpl(_rlm, resultSets, maxResults, projectId, rep
122143
122180
  const row = await Promise.resolve(repo.getById(id));
122144
122181
  if (!row || row.deleted_at !== null)
122145
122182
  continue;
122183
+ if (projectId && row.project_id !== projectId)
122184
+ continue;
122146
122185
  out.push({
122147
122186
  id: row.id,
122148
122187
  content: row.content,
@@ -127094,7 +127133,7 @@ class ResolveStage {
127094
127133
  timestamp: Date.now()
127095
127134
  });
127096
127135
  const knownRelPaths = new Set(files.map((f) => f.file.relativePath));
127097
- const { index: symbolIndex, definitions: repositoryDefinitions } = await this.buildSymbolIndex(ctx.projectId, files);
127136
+ const { index: symbolIndex, fqns: knownFqns, definitions: repositoryDefinitions } = await this.buildSymbolIndex(ctx.projectId, files);
127098
127137
  if (ctx.abortSignal?.aborted)
127099
127138
  throw ctx.abortSignal.reason;
127100
127139
  const rootAliases = this.loadTsConfigPaths(ctx.projectPath);
@@ -127132,7 +127171,7 @@ class ResolveStage {
127132
127171
  const resolved = [];
127133
127172
  let processed = 0;
127134
127173
  for (const parsedFile of files) {
127135
- const resolvedFile = parsedFile.structure && session2 ? this.resolveStructuralFile(parsedFile, session2, knownRelPaths, rootAliases, monorepoPackages) : this.resolveFile(parsedFile, ctx.projectPath, knownRelPaths, rootAliases, monorepoPackages, symbolIndex);
127174
+ const resolvedFile = parsedFile.structure && session2 ? this.resolveStructuralFile(parsedFile, session2, knownRelPaths, rootAliases, monorepoPackages) : this.resolveFile(parsedFile, ctx.projectPath, knownRelPaths, rootAliases, monorepoPackages, symbolIndex, knownFqns);
127136
127175
  resolved.push(resolvedFile);
127137
127176
  processed++;
127138
127177
  if (processed % 50 === 0) {
@@ -127264,7 +127303,7 @@ class ResolveStage {
127264
127303
  defaultExport: false
127265
127304
  });
127266
127305
  }
127267
- resolveFile(parsed, projectPath, knownRelPaths, rootAliases, monorepoPackages, symbolIndex) {
127306
+ resolveFile(parsed, projectPath, knownRelPaths, rootAliases, monorepoPackages, symbolIndex, knownFqns) {
127268
127307
  const fromDir = path14.dirname(path14.join(projectPath, parsed.file.relativePath));
127269
127308
  const packageAliases = this.getPackageAliases(parsed.file.relativePath, monorepoPackages);
127270
127309
  const allAliases = [...packageAliases, ...rootAliases];
@@ -127291,7 +127330,7 @@ class ResolveStage {
127291
127330
  }
127292
127331
  const localNames = new Set(parsed.symbols.map((s) => s.name));
127293
127332
  const resolvedEdges = (parsed.rawEdges ?? []).map((edge) => {
127294
- const targetFqn = this.resolveEdgeTarget(edge.symbolName, parsed.file.relativePath, localNames, importNameToPath, namespaceToPath, symbolIndex);
127333
+ const targetFqn = this.resolveEdgeTarget(edge.symbolName, parsed.file.relativePath, localNames, importNameToPath, namespaceToPath, symbolIndex, knownFqns);
127295
127334
  const meta3 = { ...edge.meta ?? {} };
127296
127335
  if (edge.callerSymbol) {
127297
127336
  meta3.callerFqn = `${parsed.file.relativePath}#${edge.callerSymbol}`;
@@ -127305,7 +127344,7 @@ class ResolveStage {
127305
127344
  resolvedEdges
127306
127345
  };
127307
127346
  }
127308
- resolveEdgeTarget(name26, thisFile, localNames, importNameToPath, namespaceToPath, symbolIndex) {
127347
+ resolveEdgeTarget(name26, thisFile, localNames, importNameToPath, namespaceToPath, symbolIndex, knownFqns) {
127309
127348
  if (localNames.has(name26))
127310
127349
  return `${thisFile}#${name26}`;
127311
127350
  const importedPath = importNameToPath.get(name26);
@@ -127314,6 +127353,8 @@ class ResolveStage {
127314
127353
  const nsPath = namespaceToPath.get("*") ?? namespaceToPath.get("default");
127315
127354
  if (nsPath) {
127316
127355
  const nsFqn = `${nsPath}#${name26}`;
127356
+ if (knownFqns.has(nsFqn))
127357
+ return nsFqn;
127317
127358
  if (symbolIndex.has(name26))
127318
127359
  return symbolIndex.get(name26);
127319
127360
  return nsFqn;
@@ -127323,10 +127364,12 @@ class ResolveStage {
127323
127364
  }
127324
127365
  async buildSymbolIndex(projectId, files) {
127325
127366
  const index = new Map;
127367
+ const fqns = new Set;
127326
127368
  let repositoryDefinitions = [];
127327
127369
  try {
127328
127370
  repositoryDefinitions = await this.symbolRepository.listAllDefinitions(projectId);
127329
127371
  for (const def of repositoryDefinitions) {
127372
+ fqns.add(`${def.file_path}#${def.name}`);
127330
127373
  if (index.has(def.name))
127331
127374
  continue;
127332
127375
  index.set(def.name, `${def.file_path}#${def.name}`);
@@ -127343,6 +127386,7 @@ class ResolveStage {
127343
127386
  const inBatch = new Map;
127344
127387
  for (const f of files) {
127345
127388
  for (const sym of f.symbols) {
127389
+ fqns.add(`${f.file.relativePath}#${sym.name}`);
127346
127390
  if (inBatch.has(sym.name))
127347
127391
  continue;
127348
127392
  inBatch.set(sym.name, `${f.file.relativePath}#${sym.name}`);
@@ -127351,7 +127395,7 @@ class ResolveStage {
127351
127395
  for (const [name26, fqn] of inBatch) {
127352
127396
  index.set(name26, fqn);
127353
127397
  }
127354
- return { index, definitions: repositoryDefinitions };
127398
+ return { index, fqns, definitions: repositoryDefinitions };
127355
127399
  }
127356
127400
  resolveSpecifier(specifier, fromDir, projectPath, knownRelPaths, aliases) {
127357
127401
  if (specifier.startsWith("./") || specifier.startsWith("../")) {
@@ -128472,6 +128516,10 @@ var init_pipeline = __esm(() => {
128472
128516
  });
128473
128517
  } catch (beginError) {
128474
128518
  if (beginError.message.startsWith("graph_generation_stale_active:") && generationRetry < 3) {
128519
+ stopManagedRunHeartbeat = true;
128520
+ managedRunTimerController.abort();
128521
+ if (managedRunHeartbeat)
128522
+ await managedRunHeartbeat;
128475
128523
  return this.runInternal(input, generationRetry + 1);
128476
128524
  }
128477
128525
  throw beginError;
@@ -131594,10 +131642,8 @@ var init_memory_service = __esm(() => {
131594
131642
 
131595
131643
  // ../../packages/core/dist/services/graph/relation-extractor.js
131596
131644
  class RelationExtractor {
131597
- embeddingService;
131598
131645
  graphStore;
131599
131646
  constructor(graphStore) {
131600
- this.embeddingService = new EmbeddingService;
131601
131647
  this.graphStore = graphStore ?? getGraphStore();
131602
131648
  }
131603
131649
  async extractRelations(memoryId, options) {
@@ -131771,7 +131817,6 @@ class RelationExtractor {
131771
131817
  var DEFAULT_OPTIONS, CONTRADICTION_SIGNALS, RESOLUTION_SIGNALS, DERIVATION_SIGNALS, SUPPORT_SIGNALS;
131772
131818
  var init_relation_extractor = __esm(() => {
131773
131819
  init_dist();
131774
- init_embeddings();
131775
131820
  init_graph_store_factory();
131776
131821
  init_memory_repository_factory();
131777
131822
  DEFAULT_OPTIONS = {
@@ -135276,7 +135321,8 @@ class PgObservationStore {
135276
135321
  return this.hydrating;
135277
135322
  }
135278
135323
  insert(obs) {
135279
- this.mirror.set(obs.id, obs);
135324
+ const cachedCanonical = getProjectIdentityAliasResolver().resolveCached(obs.projectId);
135325
+ this.mirror.set(obs.id, cachedCanonical && cachedCanonical !== obs.projectId ? { ...obs, projectId: cachedCanonical } : obs);
135280
135326
  this.ensureHydrated();
135281
135327
  (async () => {
135282
135328
  try {
@@ -138515,6 +138561,13 @@ function isSeatbeltAvailable() {
138515
138561
  }
138516
138562
  return _seatbeltAvailable;
138517
138563
  }
138564
+ function warnSandboxUnavailable() {
138565
+ if (_warnedAboutNoSandbox)
138566
+ return;
138567
+ _warnedAboutNoSandbox = true;
138568
+ const missingTool = process.platform === "darwin" ? "sandbox-exec" : "docker";
138569
+ logger.warn(`sandbox: MASSA_AI_EXECUTOR_SANDBOX=auto found no '${missingTool}' on this platform, ` + `so code is executing with best-effort containment and no OS-level isolation. ` + `Install '${missingTool}', or set MASSA_AI_EXECUTOR_SANDBOX=on to fail loudly instead of falling back.`, { missingTool, platform: process.platform, effectiveMode: "none" });
138570
+ }
138518
138571
  function getSandboxMode() {
138519
138572
  const env4 = process.env.MASSA_AI_EXECUTOR_SANDBOX ?? "auto";
138520
138573
  if (env4 === "none")
@@ -138532,6 +138585,7 @@ function getSandboxMode() {
138532
138585
  return "seatbelt";
138533
138586
  if (isLinux && isDockerAvailable())
138534
138587
  return "docker";
138588
+ warnSandboxUnavailable();
138535
138589
  return "none";
138536
138590
  }
138537
138591
  function _buildSeatbeltProfile(projectRoot, tmpDir) {
@@ -138599,7 +138653,7 @@ function wrapSpawn(cmd, cwd, tmpDir, mode) {
138599
138653
  }
138600
138654
  return cmd;
138601
138655
  }
138602
- var _dockerAvailable = null, _seatbeltAvailable = null;
138656
+ var _dockerAvailable = null, _seatbeltAvailable = null, _warnedAboutNoSandbox = false;
138603
138657
  var init_sandbox = __esm(() => {
138604
138658
  init_dist();
138605
138659
  });
@@ -138761,7 +138815,8 @@ class PolyglotExecutor {
138761
138815
  stdout: "",
138762
138816
  stderr: `Blocked: path "${filePath}" resolves outside the project root (${root}).`,
138763
138817
  exitCode: 1,
138764
- timedOut: false
138818
+ timedOut: false,
138819
+ sandboxMode: getSandboxMode()
138765
138820
  };
138766
138821
  return err;
138767
138822
  }
@@ -138770,7 +138825,8 @@ class PolyglotExecutor {
138770
138825
  stdout: "",
138771
138826
  stderr: `Blocked: path "${filePath}" matches a deny-listed pattern (secrets/credentials).`,
138772
138827
  exitCode: 1,
138773
- timedOut: false
138828
+ timedOut: false,
138829
+ sandboxMode: getSandboxMode()
138774
138830
  };
138775
138831
  return err;
138776
138832
  }
@@ -138821,7 +138877,8 @@ ${body}`;
138821
138877
  stderr: `Compilation failed:
138822
138878
  ${message}`,
138823
138879
  exitCode: 1,
138824
- timedOut: false
138880
+ timedOut: false,
138881
+ sandboxMode: getSandboxMode()
138825
138882
  };
138826
138883
  }
138827
138884
  return await this.#spawn([binPath], cwd, cwd, timeout, false);
@@ -138864,7 +138921,8 @@ ${message}`,
138864
138921
  timedOut: true,
138865
138922
  backgrounded: true,
138866
138923
  command: cmd.join(" "),
138867
- cwd
138924
+ cwd,
138925
+ sandboxMode
138868
138926
  });
138869
138927
  } else {
138870
138928
  killTree(proc2);
@@ -138903,7 +138961,8 @@ ${message}`,
138903
138961
  exitCode: timedOut ? null : exitCode,
138904
138962
  timedOut,
138905
138963
  command: cmd.join(" "),
138906
- cwd
138964
+ cwd,
138965
+ sandboxMode
138907
138966
  });
138908
138967
  });
138909
138968
  proc2.on("error", (err) => {
@@ -138917,7 +138976,8 @@ ${message}`,
138917
138976
  exitCode: null,
138918
138977
  timedOut: false,
138919
138978
  command: cmd.join(" "),
138920
- cwd
138979
+ cwd,
138980
+ sandboxMode
138921
138981
  });
138922
138982
  });
138923
138983
  });
@@ -139255,6 +139315,7 @@ var init_intent_search = __esm(() => {
139255
139315
  var init_executor2 = __esm(() => {
139256
139316
  init_executor();
139257
139317
  init_executor();
139318
+ init_sandbox();
139258
139319
  init_run_pool();
139259
139320
  init_runtime();
139260
139321
  init_intent_search();
@@ -139318,7 +139379,8 @@ class ExecutorController {
139318
139379
  timedOut: finalResult.timedOut,
139319
139380
  backgrounded: finalResult.backgrounded ?? false,
139320
139381
  command: finalResult.command,
139321
- cwd: finalResult.cwd
139382
+ cwd: finalResult.cwd,
139383
+ sandboxMode: finalResult.sandboxMode
139322
139384
  }
139323
139385
  };
139324
139386
  } catch (error51) {
@@ -139354,7 +139416,8 @@ class ExecutorController {
139354
139416
  exitCode: finalResult.exitCode,
139355
139417
  timedOut: finalResult.timedOut,
139356
139418
  command: finalResult.command,
139357
- cwd: finalResult.cwd
139419
+ cwd: finalResult.cwd,
139420
+ sandboxMode: finalResult.sandboxMode
139358
139421
  }
139359
139422
  };
139360
139423
  } catch (error51) {
@@ -139398,7 +139461,8 @@ class ExecutorController {
139398
139461
  stdout: r.stdout,
139399
139462
  stderr: r.stderr,
139400
139463
  exitCode: r.exitCode,
139401
- timedOut: r.timedOut
139464
+ timedOut: r.timedOut,
139465
+ sandboxMode: r.sandboxMode
139402
139466
  };
139403
139467
  }
139404
139468
  return {
@@ -139406,7 +139470,8 @@ class ExecutorController {
139406
139470
  stdout: "",
139407
139471
  stderr: String(s.reason ?? "unknown error"),
139408
139472
  exitCode: null,
139409
- timedOut: false
139473
+ timedOut: false,
139474
+ sandboxMode: getSandboxMode()
139410
139475
  };
139411
139476
  });
139412
139477
  const anyFailed = results.some((r) => r.exitCode !== 0 || r.timedOut);
@@ -165500,7 +165565,7 @@ class ApiClient {
165500
165565
  maxRetries;
165501
165566
  constructor(config3) {
165502
165567
  this.baseUrl = config3?.baseUrl || process.env.MASSA_AI_API_URL || "http://localhost:3333";
165503
- this.apiKey = config3?.apiKey || process.env.MASSA_AI_API_KEY || "";
165568
+ this.apiKey = (config3?.apiKey || process.env.MASSA_AI_API_KEY || "").trim();
165504
165569
  this.timeoutMs = typeof config3?.timeoutMs === "number" ? config3.timeoutMs : parsePositiveIntEnv(process.env.MASSA_AI_PROXY_TIMEOUT_MS, 120000, { allowZero: true });
165505
165570
  this.maxRetries = config3?.maxRetries || 2;
165506
165571
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@massa-ai/mcp-client",
3
- "version": "1.7.0",
3
+ "version": "1.8.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.7.0",
24
- "@massa-ai/shared": "^1.7.0",
23
+ "@massa-ai/core": "^1.8.0",
24
+ "@massa-ai/shared": "^1.8.0",
25
25
  "@modelcontextprotocol/sdk": "^1.0.0"
26
26
  },
27
27
  "devDependencies": {