@rdmind/rdmind 0.2.3-alpha.3 → 0.2.3-alpha.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/cli.js +552 -190
  2. package/package.json +2 -2
package/cli.js CHANGED
@@ -26301,21 +26301,21 @@ var init_from = __esm({
26301
26301
  init_fetch_blob();
26302
26302
  ({ stat } = fs2);
26303
26303
  blobFromSync = /* @__PURE__ */ __name((path134, type) => fromBlob(statSync(path134), path134, type), "blobFromSync");
26304
- blobFrom = /* @__PURE__ */ __name((path134, type) => stat(path134).then((stat10) => fromBlob(stat10, path134, type)), "blobFrom");
26305
- fileFrom = /* @__PURE__ */ __name((path134, type) => stat(path134).then((stat10) => fromFile(stat10, path134, type)), "fileFrom");
26304
+ blobFrom = /* @__PURE__ */ __name((path134, type) => stat(path134).then((stat11) => fromBlob(stat11, path134, type)), "blobFrom");
26305
+ fileFrom = /* @__PURE__ */ __name((path134, type) => stat(path134).then((stat11) => fromFile(stat11, path134, type)), "fileFrom");
26306
26306
  fileFromSync = /* @__PURE__ */ __name((path134, type) => fromFile(statSync(path134), path134, type), "fileFromSync");
26307
- fromBlob = /* @__PURE__ */ __name((stat10, path134, type = "") => new fetch_blob_default([new BlobDataItem({
26307
+ fromBlob = /* @__PURE__ */ __name((stat11, path134, type = "") => new fetch_blob_default([new BlobDataItem({
26308
26308
  path: path134,
26309
- size: stat10.size,
26310
- lastModified: stat10.mtimeMs,
26309
+ size: stat11.size,
26310
+ lastModified: stat11.mtimeMs,
26311
26311
  start: 0
26312
26312
  })], { type }), "fromBlob");
26313
- fromFile = /* @__PURE__ */ __name((stat10, path134, type = "") => new file_default([new BlobDataItem({
26313
+ fromFile = /* @__PURE__ */ __name((stat11, path134, type = "") => new file_default([new BlobDataItem({
26314
26314
  path: path134,
26315
- size: stat10.size,
26316
- lastModified: stat10.mtimeMs,
26315
+ size: stat11.size,
26316
+ lastModified: stat11.mtimeMs,
26317
26317
  start: 0
26318
- })], basename(path134), { type, lastModified: stat10.mtimeMs }), "fromFile");
26318
+ })], basename(path134), { type, lastModified: stat11.mtimeMs }), "fromFile");
26319
26319
  BlobDataItem = class _BlobDataItem {
26320
26320
  static {
26321
26321
  __name(this, "BlobDataItem");
@@ -123779,18 +123779,18 @@ var require_async = __commonJS({
123779
123779
  ];
123780
123780
  }, "defaultPaths");
123781
123781
  var defaultIsFile = /* @__PURE__ */ __name(function isFile3(file, cb) {
123782
- fs122.stat(file, function(err, stat10) {
123782
+ fs122.stat(file, function(err, stat11) {
123783
123783
  if (!err) {
123784
- return cb(null, stat10.isFile() || stat10.isFIFO());
123784
+ return cb(null, stat11.isFile() || stat11.isFIFO());
123785
123785
  }
123786
123786
  if (err.code === "ENOENT" || err.code === "ENOTDIR") return cb(null, false);
123787
123787
  return cb(err);
123788
123788
  });
123789
123789
  }, "isFile");
123790
123790
  var defaultIsDir = /* @__PURE__ */ __name(function isDirectory(dir, cb) {
123791
- fs122.stat(dir, function(err, stat10) {
123791
+ fs122.stat(dir, function(err, stat11) {
123792
123792
  if (!err) {
123793
- return cb(null, stat10.isDirectory());
123793
+ return cb(null, stat11.isDirectory());
123794
123794
  }
123795
123795
  if (err.code === "ENOENT" || err.code === "ENOTDIR") return cb(null, false);
123796
123796
  return cb(err);
@@ -124286,21 +124286,21 @@ var require_sync = __commonJS({
124286
124286
  }, "defaultPaths");
124287
124287
  var defaultIsFile = /* @__PURE__ */ __name(function isFile3(file) {
124288
124288
  try {
124289
- var stat10 = fs122.statSync(file, { throwIfNoEntry: false });
124289
+ var stat11 = fs122.statSync(file, { throwIfNoEntry: false });
124290
124290
  } catch (e4) {
124291
124291
  if (e4 && (e4.code === "ENOENT" || e4.code === "ENOTDIR")) return false;
124292
124292
  throw e4;
124293
124293
  }
124294
- return !!stat10 && (stat10.isFile() || stat10.isFIFO());
124294
+ return !!stat11 && (stat11.isFile() || stat11.isFIFO());
124295
124295
  }, "isFile");
124296
124296
  var defaultIsDir = /* @__PURE__ */ __name(function isDirectory(dir) {
124297
124297
  try {
124298
- var stat10 = fs122.statSync(dir, { throwIfNoEntry: false });
124298
+ var stat11 = fs122.statSync(dir, { throwIfNoEntry: false });
124299
124299
  } catch (e4) {
124300
124300
  if (e4 && (e4.code === "ENOENT" || e4.code === "ENOTDIR")) return false;
124301
124301
  throw e4;
124302
124302
  }
124303
- return !!stat10 && stat10.isDirectory();
124303
+ return !!stat11 && stat11.isDirectory();
124304
124304
  }, "isDirectory");
124305
124305
  var defaultRealpathSync = /* @__PURE__ */ __name(function realpathSync8(x3) {
124306
124306
  try {
@@ -124726,14 +124726,14 @@ var require_require_in_the_middle = __commonJS({
124726
124726
  moduleName2 = parsedPath.name;
124727
124727
  basedir = parsedPath.dir;
124728
124728
  } else {
124729
- const stat10 = moduleDetailsFromPath(filename);
124730
- if (stat10 === void 0) {
124729
+ const stat11 = moduleDetailsFromPath(filename);
124730
+ if (stat11 === void 0) {
124731
124731
  debug3("could not parse filename: %s", filename);
124732
124732
  return exports3;
124733
124733
  }
124734
- moduleName2 = stat10.name;
124735
- basedir = stat10.basedir;
124736
- const fullModuleName = resolveModuleName(stat10);
124734
+ moduleName2 = stat11.name;
124735
+ basedir = stat11.basedir;
124736
+ const fullModuleName = resolveModuleName(stat11);
124737
124737
  debug3("resolved filename to module: %s (id: %s, resolved: %s, basedir: %s)", moduleName2, id, fullModuleName, basedir);
124738
124738
  let matchFound = false;
124739
124739
  if (hasWhitelist) {
@@ -124797,9 +124797,9 @@ var require_require_in_the_middle = __commonJS({
124797
124797
  }
124798
124798
  }
124799
124799
  };
124800
- function resolveModuleName(stat10) {
124801
- const normalizedPath = path134.sep !== "/" ? stat10.path.split(path134.sep).join("/") : stat10.path;
124802
- return path134.posix.join(stat10.name, normalizedPath).replace(normalize11, "");
124800
+ function resolveModuleName(stat11) {
124801
+ const normalizedPath = path134.sep !== "/" ? stat11.path.split(path134.sep).join("/") : stat11.path;
124802
+ return path134.posix.join(stat11.name, normalizedPath).replace(normalize11, "");
124803
124803
  }
124804
124804
  __name(resolveModuleName, "resolveModuleName");
124805
124805
  }
@@ -158380,7 +158380,7 @@ __export(geminiContentGenerator_exports2, {
158380
158380
  createGeminiContentGenerator: () => createGeminiContentGenerator
158381
158381
  });
158382
158382
  function createGeminiContentGenerator(config2, gcConfig) {
158383
- const version2 = "0.2.3-alpha.3";
158383
+ const version2 = "0.2.3-alpha.4";
158384
158384
  const userAgent2 = config2.userAgent || `QwenCode/${version2} (${process.platform}; ${process.arch})`;
158385
158385
  const baseHeaders = {
158386
158386
  "User-Agent": userAgent2
@@ -191292,12 +191292,12 @@ var require_src36 = __commonJS({
191292
191292
  function check2(path134, isFile3, isDirectory) {
191293
191293
  log(`checking %s`, path134);
191294
191294
  try {
191295
- const stat10 = fs_1.statSync(path134);
191296
- if (stat10.isFile() && isFile3) {
191295
+ const stat11 = fs_1.statSync(path134);
191296
+ if (stat11.isFile() && isFile3) {
191297
191297
  log(`[OK] path represents a file`);
191298
191298
  return true;
191299
191299
  }
191300
- if (stat10.isDirectory() && isDirectory) {
191300
+ if (stat11.isDirectory() && isDirectory) {
191301
191301
  log(`[OK] path represents a directory`);
191302
191302
  return true;
191303
191303
  }
@@ -207393,16 +207393,16 @@ var require_windows = __commonJS({
207393
207393
  return false;
207394
207394
  }
207395
207395
  __name(checkPathExt, "checkPathExt");
207396
- function checkStat(stat10, path134, options2) {
207397
- if (!stat10.isSymbolicLink() && !stat10.isFile()) {
207396
+ function checkStat(stat11, path134, options2) {
207397
+ if (!stat11.isSymbolicLink() && !stat11.isFile()) {
207398
207398
  return false;
207399
207399
  }
207400
207400
  return checkPathExt(path134, options2);
207401
207401
  }
207402
207402
  __name(checkStat, "checkStat");
207403
207403
  function isexe(path134, options2, cb) {
207404
- fs122.stat(path134, function(er2, stat10) {
207405
- cb(er2, er2 ? false : checkStat(stat10, path134, options2));
207404
+ fs122.stat(path134, function(er2, stat11) {
207405
+ cb(er2, er2 ? false : checkStat(stat11, path134, options2));
207406
207406
  });
207407
207407
  }
207408
207408
  __name(isexe, "isexe");
@@ -207421,8 +207421,8 @@ var require_mode = __commonJS({
207421
207421
  isexe.sync = sync2;
207422
207422
  var fs122 = __require("fs");
207423
207423
  function isexe(path134, options2, cb) {
207424
- fs122.stat(path134, function(er2, stat10) {
207425
- cb(er2, er2 ? false : checkStat(stat10, options2));
207424
+ fs122.stat(path134, function(er2, stat11) {
207425
+ cb(er2, er2 ? false : checkStat(stat11, options2));
207426
207426
  });
207427
207427
  }
207428
207428
  __name(isexe, "isexe");
@@ -207430,14 +207430,14 @@ var require_mode = __commonJS({
207430
207430
  return checkStat(fs122.statSync(path134), options2);
207431
207431
  }
207432
207432
  __name(sync2, "sync");
207433
- function checkStat(stat10, options2) {
207434
- return stat10.isFile() && checkMode(stat10, options2);
207433
+ function checkStat(stat11, options2) {
207434
+ return stat11.isFile() && checkMode(stat11, options2);
207435
207435
  }
207436
207436
  __name(checkStat, "checkStat");
207437
- function checkMode(stat10, options2) {
207438
- var mod2 = stat10.mode;
207439
- var uid = stat10.uid;
207440
- var gid = stat10.gid;
207437
+ function checkMode(stat11, options2) {
207438
+ var mod2 = stat11.mode;
207439
+ var uid = stat11.uid;
207440
+ var gid = stat11.gid;
207441
207441
  var myUid = options2.uid !== void 0 ? options2.uid : process.getuid && process.getuid();
207442
207442
  var myGid = options2.gid !== void 0 ? options2.gid : process.getgid && process.getgid();
207443
207443
  var u2 = parseInt("100", 8);
@@ -208631,14 +208631,14 @@ var init_ide_client = __esm({
208631
208631
  lockFiles.map(async (file) => {
208632
208632
  const fullPath = path34.join(ideDir, file);
208633
208633
  try {
208634
- const stat10 = await fs34.promises.stat(fullPath);
208634
+ const stat11 = await fs34.promises.stat(fullPath);
208635
208635
  const content = await fs34.promises.readFile(fullPath, "utf8");
208636
208636
  try {
208637
208637
  const parsed = JSON.parse(content);
208638
- return { file, mtimeMs: stat10.mtimeMs, parsed };
208638
+ return { file, mtimeMs: stat11.mtimeMs, parsed };
208639
208639
  } catch (e4) {
208640
208640
  logger.debug("Failed to parse JSON from lock file: ", e4);
208641
- return { file, mtimeMs: stat10.mtimeMs, parsed: void 0 };
208641
+ return { file, mtimeMs: stat11.mtimeMs, parsed: void 0 };
208642
208642
  }
208643
208643
  } catch (e4) {
208644
208644
  logger.debug("Failed to read/stat IDE lock file:", e4);
@@ -216772,6 +216772,19 @@ var init_mcp_client = __esm({
216772
216772
  getStatus() {
216773
216773
  return this.status;
216774
216774
  }
216775
+ async readResource(uri, options2) {
216776
+ if (this.status !== "connected" /* CONNECTED */) {
216777
+ throw new Error("Client is not connected.");
216778
+ }
216779
+ if (this.client.getServerCapabilities()?.resources == null) {
216780
+ throw new Error("MCP server does not support resources.");
216781
+ }
216782
+ return this.client.request(
216783
+ { method: "resources/read", params: { uri } },
216784
+ ReadResourceResultSchema,
216785
+ options2
216786
+ );
216787
+ }
216775
216788
  updateStatus(status) {
216776
216789
  this.status = status;
216777
216790
  updateMCPServerStatus(this.serverName, status);
@@ -216894,6 +216907,59 @@ var init_mcp_client_manager = __esm({
216894
216907
  await Promise.all(discoveryPromises);
216895
216908
  this.discoveryState = "completed" /* COMPLETED */;
216896
216909
  }
216910
+ /**
216911
+ * Connects to a single MCP server and discovers its tools/prompts.
216912
+ * The connected client is tracked so it can be closed by {@link stop}.
216913
+ *
216914
+ * This is primarily used for on-demand re-discovery flows (e.g. after OAuth).
216915
+ */
216916
+ async discoverMcpToolsForServer(serverName, cliConfig) {
216917
+ const servers = populateMcpServerCommand(
216918
+ this.cliConfig.getMcpServers() || {},
216919
+ this.cliConfig.getMcpServerCommand()
216920
+ );
216921
+ const serverConfig = servers[serverName];
216922
+ if (!serverConfig) {
216923
+ return;
216924
+ }
216925
+ const existingClient = this.clients.get(serverName);
216926
+ if (existingClient) {
216927
+ try {
216928
+ await existingClient.disconnect();
216929
+ } catch (error2) {
216930
+ console.error(
216931
+ `Error stopping client '${serverName}': ${getErrorMessage(error2)}`
216932
+ );
216933
+ } finally {
216934
+ this.clients.delete(serverName);
216935
+ this.eventEmitter?.emit("mcp-client-update", this.clients);
216936
+ }
216937
+ }
216938
+ const sdkCallback = isSdkMcpServerConfig(serverConfig) ? this.sendSdkMcpMessage : void 0;
216939
+ const client = new McpClient(
216940
+ serverName,
216941
+ serverConfig,
216942
+ this.toolRegistry,
216943
+ this.cliConfig.getPromptRegistry(),
216944
+ this.cliConfig.getWorkspaceContext(),
216945
+ this.cliConfig.getDebugMode(),
216946
+ sdkCallback
216947
+ );
216948
+ this.clients.set(serverName, client);
216949
+ this.eventEmitter?.emit("mcp-client-update", this.clients);
216950
+ try {
216951
+ await client.connect();
216952
+ await client.discover(cliConfig);
216953
+ } catch (error2) {
216954
+ console.error(
216955
+ `Error during discovery for server '${serverName}': ${getErrorMessage(
216956
+ error2
216957
+ )}`
216958
+ );
216959
+ } finally {
216960
+ this.eventEmitter?.emit("mcp-client-update", this.clients);
216961
+ }
216962
+ }
216897
216963
  /**
216898
216964
  * Stops all running local MCP servers and closes all client connections.
216899
216965
  * This is the cleanup method to be called on application exit.
@@ -216916,6 +216982,35 @@ var init_mcp_client_manager = __esm({
216916
216982
  getDiscoveryState() {
216917
216983
  return this.discoveryState;
216918
216984
  }
216985
+ async readResource(serverName, uri, options2) {
216986
+ let client = this.clients.get(serverName);
216987
+ if (!client) {
216988
+ const servers = populateMcpServerCommand(
216989
+ this.cliConfig.getMcpServers() || {},
216990
+ this.cliConfig.getMcpServerCommand()
216991
+ );
216992
+ const serverConfig = servers[serverName];
216993
+ if (!serverConfig) {
216994
+ throw new Error(`MCP server '${serverName}' is not configured.`);
216995
+ }
216996
+ const sdkCallback = isSdkMcpServerConfig(serverConfig) ? this.sendSdkMcpMessage : void 0;
216997
+ client = new McpClient(
216998
+ serverName,
216999
+ serverConfig,
217000
+ this.toolRegistry,
217001
+ this.cliConfig.getPromptRegistry(),
217002
+ this.cliConfig.getWorkspaceContext(),
217003
+ this.cliConfig.getDebugMode(),
217004
+ sdkCallback
217005
+ );
217006
+ this.clients.set(serverName, client);
217007
+ this.eventEmitter?.emit("mcp-client-update", this.clients);
217008
+ }
217009
+ if (client.getStatus() !== "connected" /* CONNECTED */) {
217010
+ await client.connect();
217011
+ }
217012
+ return client.readResource(uri, options2);
217013
+ }
216919
217014
  };
216920
217015
  }
216921
217016
  });
@@ -216929,7 +217024,6 @@ var init_tool_registry = __esm({
216929
217024
  "use strict";
216930
217025
  init_esbuild_shims();
216931
217026
  init_tools();
216932
- init_mcp_client();
216933
217027
  init_mcp_client_manager();
216934
217028
  init_mcp_tool();
216935
217029
  import_shell_quote4 = __toESM(require_shell_quote(), 1);
@@ -217141,19 +217235,10 @@ Signal: Signal number or \`(none)\` if no signal was received.
217141
217235
  }
217142
217236
  }
217143
217237
  this.config.getPromptRegistry().removePromptsByServer(serverName);
217144
- const mcpServers = this.config.getMcpServers() ?? {};
217145
- const serverConfig = mcpServers[serverName];
217146
- if (serverConfig) {
217147
- await connectAndDiscover(
217148
- serverName,
217149
- serverConfig,
217150
- this,
217151
- this.config.getPromptRegistry(),
217152
- this.config.getDebugMode(),
217153
- this.config.getWorkspaceContext(),
217154
- this.config
217155
- );
217156
- }
217238
+ await this.mcpClientManager.discoverMcpToolsForServer(
217239
+ serverName,
217240
+ this.config
217241
+ );
217157
217242
  }
217158
217243
  async discoverAndRegisterToolsFromCommand() {
217159
217244
  const discoveryCmd = this.config.getToolDiscoveryCommand();
@@ -217317,6 +217402,23 @@ Signal: Signal number or \`(none)\` if no signal was received.
217317
217402
  getTool(name3) {
217318
217403
  return this.tools.get(name3);
217319
217404
  }
217405
+ async readMcpResource(serverName, uri, options2) {
217406
+ if (!this.config.isTrustedFolder()) {
217407
+ throw new Error("MCP resources are unavailable in untrusted folders.");
217408
+ }
217409
+ return this.mcpClientManager.readResource(serverName, uri, options2);
217410
+ }
217411
+ /**
217412
+ * Stops all MCP clients and cleans up resources.
217413
+ * This method is idempotent and safe to call multiple times.
217414
+ */
217415
+ async stop() {
217416
+ try {
217417
+ await this.mcpClientManager.stop();
217418
+ } catch (error2) {
217419
+ console.error("Error stopping MCP clients:", error2);
217420
+ }
217421
+ }
217320
217422
  };
217321
217423
  }
217322
217424
  });
@@ -222953,7 +223055,7 @@ ${textContent2}
222953
223055
  return `Fetching content from ${this.params.url} and processing with prompt: "${displayPrompt}"`;
222954
223056
  }
222955
223057
  async shouldConfirmExecute() {
222956
- if (this.config.getApprovalMode() === "auto-edit" /* AUTO_EDIT */) {
223058
+ if (this.config.getApprovalMode() === "auto-edit" /* AUTO_EDIT */ || this.config.getApprovalMode() === "plan" /* PLAN */) {
222957
223059
  return false;
222958
223060
  }
222959
223061
  const confirmationDetails = {
@@ -223857,7 +223959,7 @@ var init_web_search = __esm({
223857
223959
  return ` (Searching the web via ${provider})`;
223858
223960
  }
223859
223961
  async shouldConfirmExecute(_abortSignal) {
223860
- if (this.config.getApprovalMode() === "auto-edit" /* AUTO_EDIT */) {
223962
+ if (this.config.getApprovalMode() === "auto-edit" /* AUTO_EDIT */ || this.config.getApprovalMode() === "plan" /* PLAN */) {
223861
223963
  return false;
223862
223964
  }
223863
223965
  const confirmationDetails = {
@@ -227040,8 +227142,8 @@ var init_esm21 = __esm({
227040
227142
  }
227041
227143
  return this._userIgnored(path134, stats);
227042
227144
  }
227043
- _isntIgnored(path134, stat10) {
227044
- return !this._isIgnored(path134, stat10);
227145
+ _isntIgnored(path134, stat11) {
227146
+ return !this._isIgnored(path134, stat11);
227045
227147
  }
227046
227148
  /**
227047
227149
  * Provides a set of common helpers and properties relating to symlink handling.
@@ -227342,9 +227444,15 @@ async function loadSkillsFromDir(baseDir) {
227342
227444
  return [];
227343
227445
  }
227344
227446
  }
227447
+ function normalizeSkillFileContent(content) {
227448
+ let normalized2 = content.replace(/^\uFEFF/, "");
227449
+ normalized2 = normalized2.replace(/\r\n/g, "\n").replace(/\r/g, "\n");
227450
+ return normalized2;
227451
+ }
227345
227452
  function parseSkillContent(content, filePath) {
227346
- const frontmatterRegex = /^---\n([\s\S]*?)\n---\n([\s\S]*)$/;
227347
- const match2 = content.match(frontmatterRegex);
227453
+ const normalizedContent = normalizeSkillFileContent(content);
227454
+ const frontmatterRegex = /^---\n([\s\S]*?)\n---(?:\n|$)([\s\S]*)$/;
227455
+ const match2 = normalizedContent.match(frontmatterRegex);
227348
227456
  if (!match2) {
227349
227457
  throw new Error("Invalid format: missing YAML frontmatter");
227350
227458
  }
@@ -227425,6 +227533,7 @@ var init_skill_load = __esm({
227425
227533
  init_yaml_parser();
227426
227534
  SKILL_MANIFEST_FILE = "SKILL.md";
227427
227535
  __name(loadSkillsFromDir, "loadSkillsFromDir");
227536
+ __name(normalizeSkillFileContent, "normalizeSkillFileContent");
227428
227537
  __name(parseSkillContent, "parseSkillContent");
227429
227538
  __name(validateConfig, "validateConfig");
227430
227539
  }
@@ -227435,7 +227544,7 @@ import * as fs48 from "fs/promises";
227435
227544
  import * as fsSync3 from "fs";
227436
227545
  import * as path52 from "path";
227437
227546
  import * as os21 from "os";
227438
- function normalizeSkillFileContent(content) {
227547
+ function normalizeSkillFileContent2(content) {
227439
227548
  let normalized2 = content.replace(/^\uFEFF/, "");
227440
227549
  normalized2 = normalized2.replace(/\r\n/g, "\n").replace(/\r/g, "\n");
227441
227550
  return normalized2;
@@ -227649,7 +227758,7 @@ var init_skill_manager = __esm({
227649
227758
  */
227650
227759
  parseSkillContent(content, filePath, level) {
227651
227760
  try {
227652
- const normalizedContent = normalizeSkillFileContent(content);
227761
+ const normalizedContent = normalizeSkillFileContent2(content);
227653
227762
  const frontmatterRegex = /^---\n([\s\S]*?)\n---(?:\n|$)([\s\S]*)$/;
227654
227763
  const match2 = normalizedContent.match(frontmatterRegex);
227655
227764
  if (!match2) {
@@ -227744,8 +227853,26 @@ var init_skill_manager = __esm({
227744
227853
  const entries = await fs48.readdir(baseDir, { withFileTypes: true });
227745
227854
  const skills = [];
227746
227855
  for (const entry of entries) {
227747
- if (!entry.isDirectory()) continue;
227856
+ const isDirectory = entry.isDirectory();
227857
+ const isSymlink = entry.isSymbolicLink();
227858
+ if (!isDirectory && !isSymlink) continue;
227748
227859
  const skillDir = path52.join(baseDir, entry.name);
227860
+ if (isSymlink) {
227861
+ try {
227862
+ const targetStat = await fs48.stat(skillDir);
227863
+ if (!targetStat.isDirectory()) {
227864
+ console.warn(
227865
+ `Skipping symlink ${entry.name} that does not point to a directory`
227866
+ );
227867
+ continue;
227868
+ }
227869
+ } catch (error2) {
227870
+ console.warn(
227871
+ `Skipping invalid symlink ${entry.name}: ${error2 instanceof Error ? error2.message : "Unknown error"}`
227872
+ );
227873
+ continue;
227874
+ }
227875
+ }
227749
227876
  const skillManifest = path52.join(skillDir, SKILL_MANIFEST_FILE2);
227750
227877
  try {
227751
227878
  await fs48.access(skillManifest);
@@ -227849,7 +227976,7 @@ var init_skill_manager = __esm({
227849
227976
  }
227850
227977
  }
227851
227978
  };
227852
- __name(normalizeSkillFileContent, "normalizeSkillFileContent");
227979
+ __name(normalizeSkillFileContent2, "normalizeSkillFileContent");
227853
227980
  }
227854
227981
  });
227855
227982
 
@@ -231298,16 +231425,16 @@ var init_list = __esm({
231298
231425
  let fd;
231299
231426
  try {
231300
231427
  fd = fs51.openSync(file, "r");
231301
- const stat10 = fs51.fstatSync(fd);
231428
+ const stat11 = fs51.fstatSync(fd);
231302
231429
  const readSize = opt.maxReadSize || 16 * 1024 * 1024;
231303
- if (stat10.size < readSize) {
231304
- const buf = Buffer.allocUnsafe(stat10.size);
231305
- const read3 = fs51.readSync(fd, buf, 0, stat10.size, 0);
231430
+ if (stat11.size < readSize) {
231431
+ const buf = Buffer.allocUnsafe(stat11.size);
231432
+ const read3 = fs51.readSync(fd, buf, 0, stat11.size, 0);
231306
231433
  p2.end(read3 === buf.byteLength ? buf : buf.subarray(0, read3));
231307
231434
  } else {
231308
231435
  let pos2 = 0;
231309
231436
  const buf = Buffer.allocUnsafe(readSize);
231310
- while (pos2 < stat10.size) {
231437
+ while (pos2 < stat11.size) {
231311
231438
  const bytesRead = fs51.readSync(fd, buf, 0, readSize, pos2);
231312
231439
  if (bytesRead === 0)
231313
231440
  break;
@@ -231332,13 +231459,13 @@ var init_list = __esm({
231332
231459
  const p2 = new Promise((resolve33, reject) => {
231333
231460
  parse14.on("error", reject);
231334
231461
  parse14.on("end", resolve33);
231335
- fs51.stat(file, (er2, stat10) => {
231462
+ fs51.stat(file, (er2, stat11) => {
231336
231463
  if (er2) {
231337
231464
  reject(er2);
231338
231465
  } else {
231339
231466
  const stream2 = new ReadStream(file, {
231340
231467
  readSize,
231341
- size: stat10.size
231468
+ size: stat11.size
231342
231469
  });
231343
231470
  stream2.on("error", reject);
231344
231471
  stream2.pipe(parse14);
@@ -231554,21 +231681,21 @@ var init_write_entry = __esm({
231554
231681
  return super.emit(ev, ...data);
231555
231682
  }
231556
231683
  [LSTAT]() {
231557
- fs52.lstat(this.absolute, (er2, stat10) => {
231684
+ fs52.lstat(this.absolute, (er2, stat11) => {
231558
231685
  if (er2) {
231559
231686
  return this.emit("error", er2);
231560
231687
  }
231561
- this[ONLSTAT](stat10);
231688
+ this[ONLSTAT](stat11);
231562
231689
  });
231563
231690
  }
231564
- [ONLSTAT](stat10) {
231565
- this.statCache.set(this.absolute, stat10);
231566
- this.stat = stat10;
231567
- if (!stat10.isFile()) {
231568
- stat10.size = 0;
231691
+ [ONLSTAT](stat11) {
231692
+ this.statCache.set(this.absolute, stat11);
231693
+ this.stat = stat11;
231694
+ if (!stat11.isFile()) {
231695
+ stat11.size = 0;
231569
231696
  }
231570
- this.type = getType3(stat10);
231571
- this.emit("stat", stat10);
231697
+ this.type = getType3(stat11);
231698
+ this.emit("stat", stat11);
231572
231699
  this[PROCESS2]();
231573
231700
  }
231574
231701
  [PROCESS2]() {
@@ -232018,7 +232145,7 @@ var init_write_entry = __esm({
232018
232145
  return this;
232019
232146
  }
232020
232147
  };
232021
- getType3 = /* @__PURE__ */ __name((stat10) => stat10.isFile() ? "File" : stat10.isDirectory() ? "Directory" : stat10.isSymbolicLink() ? "SymbolicLink" : "Unsupported", "getType");
232148
+ getType3 = /* @__PURE__ */ __name((stat11) => stat11.isFile() ? "File" : stat11.isDirectory() ? "Directory" : stat11.isSymbolicLink() ? "SymbolicLink" : "Unsupported", "getType");
232022
232149
  }
232023
232150
  });
232024
232151
 
@@ -232618,21 +232745,21 @@ var init_pack = __esm({
232618
232745
  [STAT](job) {
232619
232746
  job.pending = true;
232620
232747
  this[JOBS] += 1;
232621
- const stat10 = this.follow ? "stat" : "lstat";
232622
- fs53[stat10](job.absolute, (er2, stat11) => {
232748
+ const stat11 = this.follow ? "stat" : "lstat";
232749
+ fs53[stat11](job.absolute, (er2, stat12) => {
232623
232750
  job.pending = false;
232624
232751
  this[JOBS] -= 1;
232625
232752
  if (er2) {
232626
232753
  this.emit("error", er2);
232627
232754
  } else {
232628
- this[ONSTAT](job, stat11);
232755
+ this[ONSTAT](job, stat12);
232629
232756
  }
232630
232757
  });
232631
232758
  }
232632
- [ONSTAT](job, stat10) {
232633
- this.statCache.set(job.absolute, stat10);
232634
- job.stat = stat10;
232635
- if (!this.filter(job.path, stat10)) {
232759
+ [ONSTAT](job, stat11) {
232760
+ this.statCache.set(job.absolute, stat11);
232761
+ job.stat = stat11;
232762
+ if (!this.filter(job.path, stat11)) {
232636
232763
  job.ignore = true;
232637
232764
  }
232638
232765
  this[PROCESS3]();
@@ -232814,8 +232941,8 @@ var init_pack = __esm({
232814
232941
  resume() {
232815
232942
  }
232816
232943
  [STAT](job) {
232817
- const stat10 = this.follow ? "statSync" : "lstatSync";
232818
- this[ONSTAT](job, fs53[stat10](job.absolute));
232944
+ const stat11 = this.follow ? "statSync" : "lstatSync";
232945
+ this[ONSTAT](job, fs53[stat11](job.absolute));
232819
232946
  }
232820
232947
  [READDIR](job) {
232821
232948
  this[ONREADDIR](job, fs53.readdirSync(job.absolute));
@@ -234115,11 +234242,11 @@ var init_extract = __esm({
234115
234242
  extractFileSync = /* @__PURE__ */ __name((opt) => {
234116
234243
  const u2 = new UnpackSync(opt);
234117
234244
  const file = opt.file;
234118
- const stat10 = fs58.statSync(file);
234245
+ const stat11 = fs58.statSync(file);
234119
234246
  const readSize = opt.maxReadSize || 16 * 1024 * 1024;
234120
234247
  const stream2 = new ReadStreamSync(file, {
234121
234248
  readSize,
234122
- size: stat10.size
234249
+ size: stat11.size
234123
234250
  });
234124
234251
  stream2.pipe(u2);
234125
234252
  }, "extractFileSync");
@@ -234130,13 +234257,13 @@ var init_extract = __esm({
234130
234257
  const p2 = new Promise((resolve33, reject) => {
234131
234258
  u2.on("error", reject);
234132
234259
  u2.on("close", resolve33);
234133
- fs58.stat(file, (er2, stat10) => {
234260
+ fs58.stat(file, (er2, stat11) => {
234134
234261
  if (er2) {
234135
234262
  reject(er2);
234136
234263
  } else {
234137
234264
  const stream2 = new ReadStream(file, {
234138
234265
  readSize,
234139
- size: stat10.size
234266
+ size: stat11.size
234140
234267
  });
234141
234268
  stream2.on("error", reject);
234142
234269
  stream2.pipe(u2);
@@ -234381,9 +234508,9 @@ var init_update = __esm({
234381
234508
  if (!opt.mtimeCache) {
234382
234509
  opt.mtimeCache = /* @__PURE__ */ new Map();
234383
234510
  }
234384
- opt.filter = filter4 ? (path134, stat10) => filter4(path134, stat10) && !/* c8 ignore start */
234385
- ((opt.mtimeCache?.get(path134) ?? stat10.mtime ?? 0) > (stat10.mtime ?? 0)) : (path134, stat10) => !/* c8 ignore start */
234386
- ((opt.mtimeCache?.get(path134) ?? stat10.mtime ?? 0) > (stat10.mtime ?? 0));
234511
+ opt.filter = filter4 ? (path134, stat11) => filter4(path134, stat11) && !/* c8 ignore start */
234512
+ ((opt.mtimeCache?.get(path134) ?? stat11.mtime ?? 0) > (stat11.mtime ?? 0)) : (path134, stat11) => !/* c8 ignore start */
234513
+ ((opt.mtimeCache?.get(path134) ?? stat11.mtime ?? 0) > (stat11.mtime ?? 0));
234387
234514
  }, "mtimeFilter");
234388
234515
  }
234389
234516
  });
@@ -239168,8 +239295,8 @@ async function collectResources(resourcePaths, pluginRoot, destDir) {
239168
239295
  console.warn(`Resource path not found: ${resolvedPath}`);
239169
239296
  continue;
239170
239297
  }
239171
- const stat10 = fs63.statSync(resolvedPath);
239172
- if (stat10.isDirectory()) {
239298
+ const stat11 = fs63.statSync(resolvedPath);
239299
+ if (stat11.isDirectory()) {
239173
239300
  const dirName = path65.basename(resolvedPath);
239174
239301
  const parentDir = path65.dirname(resolvedPath);
239175
239302
  if (dirName === destFolderName && parentDir === pluginRoot) {
@@ -249974,12 +250101,6 @@ var init_config3 = __esm({
249974
250101
  getSessionId() {
249975
250102
  return this.sessionId;
249976
250103
  }
249977
- /**
249978
- * Releases resources owned by the config instance.
249979
- */
249980
- async shutdown() {
249981
- this.skillManager?.stopWatching();
249982
- }
249983
250104
  /**
249984
250105
  * Starts a new session and resets session-scoped services.
249985
250106
  */
@@ -250120,6 +250241,24 @@ var init_config3 = __esm({
250120
250241
  getToolRegistry() {
250121
250242
  return this.toolRegistry;
250122
250243
  }
250244
+ /**
250245
+ * Shuts down the Config and releases all resources.
250246
+ * This method is idempotent and safe to call multiple times.
250247
+ * It handles the case where initialization was not completed.
250248
+ */
250249
+ async shutdown() {
250250
+ if (!this.initialized) {
250251
+ return;
250252
+ }
250253
+ try {
250254
+ this.skillManager?.stopWatching();
250255
+ if (this.toolRegistry) {
250256
+ await this.toolRegistry.stop();
250257
+ }
250258
+ } catch (error2) {
250259
+ console.error("Error during Config shutdown:", error2);
250260
+ }
250261
+ }
250123
250262
  getPromptRegistry() {
250124
250263
  return this.promptRegistry;
250125
250264
  }
@@ -253607,12 +253746,12 @@ var require_resolve_symlink = __commonJS({
253607
253746
  fs_1.default.realpath(path134, (error2, resolvedPath) => {
253608
253747
  if (error2)
253609
253748
  return queue.dequeue(suppressErrors ? null : error2, state);
253610
- fs_1.default.stat(resolvedPath, (error3, stat10) => {
253749
+ fs_1.default.stat(resolvedPath, (error3, stat11) => {
253611
253750
  if (error3)
253612
253751
  return queue.dequeue(suppressErrors ? null : error3, state);
253613
- if (stat10.isDirectory() && isRecursive(path134, resolvedPath, state))
253752
+ if (stat11.isDirectory() && isRecursive(path134, resolvedPath, state))
253614
253753
  return queue.dequeue(null, state);
253615
- callback(stat10, resolvedPath);
253754
+ callback(stat11, resolvedPath);
253616
253755
  queue.dequeue(null, state);
253617
253756
  });
253618
253757
  });
@@ -253622,10 +253761,10 @@ var require_resolve_symlink = __commonJS({
253622
253761
  queue.enqueue();
253623
253762
  try {
253624
253763
  const resolvedPath = fs_1.default.realpathSync(path134);
253625
- const stat10 = fs_1.default.statSync(resolvedPath);
253626
- if (stat10.isDirectory() && isRecursive(path134, resolvedPath, state))
253764
+ const stat11 = fs_1.default.statSync(resolvedPath);
253765
+ if (stat11.isDirectory() && isRecursive(path134, resolvedPath, state))
253627
253766
  return;
253628
- callback(stat10, resolvedPath);
253767
+ callback(stat11, resolvedPath);
253629
253768
  } catch (e4) {
253630
253769
  if (!suppressErrors)
253631
253770
  throw e4;
@@ -253944,8 +254083,8 @@ var require_walker = __commonJS({
253944
254083
  this.walkDirectory(this.state, path134, path134, depth - 1, this.walk);
253945
254084
  } else if (this.resolveSymlink && entry.isSymbolicLink()) {
253946
254085
  let path134 = joinPath.joinPathWithBasePath(entry.name, directoryPath);
253947
- this.resolveSymlink(path134, this.state, (stat10, resolvedPath) => {
253948
- if (stat10.isDirectory()) {
254086
+ this.resolveSymlink(path134, this.state, (stat11, resolvedPath) => {
254087
+ if (stat11.isDirectory()) {
253949
254088
  resolvedPath = (0, utils_1.normalizePath)(resolvedPath, this.state.options);
253950
254089
  if (exclude && exclude(entry.name, useRealPaths ? resolvedPath : path134 + pathSeparator))
253951
254090
  return;
@@ -255920,7 +256059,7 @@ var init_skills = __esm({
255920
256059
  import * as fs74 from "node:fs";
255921
256060
  import * as path79 from "node:path";
255922
256061
  import * as https5 from "node:https";
255923
- import { stat as stat6 } from "node:fs/promises";
256062
+ import { stat as stat7 } from "node:fs/promises";
255924
256063
  function parseSourceAndPluginName(source2) {
255925
256064
  const urlSchemes = ["http://", "https://", "git@", "sso://"];
255926
256065
  let repoEndIndex = source2.length;
@@ -256049,7 +256188,7 @@ async function parseInstallSource(source2) {
256049
256188
  }
256050
256189
  } else {
256051
256190
  try {
256052
- await stat6(repo);
256191
+ await stat7(repo);
256053
256192
  installMetadata = {
256054
256193
  source: repo,
256055
256194
  type: "local",
@@ -259939,8 +260078,8 @@ var init_git_commit = __esm({
259939
260078
  "packages/core/src/generated/git-commit.ts"() {
259940
260079
  "use strict";
259941
260080
  init_esbuild_shims();
259942
- GIT_COMMIT_INFO = "982b367d4";
259943
- CLI_VERSION = "0.2.3-alpha.3";
260081
+ GIT_COMMIT_INFO = "1ebbd0090";
260082
+ CLI_VERSION = "0.2.3-alpha.4";
259944
260083
  }
259945
260084
  });
259946
260085
 
@@ -360734,7 +360873,7 @@ __name(getPackageJson, "getPackageJson");
360734
360873
  // packages/cli/src/utils/version.ts
360735
360874
  async function getCliVersion() {
360736
360875
  const pkgJson = await getPackageJson();
360737
- return "0.2.3-alpha.3";
360876
+ return "0.2.3-alpha.4";
360738
360877
  }
360739
360878
  __name(getCliVersion, "getCliVersion");
360740
360879
 
@@ -368464,7 +368603,7 @@ var formatDuration = /* @__PURE__ */ __name((milliseconds) => {
368464
368603
 
368465
368604
  // packages/cli/src/generated/git-commit.ts
368466
368605
  init_esbuild_shims();
368467
- var GIT_COMMIT_INFO2 = "982b367d4";
368606
+ var GIT_COMMIT_INFO2 = "1ebbd0090";
368468
368607
 
368469
368608
  // packages/cli/src/utils/systemInfo.ts
368470
368609
  async function getNpmVersion() {
@@ -378231,6 +378370,161 @@ function parseAllAtCommands(query) {
378231
378370
  );
378232
378371
  }
378233
378372
  __name(parseAllAtCommands, "parseAllAtCommands");
378373
+ function getConfiguredMcpServerNames(config2) {
378374
+ const names = new Set(Object.keys(config2.getMcpServers() ?? {}));
378375
+ if (config2.getMcpServerCommand()) {
378376
+ names.add("mcp");
378377
+ }
378378
+ return names;
378379
+ }
378380
+ __name(getConfiguredMcpServerNames, "getConfiguredMcpServerNames");
378381
+ function normalizeMcpResourceUri(serverName, resource) {
378382
+ if (resource.includes("://")) {
378383
+ return resource;
378384
+ }
378385
+ const cleaned = resource.startsWith("/") ? resource.slice(1) : resource;
378386
+ return `${serverName}://${cleaned}`;
378387
+ }
378388
+ __name(normalizeMcpResourceUri, "normalizeMcpResourceUri");
378389
+ function splitLeadingToken(text) {
378390
+ let i3 = 0;
378391
+ while (i3 < text.length && /\s/.test(text[i3])) {
378392
+ i3++;
378393
+ }
378394
+ if (i3 >= text.length) {
378395
+ return null;
378396
+ }
378397
+ let token2 = "";
378398
+ let inEscape = false;
378399
+ while (i3 < text.length) {
378400
+ const char = text[i3];
378401
+ if (inEscape) {
378402
+ token2 += char;
378403
+ inEscape = false;
378404
+ i3++;
378405
+ continue;
378406
+ }
378407
+ if (char === "\\") {
378408
+ inEscape = true;
378409
+ i3++;
378410
+ continue;
378411
+ }
378412
+ if (/[,\s;!?()[\]{}]/.test(char)) {
378413
+ break;
378414
+ }
378415
+ if (char === ".") {
378416
+ const nextChar = i3 + 1 < text.length ? text[i3 + 1] : "";
378417
+ if (nextChar === "" || /\s/.test(nextChar)) {
378418
+ break;
378419
+ }
378420
+ }
378421
+ token2 += char;
378422
+ i3++;
378423
+ }
378424
+ if (!token2) {
378425
+ return null;
378426
+ }
378427
+ return { token: token2, rest: text.slice(i3) };
378428
+ }
378429
+ __name(splitLeadingToken, "splitLeadingToken");
378430
+ function extractMcpResourceAtReferences(parts, config2) {
378431
+ const configuredServers = getConfiguredMcpServerNames(config2);
378432
+ const refs = [];
378433
+ const merged = [];
378434
+ for (let i3 = 0; i3 < parts.length; i3++) {
378435
+ const part = parts[i3];
378436
+ if (part.type !== "atPath") {
378437
+ merged.push(part);
378438
+ continue;
378439
+ }
378440
+ const atText = part.content;
378441
+ const colonIndex = atText.indexOf(":");
378442
+ if (!atText.startsWith("@") || colonIndex <= 1) {
378443
+ merged.push(part);
378444
+ continue;
378445
+ }
378446
+ const serverName = atText.slice(1, colonIndex);
378447
+ if (!configuredServers.has(serverName)) {
378448
+ merged.push(part);
378449
+ continue;
378450
+ }
378451
+ let resource = atText.slice(colonIndex + 1);
378452
+ if (!resource) {
378453
+ const next = parts[i3 + 1];
378454
+ if (next?.type === "text") {
378455
+ const tokenInfo = splitLeadingToken(next.content);
378456
+ if (tokenInfo) {
378457
+ resource = tokenInfo.token;
378458
+ const remainingText = tokenInfo.rest;
378459
+ parts[i3 + 1] = { type: "text", content: remainingText };
378460
+ }
378461
+ }
378462
+ }
378463
+ if (!resource) {
378464
+ merged.push({ type: "text", content: atText });
378465
+ continue;
378466
+ }
378467
+ const normalizedResource = resource.includes("://") ? resource : resource.startsWith("/") ? resource.slice(1) : resource;
378468
+ const normalizedAtCommand = `@${serverName}:${normalizedResource}`;
378469
+ refs.push({
378470
+ atCommand: normalizedAtCommand,
378471
+ serverName,
378472
+ uri: normalizeMcpResourceUri(serverName, normalizedResource)
378473
+ });
378474
+ merged.push({ type: "atPath", content: normalizedAtCommand });
378475
+ }
378476
+ return {
378477
+ parts: merged.filter(
378478
+ (p2) => !(p2.type === "text" && p2.content.trim() === "")
378479
+ ),
378480
+ refs
378481
+ };
378482
+ }
378483
+ __name(extractMcpResourceAtReferences, "extractMcpResourceAtReferences");
378484
+ function formatMcpResourceContents(raw2, limits) {
378485
+ if (!raw2 || typeof raw2 !== "object") {
378486
+ return "[Error: Invalid MCP resource response]";
378487
+ }
378488
+ const contents = raw2.contents;
378489
+ if (!Array.isArray(contents)) {
378490
+ return "[Error: Invalid MCP resource response]";
378491
+ }
378492
+ const parts = [];
378493
+ for (const item of contents) {
378494
+ if (!item || typeof item !== "object") {
378495
+ continue;
378496
+ }
378497
+ const text = item.text;
378498
+ const blob = item.blob;
378499
+ const mimeType = item.mimeType;
378500
+ if (typeof text === "string") {
378501
+ parts.push(text);
378502
+ continue;
378503
+ }
378504
+ if (typeof blob === "string") {
378505
+ const mimeTypeLabel = typeof mimeType === "string" ? mimeType : "application/octet-stream";
378506
+ parts.push(
378507
+ `[Binary MCP resource omitted (mimeType: ${mimeTypeLabel}, bytes: ${blob.length})]`
378508
+ );
378509
+ }
378510
+ }
378511
+ let combined = parts.join("\n\n");
378512
+ const maxLines = limits.maxLinesPerResource;
378513
+ if (Number.isFinite(maxLines)) {
378514
+ const lines = combined.split("\n");
378515
+ if (lines.length > maxLines) {
378516
+ combined = `${lines.slice(0, maxLines).join("\n")}
378517
+ [truncated]`;
378518
+ }
378519
+ }
378520
+ const maxChars = limits.maxCharsPerResource;
378521
+ if (Number.isFinite(maxChars) && combined.length > maxChars) {
378522
+ combined = `${combined.slice(0, maxChars)}
378523
+ [truncated]`;
378524
+ }
378525
+ return combined;
378526
+ }
378527
+ __name(formatMcpResourceContents, "formatMcpResourceContents");
378234
378528
  async function handleAtCommand({
378235
378529
  query,
378236
378530
  config: config2,
@@ -378239,10 +378533,15 @@ async function handleAtCommand({
378239
378533
  messageId: userMessageTimestamp,
378240
378534
  signal
378241
378535
  }) {
378242
- const commandParts = parseAllAtCommands(query);
378536
+ const parsedParts = parseAllAtCommands(query);
378537
+ const { parts: commandParts, refs: mcpResourceRefs } = extractMcpResourceAtReferences(parsedParts, config2);
378538
+ const mcpAtCommands = new Set(mcpResourceRefs.map((r5) => r5.atCommand));
378243
378539
  const atPathCommandParts = commandParts.filter(
378244
378540
  (part) => part.type === "atPath"
378245
378541
  );
378542
+ const fileAtPathCommandParts = atPathCommandParts.filter(
378543
+ (part) => !mcpAtCommands.has(part.content)
378544
+ );
378246
378545
  if (atPathCommandParts.length === 0) {
378247
378546
  return { processedQuery: [{ text: query }], shouldProceed: true };
378248
378547
  }
@@ -378259,14 +378558,7 @@ async function handleAtCommand({
378259
378558
  const toolRegistry = config2.getToolRegistry();
378260
378559
  const readManyFilesTool = toolRegistry.getTool("read_many_files");
378261
378560
  const globTool = toolRegistry.getTool("glob");
378262
- if (!readManyFilesTool) {
378263
- addItem(
378264
- { type: "error", text: "Error: read_many_files tool not found." },
378265
- userMessageTimestamp
378266
- );
378267
- return { processedQuery: null, shouldProceed: false };
378268
- }
378269
- for (const atPathPart of atPathCommandParts) {
378561
+ for (const atPathPart of fileAtPathCommandParts) {
378270
378562
  const originalAtPath = atPathPart.content;
378271
378563
  if (originalAtPath === "@") {
378272
378564
  onDebugMessage(
@@ -378426,7 +378718,7 @@ ${messages.join("\n")}`;
378426
378718
  console.log(message);
378427
378719
  onDebugMessage(message);
378428
378720
  }
378429
- if (pathSpecsToRead.length === 0) {
378721
+ if (pathSpecsToRead.length === 0 && mcpResourceRefs.length === 0) {
378430
378722
  onDebugMessage("No valid file paths found in @ commands to read.");
378431
378723
  if (initialQueryText === "@" && query.trim() === "@") {
378432
378724
  return { processedQuery: [{ text: query }], shouldProceed: true };
@@ -378439,76 +378731,146 @@ ${messages.join("\n")}`;
378439
378731
  };
378440
378732
  }
378441
378733
  const processedQueryParts = [{ text: initialQueryText }];
378442
- const toolArgs = {
378443
- paths: pathSpecsToRead,
378444
- file_filtering_options: {
378445
- respect_git_ignore: respectFileIgnore.respectGitIgnore,
378446
- respect_rdmind_ignore: respectFileIgnore.respectRdmindIgnore
378734
+ const toolDisplays = [];
378735
+ if (pathSpecsToRead.length > 0) {
378736
+ if (!readManyFilesTool) {
378737
+ addItem(
378738
+ { type: "error", text: "Error: read_many_files tool not found." },
378739
+ userMessageTimestamp
378740
+ );
378741
+ return { processedQuery: null, shouldProceed: false };
378447
378742
  }
378448
- // Use configuration setting
378449
- };
378450
- let toolCallDisplay;
378451
- let invocation = void 0;
378452
- try {
378453
- invocation = readManyFilesTool.build(toolArgs);
378454
- const result = await invocation.execute(signal);
378455
- toolCallDisplay = {
378456
- callId: `client-read-${userMessageTimestamp}`,
378457
- name: readManyFilesTool.displayName,
378458
- description: invocation.getDescription(),
378459
- status: "Success" /* Success */,
378460
- resultDisplay: result.returnDisplay || `Successfully read: ${contentLabelsForDisplay.join(", ")}`,
378461
- confirmationDetails: void 0
378462
- };
378463
- if (Array.isArray(result.llmContent)) {
378464
- const fileContentRegex = /^--- (.*?) ---\n\n([\s\S]*?)\n\n$/;
378465
- processedQueryParts.push({
378466
- text: "\n--- Content from referenced files ---"
378743
+ const toolArgs = {
378744
+ paths: pathSpecsToRead,
378745
+ file_filtering_options: {
378746
+ respect_git_ignore: respectFileIgnore.respectGitIgnore,
378747
+ respect_rdmind_ignore: respectFileIgnore.respectRdmindIgnore
378748
+ }
378749
+ // Use configuration setting
378750
+ };
378751
+ let invocation = void 0;
378752
+ try {
378753
+ invocation = readManyFilesTool.build(toolArgs);
378754
+ const result = await invocation.execute(signal);
378755
+ toolDisplays.push({
378756
+ callId: `client-read-${userMessageTimestamp}`,
378757
+ name: readManyFilesTool.displayName,
378758
+ description: invocation.getDescription(),
378759
+ status: "Success" /* Success */,
378760
+ resultDisplay: result.returnDisplay || `Successfully read: ${contentLabelsForDisplay.join(", ")}`,
378761
+ confirmationDetails: void 0
378467
378762
  });
378468
- for (const part of result.llmContent) {
378469
- if (typeof part === "string") {
378470
- const match2 = fileContentRegex.exec(part);
378471
- if (match2) {
378472
- const filePathSpecInContent = match2[1];
378473
- const fileActualContent = match2[2].trim();
378474
- processedQueryParts.push({
378475
- text: `
378763
+ if (Array.isArray(result.llmContent)) {
378764
+ const fileContentRegex = /^--- (.*?) ---\n\n([\s\S]*?)\n\n$/;
378765
+ processedQueryParts.push({
378766
+ text: "\n--- Content from referenced files ---"
378767
+ });
378768
+ for (const part of result.llmContent) {
378769
+ if (typeof part === "string") {
378770
+ const match2 = fileContentRegex.exec(part);
378771
+ if (match2) {
378772
+ const filePathSpecInContent = match2[1];
378773
+ const fileActualContent = match2[2].trim();
378774
+ processedQueryParts.push({
378775
+ text: `
378476
378776
  Content from @${filePathSpecInContent}:
378477
378777
  `
378478
- });
378479
- processedQueryParts.push({ text: fileActualContent });
378778
+ });
378779
+ processedQueryParts.push({ text: fileActualContent });
378780
+ } else {
378781
+ processedQueryParts.push({ text: part });
378782
+ }
378480
378783
  } else {
378481
- processedQueryParts.push({ text: part });
378784
+ processedQueryParts.push(part);
378482
378785
  }
378483
- } else {
378484
- processedQueryParts.push(part);
378485
378786
  }
378787
+ } else {
378788
+ onDebugMessage(
378789
+ "read_many_files tool returned no content or empty content."
378790
+ );
378486
378791
  }
378487
- } else {
378488
- onDebugMessage(
378489
- "read_many_files tool returned no content or empty content."
378792
+ } catch (error2) {
378793
+ toolDisplays.push({
378794
+ callId: `client-read-${userMessageTimestamp}`,
378795
+ name: readManyFilesTool.displayName,
378796
+ description: invocation?.getDescription() ?? "Error attempting to execute tool to read files",
378797
+ status: "Error" /* Error */,
378798
+ resultDisplay: `Error reading files (${contentLabelsForDisplay.join(", ")}): ${getErrorMessage(error2)}`,
378799
+ confirmationDetails: void 0
378800
+ });
378801
+ addItem(
378802
+ { type: "tool_group", tools: toolDisplays },
378803
+ userMessageTimestamp
378490
378804
  );
378805
+ return { processedQuery: null, shouldProceed: false };
378491
378806
  }
378807
+ }
378808
+ if (mcpResourceRefs.length > 0) {
378809
+ const totalCharLimit = config2.getTruncateToolOutputThreshold();
378810
+ const totalLineLimit = config2.getTruncateToolOutputLines();
378811
+ const maxCharsPerResource = Number.isFinite(totalCharLimit) ? Math.floor(totalCharLimit / Math.max(1, mcpResourceRefs.length)) : Number.POSITIVE_INFINITY;
378812
+ const maxLinesPerResource = Number.isFinite(totalLineLimit) ? Math.floor(totalLineLimit / Math.max(1, mcpResourceRefs.length)) : Number.POSITIVE_INFINITY;
378813
+ processedQueryParts.push({
378814
+ text: "\n--- Content from referenced MCP resources ---"
378815
+ });
378816
+ for (let i3 = 0; i3 < mcpResourceRefs.length; i3++) {
378817
+ const ref = mcpResourceRefs[i3];
378818
+ let resourceResult;
378819
+ try {
378820
+ if (signal.aborted) {
378821
+ const error2 = new Error("MCP resource read aborted");
378822
+ error2.name = "AbortError";
378823
+ throw error2;
378824
+ }
378825
+ resourceResult = await toolRegistry.readMcpResource(
378826
+ ref.serverName,
378827
+ ref.uri,
378828
+ { signal }
378829
+ );
378830
+ toolDisplays.push({
378831
+ callId: `client-mcp-resource-${userMessageTimestamp}-${i3}`,
378832
+ name: "McpResourceRead",
378833
+ description: `Read MCP resource ${ref.uri} (server: ${ref.serverName})`,
378834
+ status: "Success" /* Success */,
378835
+ resultDisplay: `Read: ${ref.uri}`,
378836
+ confirmationDetails: void 0
378837
+ });
378838
+ } catch (error2) {
378839
+ toolDisplays.push({
378840
+ callId: `client-mcp-resource-${userMessageTimestamp}-${i3}`,
378841
+ name: "McpResourceRead",
378842
+ description: `Read MCP resource ${ref.uri} (server: ${ref.serverName})`,
378843
+ status: "Error" /* Error */,
378844
+ resultDisplay: `Error reading MCP resource (${ref.uri}): ${getErrorMessage(error2)}`,
378845
+ confirmationDetails: void 0
378846
+ });
378847
+ addItem(
378848
+ { type: "tool_group", tools: toolDisplays },
378849
+ userMessageTimestamp
378850
+ );
378851
+ return { processedQuery: null, shouldProceed: false };
378852
+ }
378853
+ processedQueryParts.push({
378854
+ text: `
378855
+ Content from ${ref.atCommand}:
378856
+ `
378857
+ });
378858
+ processedQueryParts.push({
378859
+ text: formatMcpResourceContents(resourceResult, {
378860
+ maxCharsPerResource,
378861
+ maxLinesPerResource
378862
+ })
378863
+ });
378864
+ }
378865
+ processedQueryParts.push({ text: "\n--- End of MCP resource content ---" });
378866
+ }
378867
+ if (toolDisplays.length > 0) {
378492
378868
  addItem(
378493
- { type: "tool_group", tools: [toolCallDisplay] },
378494
- userMessageTimestamp
378495
- );
378496
- return { processedQuery: processedQueryParts, shouldProceed: true };
378497
- } catch (error2) {
378498
- toolCallDisplay = {
378499
- callId: `client-read-${userMessageTimestamp}`,
378500
- name: readManyFilesTool.displayName,
378501
- description: invocation?.getDescription() ?? "Error attempting to execute tool to read files",
378502
- status: "Error" /* Error */,
378503
- resultDisplay: `Error reading files (${contentLabelsForDisplay.join(", ")}): ${getErrorMessage(error2)}`,
378504
- confirmationDetails: void 0
378505
- };
378506
- addItem(
378507
- { type: "tool_group", tools: [toolCallDisplay] },
378869
+ { type: "tool_group", tools: toolDisplays },
378508
378870
  userMessageTimestamp
378509
378871
  );
378510
- return { processedQuery: null, shouldProceed: false };
378511
378872
  }
378873
+ return { processedQuery: processedQueryParts, shouldProceed: true };
378512
378874
  }
378513
378875
  __name(handleAtCommand, "handleAtCommand");
378514
378876
 
@@ -426901,7 +427263,7 @@ var GeminiAgent = class {
426901
427263
  name: APPROVAL_MODE_INFO[mode].name,
426902
427264
  description: APPROVAL_MODE_INFO[mode].description
426903
427265
  }));
426904
- const version2 = "0.2.3-alpha.3";
427266
+ const version2 = "0.2.3-alpha.4";
426905
427267
  return {
426906
427268
  protocolVersion: PROTOCOL_VERSION,
426907
427269
  agentInfo: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rdmind/rdmind",
3
- "version": "0.2.3-alpha.3",
3
+ "version": "0.2.3-alpha.4",
4
4
  "description": "RDMind - AI-powered coding assistant",
5
5
  "type": "module",
6
6
  "main": "cli.js",
@@ -20,7 +20,7 @@
20
20
  "locales"
21
21
  ],
22
22
  "config": {
23
- "sandboxImageUri": "ghcr.io/qwenlm/qwen-code:0.2.3-alpha.3"
23
+ "sandboxImageUri": "ghcr.io/qwenlm/qwen-code:0.2.3-alpha.4"
24
24
  },
25
25
  "publishConfig": {
26
26
  "access": "public"