@qwen-code/qwen-code 0.1.4 → 0.1.5-nightly.20251107.d17c37af

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 +258 -438
  2. package/package.json +2 -2
package/cli.js CHANGED
@@ -182650,7 +182650,7 @@ function createContentGeneratorConfig(config, authType, generationConfig) {
182650
182650
  };
182651
182651
  }
182652
182652
  async function createContentGenerator(config, gcConfig, sessionId2) {
182653
- const version2 = "0.1.4";
182653
+ const version2 = "0.1.5-nightly.20251107.d17c37af";
182654
182654
  const userAgent2 = `QwenCode/${version2} (${process.platform}; ${process.arch})`;
182655
182655
  const baseHeaders = {
182656
182656
  "User-Agent": userAgent2
@@ -184491,6 +184491,7 @@ var init_gitUtils = __esm({
184491
184491
  });
184492
184492
 
184493
184493
  // packages/core/dist/src/utils/paths.js
184494
+ import fs19 from "node:fs";
184494
184495
  import path15 from "node:path";
184495
184496
  import os11 from "node:os";
184496
184497
  import * as crypto11 from "node:crypto";
@@ -184579,11 +184580,51 @@ function isSubpath(parentPath, childPath) {
184579
184580
  const relative10 = pathModule2.relative(parentPath, childPath);
184580
184581
  return !relative10.startsWith(`..${pathModule2.sep}`) && relative10 !== ".." && !pathModule2.isAbsolute(relative10);
184581
184582
  }
184583
+ function resolvePath(baseDir = process.cwd(), relativePath) {
184584
+ const homeDir = os11.homedir();
184585
+ if (relativePath === "~") {
184586
+ return homeDir;
184587
+ } else if (relativePath.startsWith("~/")) {
184588
+ return path15.join(homeDir, relativePath.slice(2));
184589
+ } else if (path15.isAbsolute(relativePath)) {
184590
+ return relativePath;
184591
+ } else {
184592
+ return path15.resolve(baseDir, relativePath);
184593
+ }
184594
+ }
184595
+ function validatePath(config, resolvedPath, options2 = {}) {
184596
+ const { allowFiles = false } = options2;
184597
+ const workspaceContext = config.getWorkspaceContext();
184598
+ if (!workspaceContext.isPathWithinWorkspace(resolvedPath)) {
184599
+ throw new Error("Path is not within workspace");
184600
+ }
184601
+ try {
184602
+ const stats = fs19.statSync(resolvedPath);
184603
+ if (!allowFiles && !stats.isDirectory()) {
184604
+ throw new Error(`Path is not a directory: ${resolvedPath}`);
184605
+ }
184606
+ } catch (error) {
184607
+ if (isNodeError(error) && error.code === "ENOENT") {
184608
+ throw new Error(`Path does not exist: ${resolvedPath}`);
184609
+ }
184610
+ throw error;
184611
+ }
184612
+ }
184613
+ function resolveAndValidatePath(config, relativePath, options2 = {}) {
184614
+ const targetDir = config.getTargetDir();
184615
+ if (!relativePath) {
184616
+ return targetDir;
184617
+ }
184618
+ const resolvedPath = resolvePath(targetDir, relativePath);
184619
+ validatePath(config, resolvedPath, options2);
184620
+ return resolvedPath;
184621
+ }
184582
184622
  var QWEN_DIR5, SHELL_SPECIAL_CHARS;
184583
184623
  var init_paths = __esm({
184584
184624
  "packages/core/dist/src/utils/paths.js"() {
184585
184625
  "use strict";
184586
184626
  init_esbuild_shims();
184627
+ init_errors();
184587
184628
  QWEN_DIR5 = ".qwen";
184588
184629
  SHELL_SPECIAL_CHARS = /[ \t()[\]{};|*?$`'"#&<>!~]/;
184589
184630
  __name(tildeifyPath, "tildeifyPath");
@@ -184593,11 +184634,14 @@ var init_paths = __esm({
184593
184634
  __name(unescapePath, "unescapePath");
184594
184635
  __name(getProjectHash, "getProjectHash");
184595
184636
  __name(isSubpath, "isSubpath");
184637
+ __name(resolvePath, "resolvePath");
184638
+ __name(validatePath, "validatePath");
184639
+ __name(resolveAndValidatePath, "resolveAndValidatePath");
184596
184640
  }
184597
184641
  });
184598
184642
 
184599
184643
  // packages/core/dist/src/tools/memoryTool.js
184600
- import * as fs19 from "node:fs/promises";
184644
+ import * as fs20 from "node:fs/promises";
184601
184645
  import * as path16 from "node:path";
184602
184646
  function setGeminiMdFilename(newFilename) {
184603
184647
  if (Array.isArray(newFilename)) {
@@ -184640,7 +184684,7 @@ function ensureNewlineSeparation(currentContent) {
184640
184684
  }
184641
184685
  async function readMemoryFileContent(scope = "global") {
184642
184686
  try {
184643
- return await fs19.readFile(getMemoryFilePath(scope), "utf-8");
184687
+ return await fs20.readFile(getMemoryFilePath(scope), "utf-8");
184644
184688
  } catch (err) {
184645
184689
  const error = err;
184646
184690
  if (!(error instanceof Error) || error.code !== "ENOENT")
@@ -184849,10 +184893,10 @@ Project: ${projectPath} (current project only)`;
184849
184893
  const memoryFilePath = getMemoryFilePath(scope);
184850
184894
  try {
184851
184895
  if (modified_by_user && modified_content !== void 0) {
184852
- await fs19.mkdir(path16.dirname(memoryFilePath), {
184896
+ await fs20.mkdir(path16.dirname(memoryFilePath), {
184853
184897
  recursive: true
184854
184898
  });
184855
- await fs19.writeFile(memoryFilePath, modified_content, "utf-8");
184899
+ await fs20.writeFile(memoryFilePath, modified_content, "utf-8");
184856
184900
  const successMessage = `Okay, I've updated the ${scope} memory file with your modifications.`;
184857
184901
  return {
184858
184902
  llmContent: successMessage,
@@ -184860,9 +184904,9 @@ Project: ${projectPath} (current project only)`;
184860
184904
  };
184861
184905
  } else {
184862
184906
  await MemoryTool.performAddMemoryEntry(fact, memoryFilePath, {
184863
- readFile: fs19.readFile,
184864
- writeFile: fs19.writeFile,
184865
- mkdir: fs19.mkdir
184907
+ readFile: fs20.readFile,
184908
+ writeFile: fs20.writeFile,
184909
+ mkdir: fs20.mkdir
184866
184910
  });
184867
184911
  const successMessage = `Okay, I've remembered that in ${scope} memory: "${fact}"`;
184868
184912
  return {
@@ -184997,7 +185041,7 @@ ${newContent}`;
184997
185041
 
184998
185042
  // packages/core/dist/src/core/prompts.js
184999
185043
  import path17 from "node:path";
185000
- import fs20 from "node:fs";
185044
+ import fs21 from "node:fs";
185001
185045
  import os12 from "node:os";
185002
185046
  import process18 from "node:process";
185003
185047
  function resolvePathFromEnv(envVar) {
@@ -185057,11 +185101,11 @@ function getCoreSystemPrompt(userMemory, model) {
185057
185101
  if (!systemMdResolution.isSwitch) {
185058
185102
  systemMdPath = systemMdResolution.value;
185059
185103
  }
185060
- if (!fs20.existsSync(systemMdPath)) {
185104
+ if (!fs21.existsSync(systemMdPath)) {
185061
185105
  throw new Error(`missing system prompt file '${systemMdPath}'`);
185062
185106
  }
185063
185107
  }
185064
- const basePrompt = systemMdEnabled ? fs20.readFileSync(systemMdPath, "utf8") : `
185108
+ const basePrompt = systemMdEnabled ? fs21.readFileSync(systemMdPath, "utf8") : `
185065
185109
  You are Qwen Code, an interactive CLI agent developed by Alibaba Group, specializing in software engineering tasks. Your primary goal is to help users safely and efficiently, adhering strictly to the following instructions and utilizing your available tools.
185066
185110
 
185067
185111
  # Core Mandates
@@ -185241,8 +185285,8 @@ Your core function is efficient and safe assistance. Balance extreme conciseness
185241
185285
  const writeSystemMdResolution = resolvePathFromEnv(process18.env["QWEN_WRITE_SYSTEM_MD"]);
185242
185286
  if (writeSystemMdResolution.value && !writeSystemMdResolution.isDisabled) {
185243
185287
  const writePath = writeSystemMdResolution.isSwitch ? systemMdPath : writeSystemMdResolution.value;
185244
- fs20.mkdirSync(path17.dirname(writePath), { recursive: true });
185245
- fs20.writeFileSync(writePath, basePrompt);
185288
+ fs21.mkdirSync(path17.dirname(writePath), { recursive: true });
185289
+ fs21.writeFileSync(writePath, basePrompt);
185246
185290
  }
185247
185291
  const memorySuffix = userMemory && userMemory.trim().length > 0 ? `
185248
185292
 
@@ -196828,7 +196872,7 @@ ${stderr}`));
196828
196872
  });
196829
196873
 
196830
196874
  // packages/core/dist/src/tools/shell.js
196831
- import fs21 from "node:fs";
196875
+ import fs22 from "node:fs";
196832
196876
  import path18 from "node:path";
196833
196877
  import os16, { EOL } from "node:os";
196834
196878
  import crypto12 from "node:crypto";
@@ -197006,8 +197050,8 @@ var init_shell = __esm({
197006
197050
  const result = await resultPromise;
197007
197051
  const backgroundPIDs = [];
197008
197052
  if (os16.platform() !== "win32") {
197009
- if (fs21.existsSync(tempFilePath)) {
197010
- const pgrepLines = fs21.readFileSync(tempFilePath, "utf8").split(EOL).filter(Boolean);
197053
+ if (fs22.existsSync(tempFilePath)) {
197054
+ const pgrepLines = fs22.readFileSync(tempFilePath, "utf8").split(EOL).filter(Boolean);
197011
197055
  for (const line of pgrepLines) {
197012
197056
  if (!/^\d+$/.test(line)) {
197013
197057
  console.error(`pgrep: ${line}`);
@@ -197085,8 +197129,8 @@ ${result.output}`;
197085
197129
  ...executionError
197086
197130
  };
197087
197131
  } finally {
197088
- if (fs21.existsSync(tempFilePath)) {
197089
- fs21.unlinkSync(tempFilePath);
197132
+ if (fs22.existsSync(tempFilePath)) {
197133
+ fs22.unlinkSync(tempFilePath);
197090
197134
  }
197091
197135
  }
197092
197136
  }
@@ -197191,7 +197235,7 @@ Co-authored-by: ${gitCoAuthorSettings.name} <${gitCoAuthorSettings.email}>`;
197191
197235
  });
197192
197236
 
197193
197237
  // packages/core/dist/src/core/coreToolScheduler.js
197194
- import * as fs22 from "node:fs/promises";
197238
+ import * as fs23 from "node:fs/promises";
197195
197239
  import * as path19 from "node:path";
197196
197240
  function createFunctionResponsePart(callId, toolName, output) {
197197
197241
  return {
@@ -197271,7 +197315,7 @@ async function truncateAndSaveToFile(content, callId, projectTempDir, threshold,
197271
197315
  const safeFileName = `${path19.basename(callId)}.output`;
197272
197316
  const outputFile = path19.join(projectTempDir, safeFileName);
197273
197317
  try {
197274
- await fs22.writeFile(outputFile, fileContent);
197318
+ await fs23.writeFile(outputFile, fileContent);
197275
197319
  return {
197276
197320
  content: `Tool output was too large and has been truncated.
197277
197321
  The full output has been saved to: ${outputFile}
@@ -197886,7 +197930,7 @@ var init_thoughtUtils = __esm({
197886
197930
 
197887
197931
  // packages/core/dist/src/services/chatRecordingService.js
197888
197932
  import path20 from "node:path";
197889
- import fs23 from "node:fs";
197933
+ import fs24 from "node:fs";
197890
197934
  import { randomUUID as randomUUID4 } from "node:crypto";
197891
197935
  var ChatRecordingService;
197892
197936
  var init_chatRecordingService = __esm({
@@ -197928,7 +197972,7 @@ var init_chatRecordingService = __esm({
197928
197972
  this.cachedLastConvData = null;
197929
197973
  } else {
197930
197974
  const chatsDir = path20.join(this.config.storage.getProjectTempDir(), "chats");
197931
- fs23.mkdirSync(chatsDir, { recursive: true });
197975
+ fs24.mkdirSync(chatsDir, { recursive: true });
197932
197976
  const timestamp = (/* @__PURE__ */ new Date()).toISOString().slice(0, 16).replace(/:/g, "-");
197933
197977
  const filename = `session-${timestamp}-${this.sessionId.slice(0, 8)}.json`;
197934
197978
  this.conversationFile = path20.join(chatsDir, filename);
@@ -198101,7 +198145,7 @@ var init_chatRecordingService = __esm({
198101
198145
  */
198102
198146
  readConversation() {
198103
198147
  try {
198104
- this.cachedLastConvData = fs23.readFileSync(this.conversationFile, "utf8");
198148
+ this.cachedLastConvData = fs24.readFileSync(this.conversationFile, "utf8");
198105
198149
  return JSON.parse(this.cachedLastConvData);
198106
198150
  } catch (error) {
198107
198151
  if (error.code !== "ENOENT") {
@@ -198130,7 +198174,7 @@ var init_chatRecordingService = __esm({
198130
198174
  conversation.lastUpdated = (/* @__PURE__ */ new Date()).toISOString();
198131
198175
  const newContent = JSON.stringify(conversation, null, 2);
198132
198176
  this.cachedLastConvData = newContent;
198133
- fs23.writeFileSync(this.conversationFile, newContent);
198177
+ fs24.writeFileSync(this.conversationFile, newContent);
198134
198178
  }
198135
198179
  } catch (error) {
198136
198180
  console.error("Error writing conversation file:", error);
@@ -198153,7 +198197,7 @@ var init_chatRecordingService = __esm({
198153
198197
  try {
198154
198198
  const chatsDir = path20.join(this.config.storage.getProjectTempDir(), "chats");
198155
198199
  const sessionPath = path20.join(chatsDir, `${sessionId2}.json`);
198156
- fs23.unlinkSync(sessionPath);
198200
+ fs24.unlinkSync(sessionPath);
198157
198201
  } catch (error) {
198158
198202
  console.error("Error deleting session:", error);
198159
198203
  throw error;
@@ -199002,7 +199046,7 @@ var init_constants3 = __esm({
199002
199046
  });
199003
199047
 
199004
199048
  // packages/core/dist/src/utils/getFolderStructure.js
199005
- import * as fs24 from "node:fs/promises";
199049
+ import * as fs25 from "node:fs/promises";
199006
199050
  import * as path21 from "node:path";
199007
199051
  async function readFullStructure(rootPath, options2) {
199008
199052
  const rootName = path21.basename(rootPath);
@@ -199030,7 +199074,7 @@ async function readFullStructure(rootPath, options2) {
199030
199074
  }
199031
199075
  let entries;
199032
199076
  try {
199033
- const rawEntries = await fs24.readdir(currentPath, { withFileTypes: true });
199077
+ const rawEntries = await fs25.readdir(currentPath, { withFileTypes: true });
199034
199078
  entries = rawEntries.sort((a, b) => a.name.localeCompare(b.name));
199035
199079
  } catch (error) {
199036
199080
  if (isNodeError(error) && (error.code === "EACCES" || error.code === "ENOENT")) {
@@ -206285,7 +206329,7 @@ var require_ignore = __commonJS({
206285
206329
  });
206286
206330
 
206287
206331
  // packages/core/dist/src/utils/gitIgnoreParser.js
206288
- import * as fs25 from "node:fs";
206332
+ import * as fs26 from "node:fs";
206289
206333
  import * as path22 from "node:path";
206290
206334
  var import_ignore, GitIgnoreParser;
206291
206335
  var init_gitIgnoreParser = __esm({
@@ -206306,7 +206350,7 @@ var init_gitIgnoreParser = __esm({
206306
206350
  loadPatternsForFile(patternsFilePath) {
206307
206351
  let content;
206308
206352
  try {
206309
- content = fs25.readFileSync(patternsFilePath, "utf-8");
206353
+ content = fs26.readFileSync(patternsFilePath, "utf-8");
206310
206354
  } catch (_error) {
206311
206355
  return [];
206312
206356
  }
@@ -206366,7 +206410,7 @@ var init_gitIgnoreParser = __esm({
206366
206410
  ig.add(".git");
206367
206411
  if (this.globalPatterns === void 0) {
206368
206412
  const excludeFile = path22.join(this.projectRoot, ".git", "info", "exclude");
206369
- this.globalPatterns = fs25.existsSync(excludeFile) ? this.loadPatternsForFile(excludeFile) : [];
206413
+ this.globalPatterns = fs26.existsSync(excludeFile) ? this.loadPatternsForFile(excludeFile) : [];
206370
206414
  }
206371
206415
  ig.add(this.globalPatterns);
206372
206416
  const pathParts = relativePath.split(path22.sep);
@@ -206391,7 +206435,7 @@ var init_gitIgnoreParser = __esm({
206391
206435
  }
206392
206436
  } else {
206393
206437
  const gitignorePath = path22.join(dir, ".gitignore");
206394
- if (fs25.existsSync(gitignorePath)) {
206438
+ if (fs26.existsSync(gitignorePath)) {
206395
206439
  const patterns = this.loadPatternsForFile(gitignorePath);
206396
206440
  this.cache.set(dir, patterns);
206397
206441
  ig.add(patterns);
@@ -206410,7 +206454,7 @@ var init_gitIgnoreParser = __esm({
206410
206454
  });
206411
206455
 
206412
206456
  // packages/core/dist/src/utils/qwenIgnoreParser.js
206413
- import * as fs26 from "node:fs";
206457
+ import * as fs27 from "node:fs";
206414
206458
  import * as path23 from "node:path";
206415
206459
  var import_ignore2, QwenIgnoreParser;
206416
206460
  var init_qwenIgnoreParser = __esm({
@@ -206433,7 +206477,7 @@ var init_qwenIgnoreParser = __esm({
206433
206477
  const patternsFilePath = path23.join(this.projectRoot, ".qwenignore");
206434
206478
  let content;
206435
206479
  try {
206436
- content = fs26.readFileSync(patternsFilePath, "utf-8");
206480
+ content = fs27.readFileSync(patternsFilePath, "utf-8");
206437
206481
  } catch (_error) {
206438
206482
  return;
206439
206483
  }
@@ -213392,7 +213436,7 @@ var init_esm9 = __esm({
213392
213436
  });
213393
213437
 
213394
213438
  // packages/core/dist/src/services/fileSystemService.js
213395
- import fs27 from "node:fs/promises";
213439
+ import fs28 from "node:fs/promises";
213396
213440
  import * as path26 from "node:path";
213397
213441
  var StandardFileSystemService;
213398
213442
  var init_fileSystemService = __esm({
@@ -213405,10 +213449,10 @@ var init_fileSystemService = __esm({
213405
213449
  __name(this, "StandardFileSystemService");
213406
213450
  }
213407
213451
  async readTextFile(filePath) {
213408
- return fs27.readFile(filePath, "utf-8");
213452
+ return fs28.readFile(filePath, "utf-8");
213409
213453
  }
213410
213454
  async writeTextFile(filePath, content) {
213411
- await fs27.writeFile(filePath, content, "utf-8");
213455
+ await fs28.writeFile(filePath, content, "utf-8");
213412
213456
  }
213413
213457
  findFiles(fileName, searchPaths) {
213414
213458
  return searchPaths.flatMap((searchPath) => {
@@ -218238,7 +218282,7 @@ var init_esm10 = __esm({
218238
218282
  });
218239
218283
 
218240
218284
  // packages/core/dist/src/services/gitService.js
218241
- import * as fs28 from "node:fs/promises";
218285
+ import * as fs29 from "node:fs/promises";
218242
218286
  import * as path27 from "node:path";
218243
218287
  var GitService;
218244
218288
  var init_gitService = __esm({
@@ -218287,9 +218331,9 @@ var init_gitService = __esm({
218287
218331
  async setupShadowGitRepository() {
218288
218332
  const repoDir = this.getHistoryDir();
218289
218333
  const gitConfigPath = path27.join(repoDir, ".gitconfig");
218290
- await fs28.mkdir(repoDir, { recursive: true });
218334
+ await fs29.mkdir(repoDir, { recursive: true });
218291
218335
  const gitConfigContent = "[user]\n name = Qwen Code\n email = qwen-code@qwen.ai\n[commit]\n gpgsign = false\n";
218292
- await fs28.writeFile(gitConfigPath, gitConfigContent);
218336
+ await fs29.writeFile(gitConfigPath, gitConfigContent);
218293
218337
  const repo = simpleGit(repoDir);
218294
218338
  const isRepoDefined = await repo.checkIsRepo(CheckRepoActions.IS_REPO_ROOT);
218295
218339
  if (!isRepoDefined) {
@@ -218302,13 +218346,13 @@ var init_gitService = __esm({
218302
218346
  const shadowGitIgnorePath = path27.join(repoDir, ".gitignore");
218303
218347
  let userGitIgnoreContent = "";
218304
218348
  try {
218305
- userGitIgnoreContent = await fs28.readFile(userGitIgnorePath, "utf-8");
218349
+ userGitIgnoreContent = await fs29.readFile(userGitIgnorePath, "utf-8");
218306
218350
  } catch (error) {
218307
218351
  if (isNodeError(error) && error.code !== "ENOENT") {
218308
218352
  throw error;
218309
218353
  }
218310
218354
  }
218311
- await fs28.writeFile(shadowGitIgnorePath, userGitIgnoreContent);
218355
+ await fs29.writeFile(shadowGitIgnorePath, userGitIgnoreContent);
218312
218356
  }
218313
218357
  get shadowGitRepository() {
218314
218358
  const repoDir = this.getHistoryDir();
@@ -218989,7 +219033,7 @@ var init_ignorePatterns = __esm({
218989
219033
  });
218990
219034
 
218991
219035
  // packages/core/dist/src/utils/fileUtils.js
218992
- import fs29 from "node:fs";
219036
+ import fs30 from "node:fs";
218993
219037
  import fsPromises from "node:fs/promises";
218994
219038
  import path29 from "node:path";
218995
219039
  function detectBOM(buf) {
@@ -219039,7 +219083,7 @@ function decodeUTF32(buf, littleEndian) {
219039
219083
  return out;
219040
219084
  }
219041
219085
  async function readFileWithEncoding(filePath) {
219042
- const full = await fs29.promises.readFile(filePath);
219086
+ const full = await fs30.promises.readFile(filePath);
219043
219087
  if (full.length === 0)
219044
219088
  return "";
219045
219089
  const bom = detectBOM(full);
@@ -219075,7 +219119,7 @@ function isWithinRoot(pathToCheck, rootDirectory) {
219075
219119
  async function isBinaryFile(filePath) {
219076
219120
  let fh = null;
219077
219121
  try {
219078
- fh = await fs29.promises.open(filePath, "r");
219122
+ fh = await fs30.promises.open(filePath, "r");
219079
219123
  const stats = await fh.stat();
219080
219124
  const fileSize = stats.size;
219081
219125
  if (fileSize === 0)
@@ -219143,7 +219187,7 @@ async function detectFileType(filePath) {
219143
219187
  }
219144
219188
  async function processSingleFileContent(filePath, rootDirectory, fileSystemService, offset, limit2) {
219145
219189
  try {
219146
- if (!fs29.existsSync(filePath)) {
219190
+ if (!fs30.existsSync(filePath)) {
219147
219191
  return {
219148
219192
  llmContent: "Could not read file because no file was found at the specified path.",
219149
219193
  returnDisplay: "File not found.",
@@ -219151,7 +219195,7 @@ async function processSingleFileContent(filePath, rootDirectory, fileSystemServi
219151
219195
  errorType: ToolErrorType.FILE_NOT_FOUND
219152
219196
  };
219153
219197
  }
219154
- const stats = await fs29.promises.stat(filePath);
219198
+ const stats = await fs30.promises.stat(filePath);
219155
219199
  if (stats.isDirectory()) {
219156
219200
  return {
219157
219201
  llmContent: "Could not read file because the provided path is a directory, not a file.",
@@ -219233,7 +219277,7 @@ async function processSingleFileContent(filePath, rootDirectory, fileSystemServi
219233
219277
  case "pdf":
219234
219278
  case "audio":
219235
219279
  case "video": {
219236
- const contentBuffer = await fs29.promises.readFile(filePath);
219280
+ const contentBuffer = await fs30.promises.readFile(filePath);
219237
219281
  const base64Data = contentBuffer.toString("base64");
219238
219282
  return {
219239
219283
  llmContent: {
@@ -219267,7 +219311,7 @@ async function processSingleFileContent(filePath, rootDirectory, fileSystemServi
219267
219311
  }
219268
219312
  async function fileExists(filePath) {
219269
219313
  try {
219270
- await fsPromises.access(filePath, fs29.constants.F_OK);
219314
+ await fsPromises.access(filePath, fs30.constants.F_OK);
219271
219315
  return true;
219272
219316
  } catch (_) {
219273
219317
  return false;
@@ -229412,18 +229456,18 @@ var init_stdio2 = __esm({
229412
229456
  });
229413
229457
 
229414
229458
  // packages/core/dist/src/ide/ide-client.js
229415
- import * as fs30 from "node:fs";
229459
+ import * as fs31 from "node:fs";
229416
229460
  import * as os18 from "node:os";
229417
229461
  import * as path33 from "node:path";
229418
229462
  function getRealPath(path108) {
229419
229463
  try {
229420
- return fs30.realpathSync(path108);
229464
+ return fs31.realpathSync(path108);
229421
229465
  } catch (_e) {
229422
229466
  return path108;
229423
229467
  }
229424
229468
  }
229425
229469
  function getIdeServerHost() {
229426
- const isInContainer = fs30.existsSync("/.dockerenv") || fs30.existsSync("/run/.containerenv");
229470
+ const isInContainer = fs31.existsSync("/.dockerenv") || fs31.existsSync("/run/.containerenv");
229427
229471
  return isInContainer ? "host.docker.internal" : "127.0.0.1";
229428
229472
  }
229429
229473
  var import_undici, logger, IDEConnectionStatus, IdeClient;
@@ -229814,14 +229858,14 @@ var init_ide_client = __esm({
229814
229858
  }
229815
229859
  try {
229816
229860
  const portFile = path33.join(os18.tmpdir(), `qwen-code-ide-server-${this.ideProcessInfo.pid}.json`);
229817
- const portFileContents = await fs30.promises.readFile(portFile, "utf8");
229861
+ const portFileContents = await fs31.promises.readFile(portFile, "utf8");
229818
229862
  return JSON.parse(portFileContents);
229819
229863
  } catch (_) {
229820
229864
  }
229821
229865
  const portFileDir = path33.join(os18.tmpdir(), "gemini", "ide");
229822
229866
  let portFiles;
229823
229867
  try {
229824
- portFiles = await fs30.promises.readdir(portFileDir);
229868
+ portFiles = await fs31.promises.readdir(portFileDir);
229825
229869
  } catch (e2) {
229826
229870
  logger.debug("Failed to read IDE connection directory:", e2);
229827
229871
  return void 0;
@@ -229836,7 +229880,7 @@ var init_ide_client = __esm({
229836
229880
  }
229837
229881
  let fileContents;
229838
229882
  try {
229839
- fileContents = await Promise.all(matchingFiles.map((file) => fs30.promises.readFile(path33.join(portFileDir, file), "utf8")));
229883
+ fileContents = await Promise.all(matchingFiles.map((file) => fs31.promises.readFile(path33.join(portFileDir, file), "utf8")));
229840
229884
  } catch (e2) {
229841
229885
  logger.debug("Failed to read IDE connection config file(s):", e2);
229842
229886
  return void 0;
@@ -230015,7 +230059,7 @@ ${errorMessage}`, true);
230015
230059
  });
230016
230060
 
230017
230061
  // packages/core/dist/src/tools/edit.js
230018
- import * as fs31 from "node:fs";
230062
+ import * as fs32 from "node:fs";
230019
230063
  import * as path34 from "node:path";
230020
230064
  function applyReplacement(currentContent, oldString, newString, isNewFile) {
230021
230065
  if (isNewFile) {
@@ -230313,8 +230357,8 @@ var init_edit = __esm({
230313
230357
  */
230314
230358
  ensureParentDirectoriesExist(filePath) {
230315
230359
  const dirName = path34.dirname(filePath);
230316
- if (!fs31.existsSync(dirName)) {
230317
- fs31.mkdirSync(dirName, { recursive: true });
230360
+ if (!fs32.existsSync(dirName)) {
230361
+ fs32.mkdirSync(dirName, { recursive: true });
230318
230362
  }
230319
230363
  }
230320
230364
  };
@@ -230552,7 +230596,7 @@ Eg.
230552
230596
  });
230553
230597
 
230554
230598
  // packages/core/dist/src/tools/glob.js
230555
- import fs32 from "node:fs";
230599
+ import fs33 from "node:fs";
230556
230600
  import path35 from "node:path";
230557
230601
  function sortFileEntries(entries, nowTimestamp, recencyThresholdMs) {
230558
230602
  const sortedEntries = [...entries];
@@ -230573,7 +230617,7 @@ function sortFileEntries(entries, nowTimestamp, recencyThresholdMs) {
230573
230617
  });
230574
230618
  return sortedEntries;
230575
230619
  }
230576
- var GlobToolInvocation, GlobTool;
230620
+ var MAX_FILE_COUNT, GlobToolInvocation, GlobTool;
230577
230621
  var init_glob2 = __esm({
230578
230622
  "packages/core/dist/src/tools/glob.js"() {
230579
230623
  "use strict";
@@ -230585,116 +230629,78 @@ var init_glob2 = __esm({
230585
230629
  init_config3();
230586
230630
  init_constants3();
230587
230631
  init_tool_error();
230632
+ init_errors();
230633
+ MAX_FILE_COUNT = 100;
230588
230634
  __name(sortFileEntries, "sortFileEntries");
230589
230635
  GlobToolInvocation = class extends BaseToolInvocation {
230590
230636
  static {
230591
230637
  __name(this, "GlobToolInvocation");
230592
230638
  }
230593
230639
  config;
230640
+ fileService;
230594
230641
  constructor(config, params) {
230595
230642
  super(params);
230596
230643
  this.config = config;
230644
+ this.fileService = config.getFileService();
230597
230645
  }
230598
230646
  getDescription() {
230599
230647
  let description = `'${this.params.pattern}'`;
230600
230648
  if (this.params.path) {
230601
- const searchDir = path35.resolve(this.config.getTargetDir(), this.params.path || ".");
230602
- const relativePath = makeRelative(searchDir, this.config.getTargetDir());
230603
- description += ` within ${shortenPath(relativePath)}`;
230649
+ description += ` in path '${this.params.path}'`;
230604
230650
  }
230605
230651
  return description;
230606
230652
  }
230607
230653
  async execute(signal) {
230608
230654
  try {
230609
- const workspaceContext = this.config.getWorkspaceContext();
230610
- const workspaceDirectories = workspaceContext.getDirectories();
230611
- let searchDirectories;
230612
- if (this.params.path) {
230613
- const searchDirAbsolute = path35.resolve(this.config.getTargetDir(), this.params.path);
230614
- if (!workspaceContext.isPathWithinWorkspace(searchDirAbsolute)) {
230615
- const rawError = `Error: Path "${this.params.path}" is not within any workspace directory`;
230616
- return {
230617
- llmContent: rawError,
230618
- returnDisplay: `Path is not within workspace`,
230619
- error: {
230620
- message: rawError,
230621
- type: ToolErrorType.PATH_NOT_IN_WORKSPACE
230622
- }
230623
- };
230624
- }
230625
- searchDirectories = [searchDirAbsolute];
230626
- } else {
230627
- searchDirectories = workspaceDirectories;
230628
- }
230629
- const fileDiscovery = this.config.getFileService();
230630
- const allEntries = [];
230631
- for (const searchDir of searchDirectories) {
230632
- let pattern = this.params.pattern;
230633
- const fullPath = path35.join(searchDir, pattern);
230634
- if (fs32.existsSync(fullPath)) {
230635
- pattern = escape3(pattern);
230636
- }
230637
- const entries = await glob(pattern, {
230638
- cwd: searchDir,
230639
- withFileTypes: true,
230640
- nodir: true,
230641
- stat: true,
230642
- nocase: !this.params.case_sensitive,
230643
- dot: true,
230644
- ignore: this.config.getFileExclusions().getGlobExcludes(),
230645
- follow: false,
230646
- signal
230647
- });
230648
- allEntries.push(...entries);
230649
- }
230650
- const relativePaths = allEntries.map((p) => path35.relative(this.config.getTargetDir(), p.fullpath()));
230651
- const { filteredPaths, gitIgnoredCount, qwenIgnoredCount } = fileDiscovery.filterFilesWithReport(relativePaths, {
230652
- respectGitIgnore: this.params?.respect_git_ignore ?? this.config.getFileFilteringOptions().respectGitIgnore ?? DEFAULT_FILE_FILTERING_OPTIONS.respectGitIgnore,
230653
- respectQwenIgnore: this.params?.respect_qwen_ignore ?? this.config.getFileFilteringOptions().respectQwenIgnore ?? DEFAULT_FILE_FILTERING_OPTIONS.respectQwenIgnore
230655
+ const searchDirAbs = resolveAndValidatePath(this.config, this.params.path);
230656
+ const searchLocationDescription = this.params.path ? `within ${searchDirAbs}` : `in the workspace directory`;
230657
+ let pattern = this.params.pattern;
230658
+ const fullPath = path35.join(searchDirAbs, pattern);
230659
+ if (fs33.existsSync(fullPath)) {
230660
+ pattern = escape3(pattern);
230661
+ }
230662
+ const allEntries = await glob(pattern, {
230663
+ cwd: searchDirAbs,
230664
+ withFileTypes: true,
230665
+ nodir: true,
230666
+ stat: true,
230667
+ nocase: true,
230668
+ dot: true,
230669
+ follow: false,
230670
+ signal
230654
230671
  });
230672
+ const relativePaths = allEntries.map((p) => path35.relative(this.config.getTargetDir(), p.fullpath()));
230673
+ const { filteredPaths } = this.fileService.filterFilesWithReport(relativePaths, this.getFileFilteringOptions());
230655
230674
  const filteredAbsolutePaths = new Set(filteredPaths.map((p) => path35.resolve(this.config.getTargetDir(), p)));
230656
230675
  const filteredEntries = allEntries.filter((entry) => filteredAbsolutePaths.has(entry.fullpath()));
230657
230676
  if (!filteredEntries || filteredEntries.length === 0) {
230658
- let message = `No files found matching pattern "${this.params.pattern}"`;
230659
- if (searchDirectories.length === 1) {
230660
- message += ` within ${searchDirectories[0]}`;
230661
- } else {
230662
- message += ` within ${searchDirectories.length} workspace directories`;
230663
- }
230664
- if (gitIgnoredCount > 0) {
230665
- message += ` (${gitIgnoredCount} files were git-ignored)`;
230666
- }
230667
- if (qwenIgnoredCount > 0) {
230668
- message += ` (${qwenIgnoredCount} files were qwen-ignored)`;
230669
- }
230670
230677
  return {
230671
- llmContent: message,
230678
+ llmContent: `No files found matching pattern "${this.params.pattern}" ${searchLocationDescription}`,
230672
230679
  returnDisplay: `No files found`
230673
230680
  };
230674
230681
  }
230675
230682
  const oneDayInMs = 24 * 60 * 60 * 1e3;
230676
230683
  const nowTimestamp = (/* @__PURE__ */ new Date()).getTime();
230677
230684
  const sortedEntries = sortFileEntries(filteredEntries, nowTimestamp, oneDayInMs);
230678
- const sortedAbsolutePaths = sortedEntries.map((entry) => entry.fullpath());
230685
+ const totalFileCount = sortedEntries.length;
230686
+ const truncated = totalFileCount > MAX_FILE_COUNT;
230687
+ const entriesToShow = truncated ? sortedEntries.slice(0, MAX_FILE_COUNT) : sortedEntries;
230688
+ const sortedAbsolutePaths = entriesToShow.map((entry) => entry.fullpath());
230679
230689
  const fileListDescription = sortedAbsolutePaths.join("\n");
230680
- const fileCount = sortedAbsolutePaths.length;
230681
- let resultMessage = `Found ${fileCount} file(s) matching "${this.params.pattern}"`;
230682
- if (searchDirectories.length === 1) {
230683
- resultMessage += ` within ${searchDirectories[0]}`;
230684
- } else {
230685
- resultMessage += ` across ${searchDirectories.length} workspace directories`;
230686
- }
230687
- if (gitIgnoredCount > 0) {
230688
- resultMessage += ` (${gitIgnoredCount} additional files were git-ignored)`;
230689
- }
230690
- if (qwenIgnoredCount > 0) {
230691
- resultMessage += ` (${qwenIgnoredCount} additional files were qwen-ignored)`;
230692
- }
230690
+ let resultMessage = `Found ${totalFileCount} file(s) matching "${this.params.pattern}" ${searchLocationDescription}`;
230693
230691
  resultMessage += `, sorted by modification time (newest first):
230692
+ ---
230694
230693
  ${fileListDescription}`;
230694
+ if (truncated) {
230695
+ const omittedFiles = totalFileCount - MAX_FILE_COUNT;
230696
+ const fileTerm = omittedFiles === 1 ? "file" : "files";
230697
+ resultMessage += `
230698
+ ---
230699
+ [${omittedFiles} ${fileTerm} truncated] ...`;
230700
+ }
230695
230701
  return {
230696
230702
  llmContent: resultMessage,
230697
- returnDisplay: `Found ${fileCount} matching file(s)`
230703
+ returnDisplay: `Found ${totalFileCount} matching file(s)${truncated ? " (truncated)" : ""}`
230698
230704
  };
230699
230705
  } catch (error) {
230700
230706
  const errorMessage = error instanceof Error ? error.message : String(error);
@@ -230702,7 +230708,7 @@ ${fileListDescription}`;
230702
230708
  const rawError = `Error during glob search operation: ${errorMessage}`;
230703
230709
  return {
230704
230710
  llmContent: rawError,
230705
- returnDisplay: `Error: An unexpected error occurred.`,
230711
+ returnDisplay: `Error: ${errorMessage || "An unexpected error occurred."}`,
230706
230712
  error: {
230707
230713
  message: rawError,
230708
230714
  type: ToolErrorType.GLOB_EXECUTION_ERROR
@@ -230710,6 +230716,13 @@ ${fileListDescription}`;
230710
230716
  };
230711
230717
  }
230712
230718
  }
230719
+ getFileFilteringOptions() {
230720
+ const options2 = this.config.getFileFilteringOptions?.();
230721
+ return {
230722
+ respectGitIgnore: options2?.respectGitIgnore ?? DEFAULT_FILE_FILTERING_OPTIONS.respectGitIgnore,
230723
+ respectQwenIgnore: options2?.respectQwenIgnore ?? DEFAULT_FILE_FILTERING_OPTIONS.respectQwenIgnore
230724
+ };
230725
+ }
230713
230726
  };
230714
230727
  GlobTool = class _GlobTool extends BaseDeclarativeTool {
230715
230728
  static {
@@ -230718,27 +230731,15 @@ ${fileListDescription}`;
230718
230731
  config;
230719
230732
  static Name = ToolNames.GLOB;
230720
230733
  constructor(config) {
230721
- super(_GlobTool.Name, "FindFiles", "Efficiently finds files matching specific glob patterns (e.g., `src/**/*.ts`, `**/*.md`), returning absolute paths sorted by modification time (newest first). Ideal for quickly locating files based on their name or path structure, especially in large codebases.", Kind.Search, {
230734
+ super(_GlobTool.Name, "FindFiles", 'Fast file pattern matching tool that works with any codebase size\n- Supports glob patterns like "**/*.js" or "src/**/*.ts"\n- Returns matching file paths sorted by modification time\n- Use this tool when you need to find files by name patterns\n- When you are doing an open ended search that may require multiple rounds of globbing and grepping, use the Agent tool instead\n- You have the capability to call multiple tools in a single response. It is always better to speculatively perform multiple searches as a batch that are potentially useful.', Kind.Search, {
230722
230735
  properties: {
230723
230736
  pattern: {
230724
- description: "The glob pattern to match against (e.g., '**/*.py', 'docs/*.md').",
230737
+ description: "The glob pattern to match files against",
230725
230738
  type: "string"
230726
230739
  },
230727
230740
  path: {
230728
- description: "Optional: The absolute path to the directory to search within. If omitted, searches the root directory.",
230741
+ description: 'The directory to search in. If not specified, the current working directory will be used. IMPORTANT: Omit this field to use the default directory. DO NOT enter "undefined" or "null" - simply omit it for the default behavior. Must be a valid directory path if provided.',
230729
230742
  type: "string"
230730
- },
230731
- case_sensitive: {
230732
- description: "Optional: Whether the search should be case-sensitive. Defaults to false.",
230733
- type: "boolean"
230734
- },
230735
- respect_git_ignore: {
230736
- description: "Optional: Whether to respect .gitignore patterns when finding files. Only available in git repositories. Defaults to true.",
230737
- type: "boolean"
230738
- },
230739
- respect_qwen_ignore: {
230740
- description: "Optional: Whether to respect .qwenignore patterns when finding files. Defaults to true.",
230741
- type: "boolean"
230742
230743
  }
230743
230744
  },
230744
230745
  required: ["pattern"],
@@ -230750,26 +230751,16 @@ ${fileListDescription}`;
230750
230751
  * Validates the parameters for the tool.
230751
230752
  */
230752
230753
  validateToolParamValues(params) {
230753
- const searchDirAbsolute = path35.resolve(this.config.getTargetDir(), params.path || ".");
230754
- const workspaceContext = this.config.getWorkspaceContext();
230755
- if (!workspaceContext.isPathWithinWorkspace(searchDirAbsolute)) {
230756
- const directories = workspaceContext.getDirectories();
230757
- return `Search path ("${searchDirAbsolute}") resolves outside the allowed workspace directories: ${directories.join(", ")}`;
230758
- }
230759
- const targetDir = searchDirAbsolute || this.config.getTargetDir();
230760
- try {
230761
- if (!fs32.existsSync(targetDir)) {
230762
- return `Search path does not exist ${targetDir}`;
230763
- }
230764
- if (!fs32.statSync(targetDir).isDirectory()) {
230765
- return `Search path is not a directory: ${targetDir}`;
230766
- }
230767
- } catch (e2) {
230768
- return `Error accessing search path: ${e2}`;
230769
- }
230770
230754
  if (!params.pattern || typeof params.pattern !== "string" || params.pattern.trim() === "") {
230771
230755
  return "The 'pattern' parameter cannot be empty.";
230772
230756
  }
230757
+ if (params.path) {
230758
+ try {
230759
+ resolveAndValidatePath(this.config, params.path);
230760
+ } catch (error) {
230761
+ return getErrorMessage(error);
230762
+ }
230763
+ }
230773
230764
  return null;
230774
230765
  }
230775
230766
  createInvocation(params) {
@@ -230780,12 +230771,11 @@ ${fileListDescription}`;
230780
230771
  });
230781
230772
 
230782
230773
  // packages/core/dist/src/tools/grep.js
230783
- import fs33 from "node:fs";
230784
230774
  import fsPromises2 from "node:fs/promises";
230785
230775
  import path36 from "node:path";
230786
230776
  import { EOL as EOL2 } from "node:os";
230787
230777
  import { spawn as spawn5 } from "node:child_process";
230788
- var GrepToolInvocation, GrepTool;
230778
+ var MAX_LLM_CONTENT_LENGTH, GrepToolInvocation, GrepTool;
230789
230779
  var init_grep2 = __esm({
230790
230780
  "packages/core/dist/src/tools/grep.js"() {
230791
230781
  "use strict";
@@ -230797,6 +230787,7 @@ var init_grep2 = __esm({
230797
230787
  init_errors();
230798
230788
  init_gitUtils();
230799
230789
  init_tool_error();
230790
+ MAX_LLM_CONTENT_LENGTH = 2e4;
230800
230791
  GrepToolInvocation = class extends BaseToolInvocation {
230801
230792
  static {
230802
230793
  __name(this, "GrepToolInvocation");
@@ -230808,89 +230799,34 @@ var init_grep2 = __esm({
230808
230799
  this.config = config;
230809
230800
  this.fileExclusions = config.getFileExclusions();
230810
230801
  }
230811
- /**
230812
- * Checks if a path is within the root directory and resolves it.
230813
- * @param relativePath Path relative to the root directory (or undefined for root).
230814
- * @returns The absolute path if valid and exists, or null if no path specified (to search all directories).
230815
- * @throws {Error} If path is outside root, doesn't exist, or isn't a directory.
230816
- */
230817
- resolveAndValidatePath(relativePath) {
230818
- if (!relativePath) {
230819
- return null;
230820
- }
230821
- const targetPath = path36.resolve(this.config.getTargetDir(), relativePath);
230822
- const workspaceContext = this.config.getWorkspaceContext();
230823
- if (!workspaceContext.isPathWithinWorkspace(targetPath)) {
230824
- const directories = workspaceContext.getDirectories();
230825
- throw new Error(`Path validation failed: Attempted path "${relativePath}" resolves outside the allowed workspace directories: ${directories.join(", ")}`);
230826
- }
230827
- try {
230828
- const stats = fs33.statSync(targetPath);
230829
- if (!stats.isDirectory()) {
230830
- throw new Error(`Path is not a directory: ${targetPath}`);
230831
- }
230832
- } catch (error) {
230833
- if (isNodeError(error) && error.code !== "ENOENT") {
230834
- throw new Error(`Path does not exist: ${targetPath}`);
230835
- }
230836
- throw new Error(`Failed to access path stats for ${targetPath}: ${error}`);
230837
- }
230838
- return targetPath;
230839
- }
230840
230802
  async execute(signal) {
230841
230803
  try {
230842
- const workspaceContext = this.config.getWorkspaceContext();
230843
- const searchDirAbs = this.resolveAndValidatePath(this.params.path);
230804
+ const searchDirAbs = resolveAndValidatePath(this.config, this.params.path);
230844
230805
  const searchDirDisplay = this.params.path || ".";
230845
- let searchDirectories;
230846
- if (searchDirAbs === null) {
230847
- searchDirectories = workspaceContext.getDirectories();
230848
- } else {
230849
- searchDirectories = [searchDirAbs];
230850
- }
230851
- let allMatches = [];
230852
- const maxResults = this.params.maxResults ?? 20;
230853
- let totalMatchesFound = 0;
230854
- let searchTruncated = false;
230855
- for (const searchDir of searchDirectories) {
230856
- const matches = await this.performGrepSearch({
230857
- pattern: this.params.pattern,
230858
- path: searchDir,
230859
- include: this.params.include,
230860
- signal
230861
- });
230862
- totalMatchesFound += matches.length;
230863
- if (searchDirectories.length > 1) {
230864
- const dirName = path36.basename(searchDir);
230865
- matches.forEach((match2) => {
230866
- match2.filePath = path36.join(dirName, match2.filePath);
230867
- });
230868
- }
230869
- const remainingSlots = maxResults - allMatches.length;
230870
- if (remainingSlots <= 0) {
230871
- searchTruncated = true;
230872
- break;
230873
- }
230874
- if (matches.length > remainingSlots) {
230875
- allMatches = allMatches.concat(matches.slice(0, remainingSlots));
230876
- searchTruncated = true;
230877
- break;
230878
- } else {
230879
- allMatches = allMatches.concat(matches);
230880
- }
230881
- }
230882
- let searchLocationDescription;
230883
- if (searchDirAbs === null) {
230884
- const numDirs = workspaceContext.getDirectories().length;
230885
- searchLocationDescription = numDirs > 1 ? `across ${numDirs} workspace directories` : `in the workspace directory`;
230886
- } else {
230887
- searchLocationDescription = `in path "${searchDirDisplay}"`;
230888
- }
230889
- if (allMatches.length === 0) {
230890
- const noMatchMsg = `No matches found for pattern "${this.params.pattern}" ${searchLocationDescription}${this.params.include ? ` (filter: "${this.params.include}")` : ""}.`;
230806
+ const rawMatches = await this.performGrepSearch({
230807
+ pattern: this.params.pattern,
230808
+ path: searchDirAbs,
230809
+ glob: this.params.glob,
230810
+ signal
230811
+ });
230812
+ const searchLocationDescription = this.params.path ? `in path "${searchDirDisplay}"` : `in the workspace directory`;
230813
+ const filterDescription = this.params.glob ? ` (filter: "${this.params.glob}")` : "";
230814
+ if (rawMatches.length === 0) {
230815
+ const noMatchMsg = `No matches found for pattern "${this.params.pattern}" ${searchLocationDescription}${filterDescription}.`;
230891
230816
  return { llmContent: noMatchMsg, returnDisplay: `No matches found` };
230892
230817
  }
230893
- const matchesByFile = allMatches.reduce((acc, match2) => {
230818
+ let truncatedByLineLimit = false;
230819
+ let matchesToInclude = rawMatches;
230820
+ if (this.params.limit !== void 0 && rawMatches.length > this.params.limit) {
230821
+ matchesToInclude = rawMatches.slice(0, this.params.limit);
230822
+ truncatedByLineLimit = true;
230823
+ }
230824
+ const totalMatches = rawMatches.length;
230825
+ const matchTerm = totalMatches === 1 ? "match" : "matches";
230826
+ const header = `Found ${totalMatches} ${matchTerm} for pattern "${this.params.pattern}" ${searchLocationDescription}${filterDescription}:
230827
+ ---
230828
+ `;
230829
+ const matchesByFile = matchesToInclude.reduce((acc, match2) => {
230894
230830
  const fileKey = match2.filePath;
230895
230831
  if (!acc[fileKey]) {
230896
230832
  acc[fileKey] = [];
@@ -230899,40 +230835,36 @@ var init_grep2 = __esm({
230899
230835
  acc[fileKey].sort((a, b) => a.lineNumber - b.lineNumber);
230900
230836
  return acc;
230901
230837
  }, {});
230902
- const matchCount = allMatches.length;
230903
- const matchTerm = matchCount === 1 ? "match" : "matches";
230904
- let headerText = `Found ${matchCount} ${matchTerm} for pattern "${this.params.pattern}" ${searchLocationDescription}${this.params.include ? ` (filter: "${this.params.include}")` : ""}`;
230905
- if (searchTruncated) {
230906
- headerText += ` (showing first ${matchCount} of ${totalMatchesFound}+ total matches)`;
230907
- }
230908
- let llmContent = `${headerText}:
230909
- ---
230910
- `;
230838
+ let grepOutput = "";
230911
230839
  for (const filePath in matchesByFile) {
230912
- llmContent += `File: ${filePath}
230840
+ grepOutput += `File: ${filePath}
230913
230841
  `;
230914
230842
  matchesByFile[filePath].forEach((match2) => {
230915
230843
  const trimmedLine = match2.line.trim();
230916
- llmContent += `L${match2.lineNumber}: ${trimmedLine}
230844
+ grepOutput += `L${match2.lineNumber}: ${trimmedLine}
230917
230845
  `;
230918
230846
  });
230919
- llmContent += "---\n";
230847
+ grepOutput += "---\n";
230920
230848
  }
230921
- if (searchTruncated) {
230922
- llmContent += `
230923
- WARNING: Results truncated to prevent context overflow. To see more results:
230924
- - Use a more specific pattern to reduce matches
230925
- - Add file filters with the 'include' parameter (e.g., "*.js", "src/**")
230926
- - Specify a narrower 'path' to search in a subdirectory
230927
- - Increase 'maxResults' parameter if you need more matches (current: ${maxResults})`;
230849
+ let truncatedByCharLimit = false;
230850
+ if (grepOutput.length > MAX_LLM_CONTENT_LENGTH) {
230851
+ grepOutput = grepOutput.slice(0, MAX_LLM_CONTENT_LENGTH) + "...";
230852
+ truncatedByCharLimit = true;
230853
+ }
230854
+ const finalLines = grepOutput.split("\n").filter((line) => line.trim() && !line.startsWith("File:") && !line.startsWith("---"));
230855
+ const includedLines = finalLines.length;
230856
+ let llmContent = header + grepOutput;
230857
+ if (truncatedByLineLimit || truncatedByCharLimit) {
230858
+ const omittedMatches = totalMatches - includedLines;
230859
+ llmContent += ` [${omittedMatches} ${omittedMatches === 1 ? "line" : "lines"} truncated] ...`;
230928
230860
  }
230929
- let displayText = `Found ${matchCount} ${matchTerm}`;
230930
- if (searchTruncated) {
230931
- displayText += ` (truncated from ${totalMatchesFound}+)`;
230861
+ let displayMessage = `Found ${totalMatches} ${matchTerm}`;
230862
+ if (truncatedByLineLimit || truncatedByCharLimit) {
230863
+ displayMessage += ` (truncated)`;
230932
230864
  }
230933
230865
  return {
230934
230866
  llmContent: llmContent.trim(),
230935
- returnDisplay: displayText
230867
+ returnDisplay: displayMessage
230936
230868
  };
230937
230869
  } catch (error) {
230938
230870
  console.error(`Error during GrepLogic execution: ${error}`);
@@ -231011,34 +230943,19 @@ WARNING: Results truncated to prevent context overflow. To see more results:
231011
230943
  * @returns A string describing the grep
231012
230944
  */
231013
230945
  getDescription() {
231014
- let description = `'${this.params.pattern}'`;
231015
- if (this.params.include) {
231016
- description += ` in ${this.params.include}`;
231017
- }
231018
- if (this.params.path) {
231019
- const resolvedPath = path36.resolve(this.config.getTargetDir(), this.params.path);
231020
- if (resolvedPath === this.config.getTargetDir() || this.params.path === ".") {
231021
- description += ` within ./`;
231022
- } else {
231023
- const relativePath = makeRelative(resolvedPath, this.config.getTargetDir());
231024
- description += ` within ${shortenPath(relativePath)}`;
231025
- }
231026
- } else {
231027
- const workspaceContext = this.config.getWorkspaceContext();
231028
- const directories = workspaceContext.getDirectories();
231029
- if (directories.length > 1) {
231030
- description += ` across all workspace directories`;
231031
- }
230946
+ let description = `'${this.params.pattern}' in path '${this.params.path || "./"}'`;
230947
+ if (this.params.glob) {
230948
+ description += ` (filter: '${this.params.glob}')`;
231032
230949
  }
231033
230950
  return description;
231034
230951
  }
231035
230952
  /**
231036
230953
  * Performs the actual search using the prioritized strategies.
231037
- * @param options Search options including pattern, absolute path, and include glob.
230954
+ * @param options Search options including pattern, absolute path, and glob filter.
231038
230955
  * @returns A promise resolving to an array of match objects.
231039
230956
  */
231040
230957
  async performGrepSearch(options2) {
231041
- const { pattern, path: absolutePath, include } = options2;
230958
+ const { pattern, path: absolutePath, glob: glob2 } = options2;
231042
230959
  let strategyUsed = "none";
231043
230960
  try {
231044
230961
  const isGit = isGitRepository(absolutePath);
@@ -231053,8 +230970,8 @@ WARNING: Results truncated to prevent context overflow. To see more results:
231053
230970
  "--ignore-case",
231054
230971
  pattern
231055
230972
  ];
231056
- if (include) {
231057
- gitArgs.push("--", include);
230973
+ if (glob2) {
230974
+ gitArgs.push("--", glob2);
231058
230975
  }
231059
230976
  try {
231060
230977
  const output = await new Promise((resolve24, reject) => {
@@ -231104,8 +231021,8 @@ WARNING: Results truncated to prevent context overflow. To see more results:
231104
231021
  return null;
231105
231022
  }).filter((dir) => !!dir);
231106
231023
  commonExcludes.forEach((dir) => grepArgs.push(`--exclude-dir=${dir}`));
231107
- if (include) {
231108
- grepArgs.push(`--include=${include}`);
231024
+ if (glob2) {
231025
+ grepArgs.push(`--include=${glob2}`);
231109
231026
  }
231110
231027
  grepArgs.push(pattern);
231111
231028
  grepArgs.push(".");
@@ -231164,7 +231081,7 @@ WARNING: Results truncated to prevent context overflow. To see more results:
231164
231081
  }
231165
231082
  console.debug("GrepLogic: Falling back to JavaScript grep implementation.");
231166
231083
  strategyUsed = "javascript fallback";
231167
- const globPattern = include ? include : "**/*";
231084
+ const globPattern = glob2 ? glob2 : "**/*";
231168
231085
  const ignorePatterns = this.fileExclusions.getGlobExcludes();
231169
231086
  const filesIterator = globStream(globPattern, {
231170
231087
  cwd: absolutePath,
@@ -231210,25 +231127,23 @@ WARNING: Results truncated to prevent context overflow. To see more results:
231210
231127
  config;
231211
231128
  static Name = ToolNames.GREP;
231212
231129
  constructor(config) {
231213
- super(_GrepTool.Name, "SearchText", "Searches for a regular expression pattern within the content of files in a specified directory (or current working directory). Can filter files by a glob pattern. Returns the lines containing matches, along with their file paths and line numbers.", Kind.Search, {
231130
+ super(_GrepTool.Name, "Grep", 'A powerful search tool for finding patterns in files\n\n Usage:\n - ALWAYS use Grep for search tasks. NEVER invoke `grep` or `rg` as a Bash command. The Grep tool has been optimized for correct permissions and access.\n - Supports full regex syntax (e.g., "log.*Error", "function\\s+\\w+")\n - Filter files with glob parameter (e.g., "*.js", "**/*.tsx")\n - Case-insensitive by default\n - Use Task tool for open-ended searches requiring multiple rounds\n', Kind.Search, {
231214
231131
  properties: {
231215
231132
  pattern: {
231216
- description: "The regular expression (regex) pattern to search for within file contents (e.g., 'function\\s+myFunction', 'import\\s+\\{.*\\}\\s+from\\s+.*').",
231217
- type: "string"
231133
+ type: "string",
231134
+ description: "The regular expression pattern to search for in file contents"
231218
231135
  },
231219
- path: {
231220
- description: "Optional: The absolute path to the directory to search within. If omitted, searches the current working directory.",
231221
- type: "string"
231136
+ glob: {
231137
+ type: "string",
231138
+ description: 'Glob pattern to filter files (e.g. "*.js", "*.{ts,tsx}")'
231222
231139
  },
231223
- include: {
231224
- description: "Optional: A glob pattern to filter which files are searched (e.g., '*.js', '*.{ts,tsx}', 'src/**'). If omitted, searches all files (respecting potential global ignores).",
231225
- type: "string"
231140
+ path: {
231141
+ type: "string",
231142
+ description: "File or directory to search in. Defaults to current working directory."
231226
231143
  },
231227
- maxResults: {
231228
- description: "Optional: Maximum number of matches to return to prevent context overflow (default: 20, max: 100). Use lower values for broad searches, higher for specific searches.",
231144
+ limit: {
231229
231145
  type: "number",
231230
- minimum: 1,
231231
- maximum: 100
231146
+ description: "Limit output to first N matching lines. Optional - shows all matches if not specified."
231232
231147
  }
231233
231148
  },
231234
231149
  required: ["pattern"],
@@ -231236,35 +231151,6 @@ WARNING: Results truncated to prevent context overflow. To see more results:
231236
231151
  });
231237
231152
  this.config = config;
231238
231153
  }
231239
- /**
231240
- * Checks if a path is within the root directory and resolves it.
231241
- * @param relativePath Path relative to the root directory (or undefined for root).
231242
- * @returns The absolute path if valid and exists, or null if no path specified (to search all directories).
231243
- * @throws {Error} If path is outside root, doesn't exist, or isn't a directory.
231244
- */
231245
- resolveAndValidatePath(relativePath) {
231246
- if (!relativePath) {
231247
- return null;
231248
- }
231249
- const targetPath = path36.resolve(this.config.getTargetDir(), relativePath);
231250
- const workspaceContext = this.config.getWorkspaceContext();
231251
- if (!workspaceContext.isPathWithinWorkspace(targetPath)) {
231252
- const directories = workspaceContext.getDirectories();
231253
- throw new Error(`Path validation failed: Attempted path "${relativePath}" resolves outside the allowed workspace directories: ${directories.join(", ")}`);
231254
- }
231255
- try {
231256
- const stats = fs33.statSync(targetPath);
231257
- if (!stats.isDirectory()) {
231258
- throw new Error(`Path is not a directory: ${targetPath}`);
231259
- }
231260
- } catch (error) {
231261
- if (isNodeError(error) && error.code !== "ENOENT") {
231262
- throw new Error(`Path does not exist: ${targetPath}`);
231263
- }
231264
- throw new Error(`Failed to access path stats for ${targetPath}: ${error}`);
231265
- }
231266
- return targetPath;
231267
- }
231268
231154
  /**
231269
231155
  * Validates the parameters for the tool
231270
231156
  * @param params Parameters to validate
@@ -231274,16 +231160,11 @@ WARNING: Results truncated to prevent context overflow. To see more results:
231274
231160
  try {
231275
231161
  new RegExp(params.pattern);
231276
231162
  } catch (error) {
231277
- return `Invalid regular expression pattern provided: ${params.pattern}. Error: ${getErrorMessage(error)}`;
231278
- }
231279
- if (params.maxResults !== void 0) {
231280
- if (!Number.isInteger(params.maxResults) || params.maxResults < 1 || params.maxResults > 100) {
231281
- return `maxResults must be an integer between 1 and 100, got: ${params.maxResults}`;
231282
- }
231163
+ return `Invalid regular expression pattern: ${params.pattern}. Error: ${getErrorMessage(error)}`;
231283
231164
  }
231284
231165
  if (params.path) {
231285
231166
  try {
231286
- this.resolveAndValidatePath(params.path);
231167
+ resolveAndValidatePath(this.config, params.path);
231287
231168
  } catch (error) {
231288
231169
  return getErrorMessage(error);
231289
231170
  }
@@ -231944,7 +231825,7 @@ import fs36 from "node:fs";
231944
231825
  import path40 from "node:path";
231945
231826
  import { EOL as EOL3 } from "node:os";
231946
231827
  import { spawn as spawn6 } from "node:child_process";
231947
- var MAX_LLM_CONTENT_LENGTH, GrepToolInvocation2, RipGrepTool;
231828
+ var MAX_LLM_CONTENT_LENGTH2, GrepToolInvocation2, RipGrepTool;
231948
231829
  var init_ripGrep = __esm({
231949
231830
  "packages/core/dist/src/tools/ripGrep.js"() {
231950
231831
  "use strict";
@@ -231956,7 +231837,7 @@ var init_ripGrep = __esm({
231956
231837
  init_ripgrepUtils();
231957
231838
  init_schemaValidator();
231958
231839
  init_constants3();
231959
- MAX_LLM_CONTENT_LENGTH = 2e4;
231840
+ MAX_LLM_CONTENT_LENGTH2 = 2e4;
231960
231841
  GrepToolInvocation2 = class extends BaseToolInvocation {
231961
231842
  static {
231962
231843
  __name(this, "GrepToolInvocation");
@@ -231966,39 +231847,9 @@ var init_ripGrep = __esm({
231966
231847
  super(params);
231967
231848
  this.config = config;
231968
231849
  }
231969
- /**
231970
- * Checks if a path is within the root directory and resolves it.
231971
- * @param relativePath Path relative to the root directory (or undefined for root).
231972
- * @returns The absolute path to search within.
231973
- * @throws {Error} If path is outside root, doesn't exist, or isn't a directory.
231974
- */
231975
- resolveAndValidatePath(relativePath) {
231976
- const targetDir = this.config.getTargetDir();
231977
- const targetPath = relativePath ? path40.resolve(targetDir, relativePath) : targetDir;
231978
- const workspaceContext = this.config.getWorkspaceContext();
231979
- if (!workspaceContext.isPathWithinWorkspace(targetPath)) {
231980
- const directories = workspaceContext.getDirectories();
231981
- throw new Error(`Path validation failed: Attempted path "${relativePath}" resolves outside the allowed workspace directories: ${directories.join(", ")}`);
231982
- }
231983
- return this.ensureDirectory(targetPath);
231984
- }
231985
- ensureDirectory(targetPath) {
231986
- try {
231987
- const stats = fs36.statSync(targetPath);
231988
- if (!stats.isDirectory()) {
231989
- throw new Error(`Path is not a directory: ${targetPath}`);
231990
- }
231991
- } catch (error) {
231992
- if (isNodeError(error) && error.code !== "ENOENT") {
231993
- throw new Error(`Path does not exist: ${targetPath}`);
231994
- }
231995
- throw new Error(`Failed to access path stats for ${targetPath}: ${error}`);
231996
- }
231997
- return targetPath;
231998
- }
231999
231850
  async execute(signal) {
232000
231851
  try {
232001
- const searchDirAbs = this.resolveAndValidatePath(this.params.path);
231852
+ const searchDirAbs = resolveAndValidatePath(this.config, this.params.path, { allowFiles: true });
232002
231853
  const searchDirDisplay = this.params.path || ".";
232003
231854
  const rawOutput = await this.performRipgrepSearch({
232004
231855
  pattern: this.params.pattern,
@@ -232018,26 +231869,36 @@ var init_ripGrep = __esm({
232018
231869
  const header = `Found ${totalMatches} ${matchTerm} for pattern "${this.params.pattern}" ${searchLocationDescription}${filterDescription}:
232019
231870
  ---
232020
231871
  `;
232021
- const maxTruncationNoticeLength = 100;
232022
- const maxGrepOutputLength = MAX_LLM_CONTENT_LENGTH - header.length - maxTruncationNoticeLength;
232023
231872
  let truncatedByLineLimit = false;
232024
231873
  let linesToInclude = allLines;
232025
231874
  if (this.params.limit !== void 0 && allLines.length > this.params.limit) {
232026
231875
  linesToInclude = allLines.slice(0, this.params.limit);
232027
231876
  truncatedByLineLimit = true;
232028
231877
  }
232029
- let grepOutput = linesToInclude.join(EOL3);
231878
+ const parts = [];
231879
+ let includedLines = 0;
232030
231880
  let truncatedByCharLimit = false;
232031
- if (grepOutput.length > maxGrepOutputLength) {
232032
- grepOutput = grepOutput.slice(0, maxGrepOutputLength) + "...";
232033
- truncatedByCharLimit = true;
231881
+ let currentLength = 0;
231882
+ for (const line of linesToInclude) {
231883
+ const sep7 = includedLines > 0 ? 1 : 0;
231884
+ includedLines++;
231885
+ if (currentLength + line.length <= MAX_LLM_CONTENT_LENGTH2) {
231886
+ parts.push(line);
231887
+ currentLength = currentLength + line.length + sep7;
231888
+ } else {
231889
+ const remaining = Math.max(MAX_LLM_CONTENT_LENGTH2 - currentLength - sep7, 10);
231890
+ parts.push(line.slice(0, remaining) + "...");
231891
+ truncatedByCharLimit = true;
231892
+ break;
231893
+ }
232034
231894
  }
232035
- const finalLines = grepOutput.split(EOL3).filter((line) => line.trim());
232036
- const includedLines = finalLines.length;
231895
+ const grepOutput = parts.join("\n");
232037
231896
  let llmContent = header + grepOutput;
232038
231897
  if (truncatedByLineLimit || truncatedByCharLimit) {
232039
231898
  const omittedMatches = totalMatches - includedLines;
232040
- llmContent += ` [${omittedMatches} ${omittedMatches === 1 ? "line" : "lines"} truncated] ...`;
231899
+ llmContent += `
231900
+ ---
231901
+ [${omittedMatches} ${omittedMatches === 1 ? "line" : "lines"} truncated] ...`;
232041
231902
  }
232042
231903
  let displayMessage = `Found ${totalMatches} ${matchTerm}`;
232043
231904
  if (truncatedByLineLimit || truncatedByCharLimit) {
@@ -232133,23 +231994,11 @@ var init_ripGrep = __esm({
232133
231994
  */
232134
231995
  getDescription() {
232135
231996
  let description = `'${this.params.pattern}'`;
232136
- if (this.params.glob) {
232137
- description += ` in ${this.params.glob}`;
232138
- }
232139
231997
  if (this.params.path) {
232140
- const resolvedPath = path40.resolve(this.config.getTargetDir(), this.params.path);
232141
- if (resolvedPath === this.config.getTargetDir() || this.params.path === ".") {
232142
- description += ` within ./`;
232143
- } else {
232144
- const relativePath = makeRelative(resolvedPath, this.config.getTargetDir());
232145
- description += ` within ${shortenPath(relativePath)}`;
232146
- }
232147
- } else {
232148
- const workspaceContext = this.config.getWorkspaceContext();
232149
- const directories = workspaceContext.getDirectories();
232150
- if (directories.length > 1) {
232151
- description += ` across all workspace directories`;
232152
- }
231998
+ description += ` in path '${this.params.path}'`;
231999
+ }
232000
+ if (this.params.glob) {
232001
+ description += ` (filter: '${this.params.glob}')`;
232153
232002
  }
232154
232003
  return description;
232155
232004
  }
@@ -232185,35 +232034,6 @@ var init_ripGrep = __esm({
232185
232034
  });
232186
232035
  this.config = config;
232187
232036
  }
232188
- /**
232189
- * Checks if a path is within the root directory and resolves it.
232190
- * @param relativePath Path relative to the root directory (or undefined for root).
232191
- * @returns The absolute path to search within.
232192
- * @throws {Error} If path is outside root, doesn't exist, or isn't a directory.
232193
- */
232194
- resolveAndValidatePath(relativePath) {
232195
- if (!relativePath) {
232196
- return this.config.getTargetDir();
232197
- }
232198
- const targetPath = path40.resolve(this.config.getTargetDir(), relativePath);
232199
- const workspaceContext = this.config.getWorkspaceContext();
232200
- if (!workspaceContext.isPathWithinWorkspace(targetPath)) {
232201
- const directories = workspaceContext.getDirectories();
232202
- throw new Error(`Path validation failed: Attempted path "${relativePath}" resolves outside the allowed workspace directories: ${directories.join(", ")}`);
232203
- }
232204
- try {
232205
- const stats = fs36.statSync(targetPath);
232206
- if (!stats.isDirectory()) {
232207
- throw new Error(`Path is not a directory: ${targetPath}`);
232208
- }
232209
- } catch (error) {
232210
- if (isNodeError(error) && error.code !== "ENOENT") {
232211
- throw new Error(`Path does not exist: ${targetPath}`);
232212
- }
232213
- throw new Error(`Failed to access path stats for ${targetPath}: ${error}`);
232214
- }
232215
- return targetPath;
232216
- }
232217
232037
  /**
232218
232038
  * Validates the parameters for the tool
232219
232039
  * @param params Parameters to validate
@@ -232231,7 +232051,7 @@ var init_ripGrep = __esm({
232231
232051
  }
232232
232052
  if (params.path) {
232233
232053
  try {
232234
- this.resolveAndValidatePath(params.path);
232054
+ resolveAndValidatePath(this.config, params.path, { allowFiles: true });
232235
232055
  } catch (error) {
232236
232056
  return getErrorMessage(error);
232237
232057
  }
@@ -316649,7 +316469,7 @@ init_esbuild_shims();
316649
316469
 
316650
316470
  // packages/cli/src/generated/git-commit.ts
316651
316471
  init_esbuild_shims();
316652
- var GIT_COMMIT_INFO2 = "553a3630";
316472
+ var GIT_COMMIT_INFO2 = "bc3a1686";
316653
316473
 
316654
316474
  // packages/cli/src/ui/components/AboutBox.tsx
316655
316475
  var import_jsx_runtime43 = __toESM(require_jsx_runtime(), 1);
@@ -338496,7 +338316,7 @@ import { homedir as homedir16 } from "node:os";
338496
338316
  init_esbuild_shims();
338497
338317
  import * as os26 from "node:os";
338498
338318
  import * as path76 from "node:path";
338499
- function resolvePath(p) {
338319
+ function resolvePath2(p) {
338500
338320
  if (!p) {
338501
338321
  return "";
338502
338322
  }
@@ -338508,7 +338328,7 @@ function resolvePath(p) {
338508
338328
  }
338509
338329
  return path76.normalize(expandedPath);
338510
338330
  }
338511
- __name(resolvePath, "resolvePath");
338331
+ __name(resolvePath2, "resolvePath");
338512
338332
 
338513
338333
  // packages/cli/src/utils/version.ts
338514
338334
  init_esbuild_shims();
@@ -338744,7 +338564,7 @@ __name(getPackageJson, "getPackageJson");
338744
338564
  // packages/cli/src/utils/version.ts
338745
338565
  async function getCliVersion() {
338746
338566
  const pkgJson = await getPackageJson();
338747
- return "0.1.4";
338567
+ return "0.1.5-nightly.20251107.d17c37af";
338748
338568
  }
338749
338569
  __name(getCliVersion, "getCliVersion");
338750
338570
 
@@ -339541,7 +339361,7 @@ async function loadCliConfig(settings, extensions, extensionEnablementManager, s
339541
339361
  ...DEFAULT_MEMORY_FILE_FILTERING_OPTIONS,
339542
339362
  ...settings.context?.fileFiltering
339543
339363
  };
339544
- const includeDirectories = (settings.context?.includeDirectories || []).map(resolvePath).concat((argv.includeDirectories || []).map(resolvePath));
339364
+ const includeDirectories = (settings.context?.includeDirectories || []).map(resolvePath2).concat((argv.includeDirectories || []).map(resolvePath2));
339545
339365
  const { memoryContent, fileCount } = await loadHierarchicalGeminiMemory(
339546
339366
  cwd7,
339547
339367
  settings.context?.loadMemoryFromIncludeDirectories ? includeDirectories : [],