@qwen-code/qwen-code 0.1.2-nightly.20251031.ced79cf4 → 0.1.3-nightly.20251101.ff8a8ac6
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.
- package/cli.js +678 -581
- package/package.json +2 -2
package/cli.js
CHANGED
|
@@ -182628,7 +182628,7 @@ function createContentGeneratorConfig(config, authType, generationConfig) {
|
|
|
182628
182628
|
};
|
|
182629
182629
|
}
|
|
182630
182630
|
async function createContentGenerator(config, gcConfig, sessionId2) {
|
|
182631
|
-
const version2 = "0.1.
|
|
182631
|
+
const version2 = "0.1.3-nightly.20251101.ff8a8ac6";
|
|
182632
182632
|
const userAgent2 = `QwenCode/${version2} (${process.platform}; ${process.arch})`;
|
|
182633
182633
|
const baseHeaders = {
|
|
182634
182634
|
"User-Agent": userAgent2
|
|
@@ -184427,7 +184427,7 @@ var init_tool_names = __esm({
|
|
|
184427
184427
|
WRITE_FILE: "write_file",
|
|
184428
184428
|
READ_FILE: "read_file",
|
|
184429
184429
|
READ_MANY_FILES: "read_many_files",
|
|
184430
|
-
GREP: "
|
|
184430
|
+
GREP: "grep_search",
|
|
184431
184431
|
GLOB: "glob",
|
|
184432
184432
|
SHELL: "run_shell_command",
|
|
184433
184433
|
TODO_WRITE: "todo_write",
|
|
@@ -198829,7 +198829,8 @@ var init_turn = __esm({
|
|
|
198829
198829
|
CompressionStatus2[CompressionStatus2["COMPRESSED"] = 1] = "COMPRESSED";
|
|
198830
198830
|
CompressionStatus2[CompressionStatus2["COMPRESSION_FAILED_INFLATED_TOKEN_COUNT"] = 2] = "COMPRESSION_FAILED_INFLATED_TOKEN_COUNT";
|
|
198831
198831
|
CompressionStatus2[CompressionStatus2["COMPRESSION_FAILED_TOKEN_COUNT_ERROR"] = 3] = "COMPRESSION_FAILED_TOKEN_COUNT_ERROR";
|
|
198832
|
-
CompressionStatus2[CompressionStatus2["
|
|
198832
|
+
CompressionStatus2[CompressionStatus2["COMPRESSION_FAILED_EMPTY_SUMMARY"] = 4] = "COMPRESSION_FAILED_EMPTY_SUMMARY";
|
|
198833
|
+
CompressionStatus2[CompressionStatus2["NOOP"] = 5] = "NOOP";
|
|
198833
198834
|
})(CompressionStatus || (CompressionStatus = {}));
|
|
198834
198835
|
Turn = class {
|
|
198835
198836
|
static {
|
|
@@ -198961,6 +198962,474 @@ ${[...this.pendingCitations].sort().join("\n")}`
|
|
|
198961
198962
|
}
|
|
198962
198963
|
});
|
|
198963
198964
|
|
|
198965
|
+
// packages/core/dist/src/config/constants.js
|
|
198966
|
+
var DEFAULT_MEMORY_FILE_FILTERING_OPTIONS, DEFAULT_FILE_FILTERING_OPTIONS;
|
|
198967
|
+
var init_constants3 = __esm({
|
|
198968
|
+
"packages/core/dist/src/config/constants.js"() {
|
|
198969
|
+
"use strict";
|
|
198970
|
+
init_esbuild_shims();
|
|
198971
|
+
DEFAULT_MEMORY_FILE_FILTERING_OPTIONS = {
|
|
198972
|
+
respectGitIgnore: false,
|
|
198973
|
+
respectQwenIgnore: true
|
|
198974
|
+
};
|
|
198975
|
+
DEFAULT_FILE_FILTERING_OPTIONS = {
|
|
198976
|
+
respectGitIgnore: true,
|
|
198977
|
+
respectQwenIgnore: true
|
|
198978
|
+
};
|
|
198979
|
+
}
|
|
198980
|
+
});
|
|
198981
|
+
|
|
198982
|
+
// packages/core/dist/src/utils/getFolderStructure.js
|
|
198983
|
+
import * as fs24 from "node:fs/promises";
|
|
198984
|
+
import * as path21 from "node:path";
|
|
198985
|
+
async function readFullStructure(rootPath, options2) {
|
|
198986
|
+
const rootName = path21.basename(rootPath);
|
|
198987
|
+
const rootNode = {
|
|
198988
|
+
name: rootName,
|
|
198989
|
+
path: rootPath,
|
|
198990
|
+
files: [],
|
|
198991
|
+
subFolders: [],
|
|
198992
|
+
totalChildren: 0,
|
|
198993
|
+
totalFiles: 0
|
|
198994
|
+
};
|
|
198995
|
+
const queue = [
|
|
198996
|
+
{ folderInfo: rootNode, currentPath: rootPath }
|
|
198997
|
+
];
|
|
198998
|
+
let currentItemCount = 0;
|
|
198999
|
+
const processedPaths = /* @__PURE__ */ new Set();
|
|
199000
|
+
while (queue.length > 0) {
|
|
199001
|
+
const { folderInfo, currentPath } = queue.shift();
|
|
199002
|
+
if (processedPaths.has(currentPath)) {
|
|
199003
|
+
continue;
|
|
199004
|
+
}
|
|
199005
|
+
processedPaths.add(currentPath);
|
|
199006
|
+
if (currentItemCount >= options2.maxItems) {
|
|
199007
|
+
continue;
|
|
199008
|
+
}
|
|
199009
|
+
let entries;
|
|
199010
|
+
try {
|
|
199011
|
+
const rawEntries = await fs24.readdir(currentPath, { withFileTypes: true });
|
|
199012
|
+
entries = rawEntries.sort((a, b) => a.name.localeCompare(b.name));
|
|
199013
|
+
} catch (error) {
|
|
199014
|
+
if (isNodeError(error) && (error.code === "EACCES" || error.code === "ENOENT")) {
|
|
199015
|
+
console.warn(`Warning: Could not read directory ${currentPath}: ${error.message}`);
|
|
199016
|
+
if (currentPath === rootPath && error.code === "ENOENT") {
|
|
199017
|
+
return null;
|
|
199018
|
+
}
|
|
199019
|
+
continue;
|
|
199020
|
+
}
|
|
199021
|
+
throw error;
|
|
199022
|
+
}
|
|
199023
|
+
const filesInCurrentDir = [];
|
|
199024
|
+
const subFoldersInCurrentDir = [];
|
|
199025
|
+
for (const entry of entries) {
|
|
199026
|
+
if (entry.isFile()) {
|
|
199027
|
+
if (currentItemCount >= options2.maxItems) {
|
|
199028
|
+
folderInfo.hasMoreFiles = true;
|
|
199029
|
+
break;
|
|
199030
|
+
}
|
|
199031
|
+
const fileName = entry.name;
|
|
199032
|
+
const filePath = path21.join(currentPath, fileName);
|
|
199033
|
+
if (options2.fileService) {
|
|
199034
|
+
const shouldIgnore = options2.fileFilteringOptions.respectGitIgnore && options2.fileService.shouldGitIgnoreFile(filePath) || options2.fileFilteringOptions.respectQwenIgnore && options2.fileService.shouldQwenIgnoreFile(filePath);
|
|
199035
|
+
if (shouldIgnore) {
|
|
199036
|
+
continue;
|
|
199037
|
+
}
|
|
199038
|
+
}
|
|
199039
|
+
if (!options2.fileIncludePattern || options2.fileIncludePattern.test(fileName)) {
|
|
199040
|
+
filesInCurrentDir.push(fileName);
|
|
199041
|
+
currentItemCount++;
|
|
199042
|
+
folderInfo.totalFiles++;
|
|
199043
|
+
folderInfo.totalChildren++;
|
|
199044
|
+
}
|
|
199045
|
+
}
|
|
199046
|
+
}
|
|
199047
|
+
folderInfo.files = filesInCurrentDir;
|
|
199048
|
+
for (const entry of entries) {
|
|
199049
|
+
if (entry.isDirectory()) {
|
|
199050
|
+
if (currentItemCount >= options2.maxItems) {
|
|
199051
|
+
folderInfo.hasMoreSubfolders = true;
|
|
199052
|
+
break;
|
|
199053
|
+
}
|
|
199054
|
+
const subFolderName = entry.name;
|
|
199055
|
+
const subFolderPath = path21.join(currentPath, subFolderName);
|
|
199056
|
+
let isIgnored = false;
|
|
199057
|
+
if (options2.fileService) {
|
|
199058
|
+
isIgnored = options2.fileFilteringOptions.respectGitIgnore && options2.fileService.shouldGitIgnoreFile(subFolderPath) || options2.fileFilteringOptions.respectQwenIgnore && options2.fileService.shouldQwenIgnoreFile(subFolderPath);
|
|
199059
|
+
}
|
|
199060
|
+
if (options2.ignoredFolders.has(subFolderName) || isIgnored) {
|
|
199061
|
+
const ignoredSubFolder = {
|
|
199062
|
+
name: subFolderName,
|
|
199063
|
+
path: subFolderPath,
|
|
199064
|
+
files: [],
|
|
199065
|
+
subFolders: [],
|
|
199066
|
+
totalChildren: 0,
|
|
199067
|
+
totalFiles: 0,
|
|
199068
|
+
isIgnored: true
|
|
199069
|
+
};
|
|
199070
|
+
subFoldersInCurrentDir.push(ignoredSubFolder);
|
|
199071
|
+
currentItemCount++;
|
|
199072
|
+
folderInfo.totalChildren++;
|
|
199073
|
+
continue;
|
|
199074
|
+
}
|
|
199075
|
+
const subFolderNode = {
|
|
199076
|
+
name: subFolderName,
|
|
199077
|
+
path: subFolderPath,
|
|
199078
|
+
files: [],
|
|
199079
|
+
subFolders: [],
|
|
199080
|
+
totalChildren: 0,
|
|
199081
|
+
totalFiles: 0
|
|
199082
|
+
};
|
|
199083
|
+
subFoldersInCurrentDir.push(subFolderNode);
|
|
199084
|
+
currentItemCount++;
|
|
199085
|
+
folderInfo.totalChildren++;
|
|
199086
|
+
queue.push({ folderInfo: subFolderNode, currentPath: subFolderPath });
|
|
199087
|
+
}
|
|
199088
|
+
}
|
|
199089
|
+
folderInfo.subFolders = subFoldersInCurrentDir;
|
|
199090
|
+
}
|
|
199091
|
+
return rootNode;
|
|
199092
|
+
}
|
|
199093
|
+
function formatStructure(node, currentIndent, isLastChildOfParent, isProcessingRootNode, builder) {
|
|
199094
|
+
const connector = isLastChildOfParent ? "\u2514\u2500\u2500\u2500" : "\u251C\u2500\u2500\u2500";
|
|
199095
|
+
if (!isProcessingRootNode || node.isIgnored) {
|
|
199096
|
+
builder.push(`${currentIndent}${connector}${node.name}${path21.sep}${node.isIgnored ? TRUNCATION_INDICATOR : ""}`);
|
|
199097
|
+
}
|
|
199098
|
+
const indentForChildren = isProcessingRootNode ? "" : currentIndent + (isLastChildOfParent ? " " : "\u2502 ");
|
|
199099
|
+
const fileCount = node.files.length;
|
|
199100
|
+
for (let i = 0; i < fileCount; i++) {
|
|
199101
|
+
const isLastFileAmongSiblings = i === fileCount - 1 && node.subFolders.length === 0 && !node.hasMoreSubfolders;
|
|
199102
|
+
const fileConnector = isLastFileAmongSiblings ? "\u2514\u2500\u2500\u2500" : "\u251C\u2500\u2500\u2500";
|
|
199103
|
+
builder.push(`${indentForChildren}${fileConnector}${node.files[i]}`);
|
|
199104
|
+
}
|
|
199105
|
+
if (node.hasMoreFiles) {
|
|
199106
|
+
const isLastIndicatorAmongSiblings = node.subFolders.length === 0 && !node.hasMoreSubfolders;
|
|
199107
|
+
const fileConnector = isLastIndicatorAmongSiblings ? "\u2514\u2500\u2500\u2500" : "\u251C\u2500\u2500\u2500";
|
|
199108
|
+
builder.push(`${indentForChildren}${fileConnector}${TRUNCATION_INDICATOR}`);
|
|
199109
|
+
}
|
|
199110
|
+
const subFolderCount = node.subFolders.length;
|
|
199111
|
+
for (let i = 0; i < subFolderCount; i++) {
|
|
199112
|
+
const isLastSubfolderAmongSiblings = i === subFolderCount - 1 && !node.hasMoreSubfolders;
|
|
199113
|
+
formatStructure(node.subFolders[i], indentForChildren, isLastSubfolderAmongSiblings, false, builder);
|
|
199114
|
+
}
|
|
199115
|
+
if (node.hasMoreSubfolders) {
|
|
199116
|
+
builder.push(`${indentForChildren}\u2514\u2500\u2500\u2500${TRUNCATION_INDICATOR}`);
|
|
199117
|
+
}
|
|
199118
|
+
}
|
|
199119
|
+
async function getFolderStructure(directory, options2) {
|
|
199120
|
+
const resolvedPath = path21.resolve(directory);
|
|
199121
|
+
const mergedOptions = {
|
|
199122
|
+
maxItems: options2?.maxItems ?? MAX_ITEMS,
|
|
199123
|
+
ignoredFolders: options2?.ignoredFolders ?? DEFAULT_IGNORED_FOLDERS,
|
|
199124
|
+
fileIncludePattern: options2?.fileIncludePattern,
|
|
199125
|
+
fileService: options2?.fileService,
|
|
199126
|
+
fileFilteringOptions: options2?.fileFilteringOptions ?? DEFAULT_FILE_FILTERING_OPTIONS
|
|
199127
|
+
};
|
|
199128
|
+
try {
|
|
199129
|
+
let isTruncated2 = function(node) {
|
|
199130
|
+
if (node.hasMoreFiles || node.hasMoreSubfolders || node.isIgnored) {
|
|
199131
|
+
return true;
|
|
199132
|
+
}
|
|
199133
|
+
for (const sub of node.subFolders) {
|
|
199134
|
+
if (isTruncated2(sub)) {
|
|
199135
|
+
return true;
|
|
199136
|
+
}
|
|
199137
|
+
}
|
|
199138
|
+
return false;
|
|
199139
|
+
};
|
|
199140
|
+
var isTruncated = isTruncated2;
|
|
199141
|
+
__name(isTruncated2, "isTruncated");
|
|
199142
|
+
const structureRoot = await readFullStructure(resolvedPath, mergedOptions);
|
|
199143
|
+
if (!structureRoot) {
|
|
199144
|
+
return `Error: Could not read directory "${resolvedPath}". Check path and permissions.`;
|
|
199145
|
+
}
|
|
199146
|
+
const structureLines = [];
|
|
199147
|
+
formatStructure(structureRoot, "", true, true, structureLines);
|
|
199148
|
+
let summary = `Showing up to ${mergedOptions.maxItems} items (files + folders).`;
|
|
199149
|
+
if (isTruncated2(structureRoot)) {
|
|
199150
|
+
summary += ` Folders or files indicated with ${TRUNCATION_INDICATOR} contain more items not shown, were ignored, or the display limit (${mergedOptions.maxItems} items) was reached.`;
|
|
199151
|
+
}
|
|
199152
|
+
return `${summary}
|
|
199153
|
+
|
|
199154
|
+
${resolvedPath}${path21.sep}
|
|
199155
|
+
${structureLines.join("\n")}`;
|
|
199156
|
+
} catch (error) {
|
|
199157
|
+
console.error(`Error getting folder structure for ${resolvedPath}:`, error);
|
|
199158
|
+
return `Error processing directory "${resolvedPath}": ${getErrorMessage(error)}`;
|
|
199159
|
+
}
|
|
199160
|
+
}
|
|
199161
|
+
var MAX_ITEMS, TRUNCATION_INDICATOR, DEFAULT_IGNORED_FOLDERS;
|
|
199162
|
+
var init_getFolderStructure = __esm({
|
|
199163
|
+
"packages/core/dist/src/utils/getFolderStructure.js"() {
|
|
199164
|
+
"use strict";
|
|
199165
|
+
init_esbuild_shims();
|
|
199166
|
+
init_errors();
|
|
199167
|
+
init_constants3();
|
|
199168
|
+
MAX_ITEMS = 20;
|
|
199169
|
+
TRUNCATION_INDICATOR = "...";
|
|
199170
|
+
DEFAULT_IGNORED_FOLDERS = /* @__PURE__ */ new Set(["node_modules", ".git", "dist"]);
|
|
199171
|
+
__name(readFullStructure, "readFullStructure");
|
|
199172
|
+
__name(formatStructure, "formatStructure");
|
|
199173
|
+
__name(getFolderStructure, "getFolderStructure");
|
|
199174
|
+
}
|
|
199175
|
+
});
|
|
199176
|
+
|
|
199177
|
+
// packages/core/dist/src/utils/environmentContext.js
|
|
199178
|
+
async function getDirectoryContextString(config) {
|
|
199179
|
+
const workspaceContext = config.getWorkspaceContext();
|
|
199180
|
+
const workspaceDirectories = workspaceContext.getDirectories();
|
|
199181
|
+
const folderStructures = await Promise.all(workspaceDirectories.map((dir) => getFolderStructure(dir, {
|
|
199182
|
+
fileService: config.getFileService()
|
|
199183
|
+
})));
|
|
199184
|
+
const folderStructure = folderStructures.join("\n");
|
|
199185
|
+
let workingDirPreamble;
|
|
199186
|
+
if (workspaceDirectories.length === 1) {
|
|
199187
|
+
workingDirPreamble = `I'm currently working in the directory: ${workspaceDirectories[0]}`;
|
|
199188
|
+
} else {
|
|
199189
|
+
const dirList = workspaceDirectories.map((dir) => ` - ${dir}`).join("\n");
|
|
199190
|
+
workingDirPreamble = `I'm currently working in the following directories:
|
|
199191
|
+
${dirList}`;
|
|
199192
|
+
}
|
|
199193
|
+
return `${workingDirPreamble}
|
|
199194
|
+
Here is the folder structure of the current working directories:
|
|
199195
|
+
|
|
199196
|
+
${folderStructure}`;
|
|
199197
|
+
}
|
|
199198
|
+
async function getEnvironmentContext(config) {
|
|
199199
|
+
const today = (/* @__PURE__ */ new Date()).toLocaleDateString(void 0, {
|
|
199200
|
+
weekday: "long",
|
|
199201
|
+
year: "numeric",
|
|
199202
|
+
month: "long",
|
|
199203
|
+
day: "numeric"
|
|
199204
|
+
});
|
|
199205
|
+
const platform14 = process.platform;
|
|
199206
|
+
const directoryContext = await getDirectoryContextString(config);
|
|
199207
|
+
const context2 = `
|
|
199208
|
+
This is the Qwen Code. We are setting up the context for our chat.
|
|
199209
|
+
Today's date is ${today} (formatted according to the user's locale).
|
|
199210
|
+
My operating system is: ${platform14}
|
|
199211
|
+
${directoryContext}
|
|
199212
|
+
`.trim();
|
|
199213
|
+
const initialParts = [{ text: context2 }];
|
|
199214
|
+
const toolRegistry = config.getToolRegistry();
|
|
199215
|
+
if (config.getFullContext()) {
|
|
199216
|
+
try {
|
|
199217
|
+
const readManyFilesTool = toolRegistry.getTool("read_many_files");
|
|
199218
|
+
if (readManyFilesTool) {
|
|
199219
|
+
const invocation = readManyFilesTool.build({
|
|
199220
|
+
paths: ["**/*"],
|
|
199221
|
+
// Read everything recursively
|
|
199222
|
+
useDefaultExcludes: true
|
|
199223
|
+
// Use default excludes
|
|
199224
|
+
});
|
|
199225
|
+
const result = await invocation.execute(AbortSignal.timeout(3e4));
|
|
199226
|
+
if (result.llmContent) {
|
|
199227
|
+
initialParts.push({
|
|
199228
|
+
text: `
|
|
199229
|
+
--- Full File Context ---
|
|
199230
|
+
${result.llmContent}`
|
|
199231
|
+
});
|
|
199232
|
+
} else {
|
|
199233
|
+
console.warn("Full context requested, but read_many_files returned no content.");
|
|
199234
|
+
}
|
|
199235
|
+
} else {
|
|
199236
|
+
console.warn("Full context requested, but read_many_files tool not found.");
|
|
199237
|
+
}
|
|
199238
|
+
} catch (error) {
|
|
199239
|
+
console.error("Error reading full file context:", error);
|
|
199240
|
+
initialParts.push({
|
|
199241
|
+
text: "\n--- Error reading full file context ---"
|
|
199242
|
+
});
|
|
199243
|
+
}
|
|
199244
|
+
}
|
|
199245
|
+
return initialParts;
|
|
199246
|
+
}
|
|
199247
|
+
async function getInitialChatHistory(config, extraHistory) {
|
|
199248
|
+
const envParts = await getEnvironmentContext(config);
|
|
199249
|
+
const envContextString = envParts.map((part) => part.text || "").join("\n\n");
|
|
199250
|
+
return [
|
|
199251
|
+
{
|
|
199252
|
+
role: "user",
|
|
199253
|
+
parts: [{ text: envContextString }]
|
|
199254
|
+
},
|
|
199255
|
+
{
|
|
199256
|
+
role: "model",
|
|
199257
|
+
parts: [{ text: "Got it. Thanks for the context!" }]
|
|
199258
|
+
},
|
|
199259
|
+
...extraHistory ?? []
|
|
199260
|
+
];
|
|
199261
|
+
}
|
|
199262
|
+
var init_environmentContext = __esm({
|
|
199263
|
+
"packages/core/dist/src/utils/environmentContext.js"() {
|
|
199264
|
+
"use strict";
|
|
199265
|
+
init_esbuild_shims();
|
|
199266
|
+
init_getFolderStructure();
|
|
199267
|
+
__name(getDirectoryContextString, "getDirectoryContextString");
|
|
199268
|
+
__name(getEnvironmentContext, "getEnvironmentContext");
|
|
199269
|
+
__name(getInitialChatHistory, "getInitialChatHistory");
|
|
199270
|
+
}
|
|
199271
|
+
});
|
|
199272
|
+
|
|
199273
|
+
// packages/core/dist/src/services/chatCompressionService.js
|
|
199274
|
+
function findCompressSplitPoint(contents, fraction) {
|
|
199275
|
+
if (fraction <= 0 || fraction >= 1) {
|
|
199276
|
+
throw new Error("Fraction must be between 0 and 1");
|
|
199277
|
+
}
|
|
199278
|
+
const charCounts = contents.map((content) => JSON.stringify(content).length);
|
|
199279
|
+
const totalCharCount = charCounts.reduce((a, b) => a + b, 0);
|
|
199280
|
+
const targetCharCount = totalCharCount * fraction;
|
|
199281
|
+
let lastSplitPoint = 0;
|
|
199282
|
+
let cumulativeCharCount = 0;
|
|
199283
|
+
for (let i = 0; i < contents.length; i++) {
|
|
199284
|
+
const content = contents[i];
|
|
199285
|
+
if (content.role === "user" && !content.parts?.some((part) => !!part.functionResponse)) {
|
|
199286
|
+
if (cumulativeCharCount >= targetCharCount) {
|
|
199287
|
+
return i;
|
|
199288
|
+
}
|
|
199289
|
+
lastSplitPoint = i;
|
|
199290
|
+
}
|
|
199291
|
+
cumulativeCharCount += charCounts[i];
|
|
199292
|
+
}
|
|
199293
|
+
const lastContent = contents[contents.length - 1];
|
|
199294
|
+
if (lastContent?.role === "model" && !lastContent?.parts?.some((part) => part.functionCall)) {
|
|
199295
|
+
return contents.length;
|
|
199296
|
+
}
|
|
199297
|
+
return lastSplitPoint;
|
|
199298
|
+
}
|
|
199299
|
+
var COMPRESSION_TOKEN_THRESHOLD, COMPRESSION_PRESERVE_THRESHOLD, ChatCompressionService;
|
|
199300
|
+
var init_chatCompressionService = __esm({
|
|
199301
|
+
"packages/core/dist/src/services/chatCompressionService.js"() {
|
|
199302
|
+
"use strict";
|
|
199303
|
+
init_esbuild_shims();
|
|
199304
|
+
init_turn();
|
|
199305
|
+
init_uiTelemetry();
|
|
199306
|
+
init_tokenLimits();
|
|
199307
|
+
init_prompts();
|
|
199308
|
+
init_partUtils();
|
|
199309
|
+
init_loggers();
|
|
199310
|
+
init_types3();
|
|
199311
|
+
init_environmentContext();
|
|
199312
|
+
COMPRESSION_TOKEN_THRESHOLD = 0.7;
|
|
199313
|
+
COMPRESSION_PRESERVE_THRESHOLD = 0.3;
|
|
199314
|
+
__name(findCompressSplitPoint, "findCompressSplitPoint");
|
|
199315
|
+
ChatCompressionService = class {
|
|
199316
|
+
static {
|
|
199317
|
+
__name(this, "ChatCompressionService");
|
|
199318
|
+
}
|
|
199319
|
+
async compress(chat, promptId, force, model, config, hasFailedCompressionAttempt) {
|
|
199320
|
+
const curatedHistory = chat.getHistory(true);
|
|
199321
|
+
if (curatedHistory.length === 0 || hasFailedCompressionAttempt && !force) {
|
|
199322
|
+
return {
|
|
199323
|
+
newHistory: null,
|
|
199324
|
+
info: {
|
|
199325
|
+
originalTokenCount: 0,
|
|
199326
|
+
newTokenCount: 0,
|
|
199327
|
+
compressionStatus: CompressionStatus.NOOP
|
|
199328
|
+
}
|
|
199329
|
+
};
|
|
199330
|
+
}
|
|
199331
|
+
const originalTokenCount = uiTelemetryService.getLastPromptTokenCount();
|
|
199332
|
+
const contextPercentageThreshold = config.getChatCompression()?.contextPercentageThreshold;
|
|
199333
|
+
if (!force) {
|
|
199334
|
+
const threshold = contextPercentageThreshold ?? COMPRESSION_TOKEN_THRESHOLD;
|
|
199335
|
+
if (originalTokenCount < threshold * tokenLimit(model)) {
|
|
199336
|
+
return {
|
|
199337
|
+
newHistory: null,
|
|
199338
|
+
info: {
|
|
199339
|
+
originalTokenCount,
|
|
199340
|
+
newTokenCount: originalTokenCount,
|
|
199341
|
+
compressionStatus: CompressionStatus.NOOP
|
|
199342
|
+
}
|
|
199343
|
+
};
|
|
199344
|
+
}
|
|
199345
|
+
}
|
|
199346
|
+
const splitPoint = findCompressSplitPoint(curatedHistory, 1 - COMPRESSION_PRESERVE_THRESHOLD);
|
|
199347
|
+
const historyToCompress = curatedHistory.slice(0, splitPoint);
|
|
199348
|
+
const historyToKeep = curatedHistory.slice(splitPoint);
|
|
199349
|
+
if (historyToCompress.length === 0) {
|
|
199350
|
+
return {
|
|
199351
|
+
newHistory: null,
|
|
199352
|
+
info: {
|
|
199353
|
+
originalTokenCount,
|
|
199354
|
+
newTokenCount: originalTokenCount,
|
|
199355
|
+
compressionStatus: CompressionStatus.NOOP
|
|
199356
|
+
}
|
|
199357
|
+
};
|
|
199358
|
+
}
|
|
199359
|
+
const summaryResponse = await config.getContentGenerator().generateContent({
|
|
199360
|
+
model,
|
|
199361
|
+
contents: [
|
|
199362
|
+
...historyToCompress,
|
|
199363
|
+
{
|
|
199364
|
+
role: "user",
|
|
199365
|
+
parts: [
|
|
199366
|
+
{
|
|
199367
|
+
text: "First, reason in your scratchpad. Then, generate the <state_snapshot>."
|
|
199368
|
+
}
|
|
199369
|
+
]
|
|
199370
|
+
}
|
|
199371
|
+
],
|
|
199372
|
+
config: {
|
|
199373
|
+
systemInstruction: getCompressionPrompt()
|
|
199374
|
+
}
|
|
199375
|
+
}, promptId);
|
|
199376
|
+
const summary = getResponseText(summaryResponse) ?? "";
|
|
199377
|
+
const isSummaryEmpty = !summary || summary.trim().length === 0;
|
|
199378
|
+
let newTokenCount = originalTokenCount;
|
|
199379
|
+
let extraHistory = [];
|
|
199380
|
+
if (!isSummaryEmpty) {
|
|
199381
|
+
extraHistory = [
|
|
199382
|
+
{
|
|
199383
|
+
role: "user",
|
|
199384
|
+
parts: [{ text: summary }]
|
|
199385
|
+
},
|
|
199386
|
+
{
|
|
199387
|
+
role: "model",
|
|
199388
|
+
parts: [{ text: "Got it. Thanks for the additional context!" }]
|
|
199389
|
+
},
|
|
199390
|
+
...historyToKeep
|
|
199391
|
+
];
|
|
199392
|
+
const fullNewHistory = await getInitialChatHistory(config, extraHistory);
|
|
199393
|
+
newTokenCount = Math.floor(fullNewHistory.reduce((total, content) => total + JSON.stringify(content).length, 0) / 4);
|
|
199394
|
+
}
|
|
199395
|
+
logChatCompression(config, makeChatCompressionEvent({
|
|
199396
|
+
tokens_before: originalTokenCount,
|
|
199397
|
+
tokens_after: newTokenCount
|
|
199398
|
+
}));
|
|
199399
|
+
if (isSummaryEmpty) {
|
|
199400
|
+
return {
|
|
199401
|
+
newHistory: null,
|
|
199402
|
+
info: {
|
|
199403
|
+
originalTokenCount,
|
|
199404
|
+
newTokenCount: originalTokenCount,
|
|
199405
|
+
compressionStatus: CompressionStatus.COMPRESSION_FAILED_EMPTY_SUMMARY
|
|
199406
|
+
}
|
|
199407
|
+
};
|
|
199408
|
+
} else if (newTokenCount > originalTokenCount) {
|
|
199409
|
+
return {
|
|
199410
|
+
newHistory: null,
|
|
199411
|
+
info: {
|
|
199412
|
+
originalTokenCount,
|
|
199413
|
+
newTokenCount,
|
|
199414
|
+
compressionStatus: CompressionStatus.COMPRESSION_FAILED_INFLATED_TOKEN_COUNT
|
|
199415
|
+
}
|
|
199416
|
+
};
|
|
199417
|
+
} else {
|
|
199418
|
+
uiTelemetryService.setLastPromptTokenCount(newTokenCount);
|
|
199419
|
+
return {
|
|
199420
|
+
newHistory: extraHistory,
|
|
199421
|
+
info: {
|
|
199422
|
+
originalTokenCount,
|
|
199423
|
+
newTokenCount,
|
|
199424
|
+
compressionStatus: CompressionStatus.COMPRESSED
|
|
199425
|
+
}
|
|
199426
|
+
};
|
|
199427
|
+
}
|
|
199428
|
+
}
|
|
199429
|
+
};
|
|
199430
|
+
}
|
|
199431
|
+
});
|
|
199432
|
+
|
|
198964
199433
|
// packages/core/dist/src/services/loopDetectionService.js
|
|
198965
199434
|
import { createHash as createHash3 } from "node:crypto";
|
|
198966
199435
|
var TOOL_CALL_LOOP_THRESHOLD, CONTENT_LOOP_THRESHOLD, CONTENT_CHUNK_SIZE, MAX_HISTORY_LENGTH, LLM_LOOP_CHECK_HISTORY_COUNT, LLM_CHECK_AFTER_TURNS, DEFAULT_LLM_CHECK_INTERVAL, MIN_LLM_CHECK_INTERVAL, MAX_LLM_CHECK_INTERVAL, LOOP_DETECTION_SYSTEM_PROMPT, LoopDetectionService;
|
|
@@ -199322,298 +199791,6 @@ var init_types6 = __esm({
|
|
|
199322
199791
|
}
|
|
199323
199792
|
});
|
|
199324
199793
|
|
|
199325
|
-
// packages/core/dist/src/config/constants.js
|
|
199326
|
-
var DEFAULT_MEMORY_FILE_FILTERING_OPTIONS, DEFAULT_FILE_FILTERING_OPTIONS;
|
|
199327
|
-
var init_constants3 = __esm({
|
|
199328
|
-
"packages/core/dist/src/config/constants.js"() {
|
|
199329
|
-
"use strict";
|
|
199330
|
-
init_esbuild_shims();
|
|
199331
|
-
DEFAULT_MEMORY_FILE_FILTERING_OPTIONS = {
|
|
199332
|
-
respectGitIgnore: false,
|
|
199333
|
-
respectQwenIgnore: true
|
|
199334
|
-
};
|
|
199335
|
-
DEFAULT_FILE_FILTERING_OPTIONS = {
|
|
199336
|
-
respectGitIgnore: true,
|
|
199337
|
-
respectQwenIgnore: true
|
|
199338
|
-
};
|
|
199339
|
-
}
|
|
199340
|
-
});
|
|
199341
|
-
|
|
199342
|
-
// packages/core/dist/src/utils/getFolderStructure.js
|
|
199343
|
-
import * as fs24 from "node:fs/promises";
|
|
199344
|
-
import * as path21 from "node:path";
|
|
199345
|
-
async function readFullStructure(rootPath, options2) {
|
|
199346
|
-
const rootName = path21.basename(rootPath);
|
|
199347
|
-
const rootNode = {
|
|
199348
|
-
name: rootName,
|
|
199349
|
-
path: rootPath,
|
|
199350
|
-
files: [],
|
|
199351
|
-
subFolders: [],
|
|
199352
|
-
totalChildren: 0,
|
|
199353
|
-
totalFiles: 0
|
|
199354
|
-
};
|
|
199355
|
-
const queue = [
|
|
199356
|
-
{ folderInfo: rootNode, currentPath: rootPath }
|
|
199357
|
-
];
|
|
199358
|
-
let currentItemCount = 0;
|
|
199359
|
-
const processedPaths = /* @__PURE__ */ new Set();
|
|
199360
|
-
while (queue.length > 0) {
|
|
199361
|
-
const { folderInfo, currentPath } = queue.shift();
|
|
199362
|
-
if (processedPaths.has(currentPath)) {
|
|
199363
|
-
continue;
|
|
199364
|
-
}
|
|
199365
|
-
processedPaths.add(currentPath);
|
|
199366
|
-
if (currentItemCount >= options2.maxItems) {
|
|
199367
|
-
continue;
|
|
199368
|
-
}
|
|
199369
|
-
let entries;
|
|
199370
|
-
try {
|
|
199371
|
-
const rawEntries = await fs24.readdir(currentPath, { withFileTypes: true });
|
|
199372
|
-
entries = rawEntries.sort((a, b) => a.name.localeCompare(b.name));
|
|
199373
|
-
} catch (error) {
|
|
199374
|
-
if (isNodeError(error) && (error.code === "EACCES" || error.code === "ENOENT")) {
|
|
199375
|
-
console.warn(`Warning: Could not read directory ${currentPath}: ${error.message}`);
|
|
199376
|
-
if (currentPath === rootPath && error.code === "ENOENT") {
|
|
199377
|
-
return null;
|
|
199378
|
-
}
|
|
199379
|
-
continue;
|
|
199380
|
-
}
|
|
199381
|
-
throw error;
|
|
199382
|
-
}
|
|
199383
|
-
const filesInCurrentDir = [];
|
|
199384
|
-
const subFoldersInCurrentDir = [];
|
|
199385
|
-
for (const entry of entries) {
|
|
199386
|
-
if (entry.isFile()) {
|
|
199387
|
-
if (currentItemCount >= options2.maxItems) {
|
|
199388
|
-
folderInfo.hasMoreFiles = true;
|
|
199389
|
-
break;
|
|
199390
|
-
}
|
|
199391
|
-
const fileName = entry.name;
|
|
199392
|
-
const filePath = path21.join(currentPath, fileName);
|
|
199393
|
-
if (options2.fileService) {
|
|
199394
|
-
const shouldIgnore = options2.fileFilteringOptions.respectGitIgnore && options2.fileService.shouldGitIgnoreFile(filePath) || options2.fileFilteringOptions.respectQwenIgnore && options2.fileService.shouldQwenIgnoreFile(filePath);
|
|
199395
|
-
if (shouldIgnore) {
|
|
199396
|
-
continue;
|
|
199397
|
-
}
|
|
199398
|
-
}
|
|
199399
|
-
if (!options2.fileIncludePattern || options2.fileIncludePattern.test(fileName)) {
|
|
199400
|
-
filesInCurrentDir.push(fileName);
|
|
199401
|
-
currentItemCount++;
|
|
199402
|
-
folderInfo.totalFiles++;
|
|
199403
|
-
folderInfo.totalChildren++;
|
|
199404
|
-
}
|
|
199405
|
-
}
|
|
199406
|
-
}
|
|
199407
|
-
folderInfo.files = filesInCurrentDir;
|
|
199408
|
-
for (const entry of entries) {
|
|
199409
|
-
if (entry.isDirectory()) {
|
|
199410
|
-
if (currentItemCount >= options2.maxItems) {
|
|
199411
|
-
folderInfo.hasMoreSubfolders = true;
|
|
199412
|
-
break;
|
|
199413
|
-
}
|
|
199414
|
-
const subFolderName = entry.name;
|
|
199415
|
-
const subFolderPath = path21.join(currentPath, subFolderName);
|
|
199416
|
-
let isIgnored = false;
|
|
199417
|
-
if (options2.fileService) {
|
|
199418
|
-
isIgnored = options2.fileFilteringOptions.respectGitIgnore && options2.fileService.shouldGitIgnoreFile(subFolderPath) || options2.fileFilteringOptions.respectQwenIgnore && options2.fileService.shouldQwenIgnoreFile(subFolderPath);
|
|
199419
|
-
}
|
|
199420
|
-
if (options2.ignoredFolders.has(subFolderName) || isIgnored) {
|
|
199421
|
-
const ignoredSubFolder = {
|
|
199422
|
-
name: subFolderName,
|
|
199423
|
-
path: subFolderPath,
|
|
199424
|
-
files: [],
|
|
199425
|
-
subFolders: [],
|
|
199426
|
-
totalChildren: 0,
|
|
199427
|
-
totalFiles: 0,
|
|
199428
|
-
isIgnored: true
|
|
199429
|
-
};
|
|
199430
|
-
subFoldersInCurrentDir.push(ignoredSubFolder);
|
|
199431
|
-
currentItemCount++;
|
|
199432
|
-
folderInfo.totalChildren++;
|
|
199433
|
-
continue;
|
|
199434
|
-
}
|
|
199435
|
-
const subFolderNode = {
|
|
199436
|
-
name: subFolderName,
|
|
199437
|
-
path: subFolderPath,
|
|
199438
|
-
files: [],
|
|
199439
|
-
subFolders: [],
|
|
199440
|
-
totalChildren: 0,
|
|
199441
|
-
totalFiles: 0
|
|
199442
|
-
};
|
|
199443
|
-
subFoldersInCurrentDir.push(subFolderNode);
|
|
199444
|
-
currentItemCount++;
|
|
199445
|
-
folderInfo.totalChildren++;
|
|
199446
|
-
queue.push({ folderInfo: subFolderNode, currentPath: subFolderPath });
|
|
199447
|
-
}
|
|
199448
|
-
}
|
|
199449
|
-
folderInfo.subFolders = subFoldersInCurrentDir;
|
|
199450
|
-
}
|
|
199451
|
-
return rootNode;
|
|
199452
|
-
}
|
|
199453
|
-
function formatStructure(node, currentIndent, isLastChildOfParent, isProcessingRootNode, builder) {
|
|
199454
|
-
const connector = isLastChildOfParent ? "\u2514\u2500\u2500\u2500" : "\u251C\u2500\u2500\u2500";
|
|
199455
|
-
if (!isProcessingRootNode || node.isIgnored) {
|
|
199456
|
-
builder.push(`${currentIndent}${connector}${node.name}${path21.sep}${node.isIgnored ? TRUNCATION_INDICATOR : ""}`);
|
|
199457
|
-
}
|
|
199458
|
-
const indentForChildren = isProcessingRootNode ? "" : currentIndent + (isLastChildOfParent ? " " : "\u2502 ");
|
|
199459
|
-
const fileCount = node.files.length;
|
|
199460
|
-
for (let i = 0; i < fileCount; i++) {
|
|
199461
|
-
const isLastFileAmongSiblings = i === fileCount - 1 && node.subFolders.length === 0 && !node.hasMoreSubfolders;
|
|
199462
|
-
const fileConnector = isLastFileAmongSiblings ? "\u2514\u2500\u2500\u2500" : "\u251C\u2500\u2500\u2500";
|
|
199463
|
-
builder.push(`${indentForChildren}${fileConnector}${node.files[i]}`);
|
|
199464
|
-
}
|
|
199465
|
-
if (node.hasMoreFiles) {
|
|
199466
|
-
const isLastIndicatorAmongSiblings = node.subFolders.length === 0 && !node.hasMoreSubfolders;
|
|
199467
|
-
const fileConnector = isLastIndicatorAmongSiblings ? "\u2514\u2500\u2500\u2500" : "\u251C\u2500\u2500\u2500";
|
|
199468
|
-
builder.push(`${indentForChildren}${fileConnector}${TRUNCATION_INDICATOR}`);
|
|
199469
|
-
}
|
|
199470
|
-
const subFolderCount = node.subFolders.length;
|
|
199471
|
-
for (let i = 0; i < subFolderCount; i++) {
|
|
199472
|
-
const isLastSubfolderAmongSiblings = i === subFolderCount - 1 && !node.hasMoreSubfolders;
|
|
199473
|
-
formatStructure(node.subFolders[i], indentForChildren, isLastSubfolderAmongSiblings, false, builder);
|
|
199474
|
-
}
|
|
199475
|
-
if (node.hasMoreSubfolders) {
|
|
199476
|
-
builder.push(`${indentForChildren}\u2514\u2500\u2500\u2500${TRUNCATION_INDICATOR}`);
|
|
199477
|
-
}
|
|
199478
|
-
}
|
|
199479
|
-
async function getFolderStructure(directory, options2) {
|
|
199480
|
-
const resolvedPath = path21.resolve(directory);
|
|
199481
|
-
const mergedOptions = {
|
|
199482
|
-
maxItems: options2?.maxItems ?? MAX_ITEMS,
|
|
199483
|
-
ignoredFolders: options2?.ignoredFolders ?? DEFAULT_IGNORED_FOLDERS,
|
|
199484
|
-
fileIncludePattern: options2?.fileIncludePattern,
|
|
199485
|
-
fileService: options2?.fileService,
|
|
199486
|
-
fileFilteringOptions: options2?.fileFilteringOptions ?? DEFAULT_FILE_FILTERING_OPTIONS
|
|
199487
|
-
};
|
|
199488
|
-
try {
|
|
199489
|
-
let isTruncated2 = function(node) {
|
|
199490
|
-
if (node.hasMoreFiles || node.hasMoreSubfolders || node.isIgnored) {
|
|
199491
|
-
return true;
|
|
199492
|
-
}
|
|
199493
|
-
for (const sub of node.subFolders) {
|
|
199494
|
-
if (isTruncated2(sub)) {
|
|
199495
|
-
return true;
|
|
199496
|
-
}
|
|
199497
|
-
}
|
|
199498
|
-
return false;
|
|
199499
|
-
};
|
|
199500
|
-
var isTruncated = isTruncated2;
|
|
199501
|
-
__name(isTruncated2, "isTruncated");
|
|
199502
|
-
const structureRoot = await readFullStructure(resolvedPath, mergedOptions);
|
|
199503
|
-
if (!structureRoot) {
|
|
199504
|
-
return `Error: Could not read directory "${resolvedPath}". Check path and permissions.`;
|
|
199505
|
-
}
|
|
199506
|
-
const structureLines = [];
|
|
199507
|
-
formatStructure(structureRoot, "", true, true, structureLines);
|
|
199508
|
-
let summary = `Showing up to ${mergedOptions.maxItems} items (files + folders).`;
|
|
199509
|
-
if (isTruncated2(structureRoot)) {
|
|
199510
|
-
summary += ` Folders or files indicated with ${TRUNCATION_INDICATOR} contain more items not shown, were ignored, or the display limit (${mergedOptions.maxItems} items) was reached.`;
|
|
199511
|
-
}
|
|
199512
|
-
return `${summary}
|
|
199513
|
-
|
|
199514
|
-
${resolvedPath}${path21.sep}
|
|
199515
|
-
${structureLines.join("\n")}`;
|
|
199516
|
-
} catch (error) {
|
|
199517
|
-
console.error(`Error getting folder structure for ${resolvedPath}:`, error);
|
|
199518
|
-
return `Error processing directory "${resolvedPath}": ${getErrorMessage(error)}`;
|
|
199519
|
-
}
|
|
199520
|
-
}
|
|
199521
|
-
var MAX_ITEMS, TRUNCATION_INDICATOR, DEFAULT_IGNORED_FOLDERS;
|
|
199522
|
-
var init_getFolderStructure = __esm({
|
|
199523
|
-
"packages/core/dist/src/utils/getFolderStructure.js"() {
|
|
199524
|
-
"use strict";
|
|
199525
|
-
init_esbuild_shims();
|
|
199526
|
-
init_errors();
|
|
199527
|
-
init_constants3();
|
|
199528
|
-
MAX_ITEMS = 20;
|
|
199529
|
-
TRUNCATION_INDICATOR = "...";
|
|
199530
|
-
DEFAULT_IGNORED_FOLDERS = /* @__PURE__ */ new Set(["node_modules", ".git", "dist"]);
|
|
199531
|
-
__name(readFullStructure, "readFullStructure");
|
|
199532
|
-
__name(formatStructure, "formatStructure");
|
|
199533
|
-
__name(getFolderStructure, "getFolderStructure");
|
|
199534
|
-
}
|
|
199535
|
-
});
|
|
199536
|
-
|
|
199537
|
-
// packages/core/dist/src/utils/environmentContext.js
|
|
199538
|
-
async function getDirectoryContextString(config) {
|
|
199539
|
-
const workspaceContext = config.getWorkspaceContext();
|
|
199540
|
-
const workspaceDirectories = workspaceContext.getDirectories();
|
|
199541
|
-
const folderStructures = await Promise.all(workspaceDirectories.map((dir) => getFolderStructure(dir, {
|
|
199542
|
-
fileService: config.getFileService()
|
|
199543
|
-
})));
|
|
199544
|
-
const folderStructure = folderStructures.join("\n");
|
|
199545
|
-
let workingDirPreamble;
|
|
199546
|
-
if (workspaceDirectories.length === 1) {
|
|
199547
|
-
workingDirPreamble = `I'm currently working in the directory: ${workspaceDirectories[0]}`;
|
|
199548
|
-
} else {
|
|
199549
|
-
const dirList = workspaceDirectories.map((dir) => ` - ${dir}`).join("\n");
|
|
199550
|
-
workingDirPreamble = `I'm currently working in the following directories:
|
|
199551
|
-
${dirList}`;
|
|
199552
|
-
}
|
|
199553
|
-
return `${workingDirPreamble}
|
|
199554
|
-
Here is the folder structure of the current working directories:
|
|
199555
|
-
|
|
199556
|
-
${folderStructure}`;
|
|
199557
|
-
}
|
|
199558
|
-
async function getEnvironmentContext(config) {
|
|
199559
|
-
const today = (/* @__PURE__ */ new Date()).toLocaleDateString(void 0, {
|
|
199560
|
-
weekday: "long",
|
|
199561
|
-
year: "numeric",
|
|
199562
|
-
month: "long",
|
|
199563
|
-
day: "numeric"
|
|
199564
|
-
});
|
|
199565
|
-
const platform14 = process.platform;
|
|
199566
|
-
const directoryContext = await getDirectoryContextString(config);
|
|
199567
|
-
const context2 = `
|
|
199568
|
-
This is the Qwen Code. We are setting up the context for our chat.
|
|
199569
|
-
Today's date is ${today} (formatted according to the user's locale).
|
|
199570
|
-
My operating system is: ${platform14}
|
|
199571
|
-
${directoryContext}
|
|
199572
|
-
`.trim();
|
|
199573
|
-
const initialParts = [{ text: context2 }];
|
|
199574
|
-
const toolRegistry = config.getToolRegistry();
|
|
199575
|
-
if (config.getFullContext()) {
|
|
199576
|
-
try {
|
|
199577
|
-
const readManyFilesTool = toolRegistry.getTool("read_many_files");
|
|
199578
|
-
if (readManyFilesTool) {
|
|
199579
|
-
const invocation = readManyFilesTool.build({
|
|
199580
|
-
paths: ["**/*"],
|
|
199581
|
-
// Read everything recursively
|
|
199582
|
-
useDefaultExcludes: true
|
|
199583
|
-
// Use default excludes
|
|
199584
|
-
});
|
|
199585
|
-
const result = await invocation.execute(AbortSignal.timeout(3e4));
|
|
199586
|
-
if (result.llmContent) {
|
|
199587
|
-
initialParts.push({
|
|
199588
|
-
text: `
|
|
199589
|
-
--- Full File Context ---
|
|
199590
|
-
${result.llmContent}`
|
|
199591
|
-
});
|
|
199592
|
-
} else {
|
|
199593
|
-
console.warn("Full context requested, but read_many_files returned no content.");
|
|
199594
|
-
}
|
|
199595
|
-
} else {
|
|
199596
|
-
console.warn("Full context requested, but read_many_files tool not found.");
|
|
199597
|
-
}
|
|
199598
|
-
} catch (error) {
|
|
199599
|
-
console.error("Error reading full file context:", error);
|
|
199600
|
-
initialParts.push({
|
|
199601
|
-
text: "\n--- Error reading full file context ---"
|
|
199602
|
-
});
|
|
199603
|
-
}
|
|
199604
|
-
}
|
|
199605
|
-
return initialParts;
|
|
199606
|
-
}
|
|
199607
|
-
var init_environmentContext = __esm({
|
|
199608
|
-
"packages/core/dist/src/utils/environmentContext.js"() {
|
|
199609
|
-
"use strict";
|
|
199610
|
-
init_esbuild_shims();
|
|
199611
|
-
init_getFolderStructure();
|
|
199612
|
-
__name(getDirectoryContextString, "getDirectoryContextString");
|
|
199613
|
-
__name(getEnvironmentContext, "getEnvironmentContext");
|
|
199614
|
-
}
|
|
199615
|
-
});
|
|
199616
|
-
|
|
199617
199794
|
// packages/core/dist/src/subagents/subagent-events.js
|
|
199618
199795
|
import { EventEmitter as EventEmitter5 } from "events";
|
|
199619
199796
|
var SubAgentEventType, SubAgentEventEmitter;
|
|
@@ -200175,11 +200352,7 @@ var init_subagent = __esm({
|
|
|
200175
200352
|
if (this.promptConfig.systemPrompt && this.promptConfig.initialMessages) {
|
|
200176
200353
|
throw new Error("PromptConfig cannot have both `systemPrompt` and `initialMessages` defined.");
|
|
200177
200354
|
}
|
|
200178
|
-
const
|
|
200179
|
-
const envHistory = [
|
|
200180
|
-
{ role: "user", parts: envParts },
|
|
200181
|
-
{ role: "model", parts: [{ text: "Got it. Thanks for the context!" }] }
|
|
200182
|
-
];
|
|
200355
|
+
const envHistory = await getInitialChatHistory(this.runtimeContext);
|
|
200183
200356
|
const start_history = [
|
|
200184
200357
|
...envHistory,
|
|
200185
200358
|
...this.promptConfig.initialMessages ?? []
|
|
@@ -205187,32 +205360,7 @@ var init_types8 = __esm({
|
|
|
205187
205360
|
function isThinkingSupported(model) {
|
|
205188
205361
|
return model.startsWith("gemini-2.5") || model === DEFAULT_GEMINI_MODEL_AUTO;
|
|
205189
205362
|
}
|
|
205190
|
-
|
|
205191
|
-
if (fraction <= 0 || fraction >= 1) {
|
|
205192
|
-
throw new Error("Fraction must be between 0 and 1");
|
|
205193
|
-
}
|
|
205194
|
-
const charCounts = contents.map((content) => JSON.stringify(content).length);
|
|
205195
|
-
const totalCharCount = charCounts.reduce((a, b) => a + b, 0);
|
|
205196
|
-
const targetCharCount = totalCharCount * fraction;
|
|
205197
|
-
let lastSplitPoint = 0;
|
|
205198
|
-
let cumulativeCharCount = 0;
|
|
205199
|
-
for (let i = 0; i < contents.length; i++) {
|
|
205200
|
-
const content = contents[i];
|
|
205201
|
-
if (content.role === "user" && !content.parts?.some((part) => !!part.functionResponse)) {
|
|
205202
|
-
if (cumulativeCharCount >= targetCharCount) {
|
|
205203
|
-
return i;
|
|
205204
|
-
}
|
|
205205
|
-
lastSplitPoint = i;
|
|
205206
|
-
}
|
|
205207
|
-
cumulativeCharCount += charCounts[i];
|
|
205208
|
-
}
|
|
205209
|
-
const lastContent = contents[contents.length - 1];
|
|
205210
|
-
if (lastContent?.role === "model" && !lastContent?.parts?.some((part) => part.functionCall)) {
|
|
205211
|
-
return contents.length;
|
|
205212
|
-
}
|
|
205213
|
-
return lastSplitPoint;
|
|
205214
|
-
}
|
|
205215
|
-
var MAX_TURNS, COMPRESSION_TOKEN_THRESHOLD, COMPRESSION_PRESERVE_THRESHOLD, GeminiClient;
|
|
205363
|
+
var MAX_TURNS, GeminiClient;
|
|
205216
205364
|
var init_client2 = __esm({
|
|
205217
205365
|
"packages/core/dist/src/core/client.js"() {
|
|
205218
205366
|
"use strict";
|
|
@@ -205221,9 +205369,9 @@ var init_client2 = __esm({
|
|
|
205221
205369
|
init_models();
|
|
205222
205370
|
init_geminiChat();
|
|
205223
205371
|
init_prompts();
|
|
205224
|
-
init_tokenLimits();
|
|
205225
205372
|
init_turn();
|
|
205226
205373
|
init_chatRecordingService();
|
|
205374
|
+
init_chatCompressionService();
|
|
205227
205375
|
init_loopDetectionService();
|
|
205228
205376
|
init_task();
|
|
205229
205377
|
init_telemetry();
|
|
@@ -205237,10 +205385,7 @@ var init_client2 = __esm({
|
|
|
205237
205385
|
init_types8();
|
|
205238
205386
|
init_handler();
|
|
205239
205387
|
__name(isThinkingSupported, "isThinkingSupported");
|
|
205240
|
-
__name(findCompressSplitPoint, "findCompressSplitPoint");
|
|
205241
205388
|
MAX_TURNS = 100;
|
|
205242
|
-
COMPRESSION_TOKEN_THRESHOLD = 0.7;
|
|
205243
|
-
COMPRESSION_PRESERVE_THRESHOLD = 0.3;
|
|
205244
205389
|
GeminiClient = class {
|
|
205245
205390
|
static {
|
|
205246
205391
|
__name(this, "GeminiClient");
|
|
@@ -205324,21 +205469,10 @@ var init_client2 = __esm({
|
|
|
205324
205469
|
async startChat(extraHistory) {
|
|
205325
205470
|
this.forceFullIdeContext = true;
|
|
205326
205471
|
this.hasFailedCompressionAttempt = false;
|
|
205327
|
-
const envParts = await getEnvironmentContext(this.config);
|
|
205328
205472
|
const toolRegistry = this.config.getToolRegistry();
|
|
205329
205473
|
const toolDeclarations = toolRegistry.getFunctionDeclarations();
|
|
205330
205474
|
const tools = [{ functionDeclarations: toolDeclarations }];
|
|
205331
|
-
const history =
|
|
205332
|
-
{
|
|
205333
|
-
role: "user",
|
|
205334
|
-
parts: envParts
|
|
205335
|
-
},
|
|
205336
|
-
{
|
|
205337
|
-
role: "model",
|
|
205338
|
-
parts: [{ text: "Got it. Thanks for the context!" }]
|
|
205339
|
-
},
|
|
205340
|
-
...extraHistory ?? []
|
|
205341
|
-
];
|
|
205475
|
+
const history = await getInitialChatHistory(this.config, extraHistory);
|
|
205342
205476
|
try {
|
|
205343
205477
|
const userMemory = this.config.getUserMemory();
|
|
205344
205478
|
const model = this.config.getModel();
|
|
@@ -205509,12 +205643,13 @@ var init_client2 = __esm({
|
|
|
205509
205643
|
const currentHistory = this.getChat().getHistory(true);
|
|
205510
205644
|
const userMemory = this.config.getUserMemory();
|
|
205511
205645
|
const systemPrompt = getCoreSystemPrompt(userMemory, this.config.getModel());
|
|
205512
|
-
const
|
|
205646
|
+
const initialHistory = await getInitialChatHistory(this.config);
|
|
205513
205647
|
const mockRequestContent = [
|
|
205514
205648
|
{
|
|
205515
205649
|
role: "system",
|
|
205516
|
-
parts: [{ text: systemPrompt }
|
|
205650
|
+
parts: [{ text: systemPrompt }]
|
|
205517
205651
|
},
|
|
205652
|
+
...initialHistory,
|
|
205518
205653
|
...currentHistory
|
|
205519
205654
|
];
|
|
205520
205655
|
const { totalTokens: totalRequestTokens } = await this.config.getContentGenerator().countTokens({
|
|
@@ -205641,85 +205776,19 @@ var init_client2 = __esm({
|
|
|
205641
205776
|
}
|
|
205642
205777
|
}
|
|
205643
205778
|
async tryCompressChat(prompt_id, force = false) {
|
|
205644
|
-
const
|
|
205645
|
-
const
|
|
205646
|
-
if (
|
|
205647
|
-
|
|
205648
|
-
|
|
205649
|
-
|
|
205650
|
-
compressionStatus: CompressionStatus.NOOP
|
|
205651
|
-
};
|
|
205652
|
-
}
|
|
205653
|
-
const originalTokenCount = uiTelemetryService.getLastPromptTokenCount();
|
|
205654
|
-
const contextPercentageThreshold = this.config.getChatCompression()?.contextPercentageThreshold;
|
|
205655
|
-
if (!force) {
|
|
205656
|
-
const threshold = contextPercentageThreshold ?? COMPRESSION_TOKEN_THRESHOLD;
|
|
205657
|
-
if (originalTokenCount < threshold * tokenLimit(model)) {
|
|
205658
|
-
return {
|
|
205659
|
-
originalTokenCount,
|
|
205660
|
-
newTokenCount: originalTokenCount,
|
|
205661
|
-
compressionStatus: CompressionStatus.NOOP
|
|
205662
|
-
};
|
|
205779
|
+
const compressionService = new ChatCompressionService();
|
|
205780
|
+
const { newHistory, info } = await compressionService.compress(this.getChat(), prompt_id, force, this.config.getModel(), this.config, this.hasFailedCompressionAttempt);
|
|
205781
|
+
if (info.compressionStatus === CompressionStatus.COMPRESSED) {
|
|
205782
|
+
if (newHistory) {
|
|
205783
|
+
this.chat = await this.startChat(newHistory);
|
|
205784
|
+
this.forceFullIdeContext = true;
|
|
205663
205785
|
}
|
|
205664
|
-
}
|
|
205665
|
-
|
|
205666
|
-
|
|
205667
|
-
const historyToKeep = curatedHistory.slice(splitPoint);
|
|
205668
|
-
const summaryResponse = await this.config.getContentGenerator().generateContent({
|
|
205669
|
-
model,
|
|
205670
|
-
contents: [
|
|
205671
|
-
...historyToCompress,
|
|
205672
|
-
{
|
|
205673
|
-
role: "user",
|
|
205674
|
-
parts: [
|
|
205675
|
-
{
|
|
205676
|
-
text: "First, reason in your scratchpad. Then, generate the <state_snapshot>."
|
|
205677
|
-
}
|
|
205678
|
-
]
|
|
205679
|
-
}
|
|
205680
|
-
],
|
|
205681
|
-
config: {
|
|
205682
|
-
systemInstruction: { text: getCompressionPrompt() }
|
|
205786
|
+
} else if (info.compressionStatus === CompressionStatus.COMPRESSION_FAILED_INFLATED_TOKEN_COUNT || info.compressionStatus === CompressionStatus.COMPRESSION_FAILED_EMPTY_SUMMARY) {
|
|
205787
|
+
if (!force) {
|
|
205788
|
+
this.hasFailedCompressionAttempt = true;
|
|
205683
205789
|
}
|
|
205684
|
-
}, prompt_id);
|
|
205685
|
-
const summary = getResponseText(summaryResponse) ?? "";
|
|
205686
|
-
const chat = await this.startChat([
|
|
205687
|
-
{
|
|
205688
|
-
role: "user",
|
|
205689
|
-
parts: [{ text: summary }]
|
|
205690
|
-
},
|
|
205691
|
-
{
|
|
205692
|
-
role: "model",
|
|
205693
|
-
parts: [{ text: "Got it. Thanks for the additional context!" }]
|
|
205694
|
-
},
|
|
205695
|
-
...historyToKeep
|
|
205696
|
-
]);
|
|
205697
|
-
this.forceFullIdeContext = true;
|
|
205698
|
-
const newTokenCount = Math.floor(chat.getHistory().reduce((total, content) => total + JSON.stringify(content).length, 0) / 4);
|
|
205699
|
-
logChatCompression(this.config, makeChatCompressionEvent({
|
|
205700
|
-
tokens_before: originalTokenCount,
|
|
205701
|
-
tokens_after: newTokenCount
|
|
205702
|
-
}));
|
|
205703
|
-
if (newTokenCount > originalTokenCount) {
|
|
205704
|
-
this.hasFailedCompressionAttempt = !force && true;
|
|
205705
|
-
return {
|
|
205706
|
-
originalTokenCount,
|
|
205707
|
-
newTokenCount,
|
|
205708
|
-
compressionStatus: CompressionStatus.COMPRESSION_FAILED_INFLATED_TOKEN_COUNT
|
|
205709
|
-
};
|
|
205710
|
-
} else {
|
|
205711
|
-
this.chat = chat;
|
|
205712
|
-
uiTelemetryService.setLastPromptTokenCount(newTokenCount);
|
|
205713
205790
|
}
|
|
205714
|
-
|
|
205715
|
-
tokens_before: originalTokenCount,
|
|
205716
|
-
tokens_after: newTokenCount
|
|
205717
|
-
}));
|
|
205718
|
-
return {
|
|
205719
|
-
originalTokenCount,
|
|
205720
|
-
newTokenCount,
|
|
205721
|
-
compressionStatus: CompressionStatus.COMPRESSED
|
|
205722
|
-
};
|
|
205791
|
+
return info;
|
|
205723
205792
|
}
|
|
205724
205793
|
};
|
|
205725
205794
|
}
|
|
@@ -231807,10 +231876,20 @@ function getRipgrepPath() {
|
|
|
231807
231876
|
const vendorPath = isBundled ? path39.join(__dirname3, "vendor", "ripgrep", `${arch3}-${platform14}`, binaryName) : path39.join(__dirname3, "..", "..", "..", "vendor", "ripgrep", `${arch3}-${platform14}`, binaryName);
|
|
231808
231877
|
return vendorPath;
|
|
231809
231878
|
}
|
|
231810
|
-
async function canUseRipgrep() {
|
|
231879
|
+
async function canUseRipgrep(useBuiltin = true) {
|
|
231811
231880
|
try {
|
|
231812
|
-
|
|
231813
|
-
|
|
231881
|
+
if (useBuiltin) {
|
|
231882
|
+
const rgPath = getRipgrepPath();
|
|
231883
|
+
if (await fileExists(rgPath)) {
|
|
231884
|
+
return true;
|
|
231885
|
+
}
|
|
231886
|
+
}
|
|
231887
|
+
const { spawn: spawn13 } = await import("node:child_process");
|
|
231888
|
+
return await new Promise((resolve23) => {
|
|
231889
|
+
const proc2 = spawn13("rg", ["--version"]);
|
|
231890
|
+
proc2.on("error", () => resolve23(false));
|
|
231891
|
+
proc2.on("exit", (code2) => resolve23(code2 === 0));
|
|
231892
|
+
});
|
|
231814
231893
|
} catch (_error) {
|
|
231815
231894
|
return false;
|
|
231816
231895
|
}
|
|
@@ -231843,17 +231922,19 @@ import fs36 from "node:fs";
|
|
|
231843
231922
|
import path40 from "node:path";
|
|
231844
231923
|
import { EOL as EOL3 } from "node:os";
|
|
231845
231924
|
import { spawn as spawn6 } from "node:child_process";
|
|
231846
|
-
var
|
|
231925
|
+
var MAX_LLM_CONTENT_LENGTH, GrepToolInvocation2, RipGrepTool;
|
|
231847
231926
|
var init_ripGrep = __esm({
|
|
231848
231927
|
"packages/core/dist/src/tools/ripGrep.js"() {
|
|
231849
231928
|
"use strict";
|
|
231850
231929
|
init_esbuild_shims();
|
|
231851
231930
|
init_tools();
|
|
231852
|
-
|
|
231931
|
+
init_tool_names();
|
|
231853
231932
|
init_paths();
|
|
231854
231933
|
init_errors();
|
|
231855
231934
|
init_ripgrepUtils();
|
|
231856
|
-
|
|
231935
|
+
init_schemaValidator();
|
|
231936
|
+
init_constants3();
|
|
231937
|
+
MAX_LLM_CONTENT_LENGTH = 2e4;
|
|
231857
231938
|
GrepToolInvocation2 = class extends BaseToolInvocation {
|
|
231858
231939
|
static {
|
|
231859
231940
|
__name(this, "GrepToolInvocation");
|
|
@@ -231866,19 +231947,20 @@ var init_ripGrep = __esm({
|
|
|
231866
231947
|
/**
|
|
231867
231948
|
* Checks if a path is within the root directory and resolves it.
|
|
231868
231949
|
* @param relativePath Path relative to the root directory (or undefined for root).
|
|
231869
|
-
* @returns The absolute path
|
|
231950
|
+
* @returns The absolute path to search within.
|
|
231870
231951
|
* @throws {Error} If path is outside root, doesn't exist, or isn't a directory.
|
|
231871
231952
|
*/
|
|
231872
231953
|
resolveAndValidatePath(relativePath) {
|
|
231873
|
-
|
|
231874
|
-
|
|
231875
|
-
}
|
|
231876
|
-
const targetPath = path40.resolve(this.config.getTargetDir(), relativePath);
|
|
231954
|
+
const targetDir = this.config.getTargetDir();
|
|
231955
|
+
const targetPath = relativePath ? path40.resolve(targetDir, relativePath) : targetDir;
|
|
231877
231956
|
const workspaceContext = this.config.getWorkspaceContext();
|
|
231878
231957
|
if (!workspaceContext.isPathWithinWorkspace(targetPath)) {
|
|
231879
231958
|
const directories = workspaceContext.getDirectories();
|
|
231880
231959
|
throw new Error(`Path validation failed: Attempted path "${relativePath}" resolves outside the allowed workspace directories: ${directories.join(", ")}`);
|
|
231881
231960
|
}
|
|
231961
|
+
return this.ensureDirectory(targetPath);
|
|
231962
|
+
}
|
|
231963
|
+
ensureDirectory(targetPath) {
|
|
231882
231964
|
try {
|
|
231883
231965
|
const stats = fs36.statSync(targetPath);
|
|
231884
231966
|
if (!stats.isDirectory()) {
|
|
@@ -231894,82 +231976,50 @@ var init_ripGrep = __esm({
|
|
|
231894
231976
|
}
|
|
231895
231977
|
async execute(signal) {
|
|
231896
231978
|
try {
|
|
231897
|
-
const workspaceContext = this.config.getWorkspaceContext();
|
|
231898
231979
|
const searchDirAbs = this.resolveAndValidatePath(this.params.path);
|
|
231899
231980
|
const searchDirDisplay = this.params.path || ".";
|
|
231900
|
-
|
|
231901
|
-
|
|
231902
|
-
|
|
231903
|
-
|
|
231904
|
-
|
|
231905
|
-
}
|
|
231906
|
-
|
|
231907
|
-
const
|
|
231908
|
-
if (
|
|
231909
|
-
|
|
231910
|
-
}
|
|
231911
|
-
for (const searchDir of searchDirectories) {
|
|
231912
|
-
const searchResult = await this.performRipgrepSearch({
|
|
231913
|
-
pattern: this.params.pattern,
|
|
231914
|
-
path: searchDir,
|
|
231915
|
-
include: this.params.include,
|
|
231916
|
-
signal
|
|
231917
|
-
});
|
|
231918
|
-
if (searchDirectories.length > 1) {
|
|
231919
|
-
const dirName = path40.basename(searchDir);
|
|
231920
|
-
searchResult.forEach((match2) => {
|
|
231921
|
-
match2.filePath = path40.join(dirName, match2.filePath);
|
|
231922
|
-
});
|
|
231923
|
-
}
|
|
231924
|
-
allMatches = allMatches.concat(searchResult);
|
|
231925
|
-
if (allMatches.length >= totalMaxMatches) {
|
|
231926
|
-
allMatches = allMatches.slice(0, totalMaxMatches);
|
|
231927
|
-
break;
|
|
231928
|
-
}
|
|
231929
|
-
}
|
|
231930
|
-
let searchLocationDescription;
|
|
231931
|
-
if (searchDirAbs === null) {
|
|
231932
|
-
const numDirs = workspaceContext.getDirectories().length;
|
|
231933
|
-
searchLocationDescription = numDirs > 1 ? `across ${numDirs} workspace directories` : `in the workspace directory`;
|
|
231934
|
-
} else {
|
|
231935
|
-
searchLocationDescription = `in path "${searchDirDisplay}"`;
|
|
231936
|
-
}
|
|
231937
|
-
if (allMatches.length === 0) {
|
|
231938
|
-
const noMatchMsg = `No matches found for pattern "${this.params.pattern}" ${searchLocationDescription}${this.params.include ? ` (filter: "${this.params.include}")` : ""}.`;
|
|
231981
|
+
const rawOutput = await this.performRipgrepSearch({
|
|
231982
|
+
pattern: this.params.pattern,
|
|
231983
|
+
path: searchDirAbs,
|
|
231984
|
+
glob: this.params.glob,
|
|
231985
|
+
signal
|
|
231986
|
+
});
|
|
231987
|
+
const searchLocationDescription = this.params.path ? `in path "${searchDirDisplay}"` : `in the workspace directory`;
|
|
231988
|
+
const filterDescription = this.params.glob ? ` (filter: "${this.params.glob}")` : "";
|
|
231989
|
+
if (!rawOutput.trim()) {
|
|
231990
|
+
const noMatchMsg = `No matches found for pattern "${this.params.pattern}" ${searchLocationDescription}${filterDescription}.`;
|
|
231939
231991
|
return { llmContent: noMatchMsg, returnDisplay: `No matches found` };
|
|
231940
231992
|
}
|
|
231941
|
-
const
|
|
231942
|
-
const
|
|
231943
|
-
|
|
231944
|
-
|
|
231945
|
-
acc[fileKey] = [];
|
|
231946
|
-
}
|
|
231947
|
-
acc[fileKey].push(match2);
|
|
231948
|
-
acc[fileKey].sort((a, b) => a.lineNumber - b.lineNumber);
|
|
231949
|
-
return acc;
|
|
231950
|
-
}, {});
|
|
231951
|
-
const matchCount = allMatches.length;
|
|
231952
|
-
const matchTerm = matchCount === 1 ? "match" : "matches";
|
|
231953
|
-
let llmContent = `Found ${matchCount} ${matchTerm} for pattern "${this.params.pattern}" ${searchLocationDescription}${this.params.include ? ` (filter: "${this.params.include}")` : ""}`;
|
|
231954
|
-
if (wasTruncated) {
|
|
231955
|
-
llmContent += ` (results limited to ${totalMaxMatches} matches for performance)`;
|
|
231956
|
-
}
|
|
231957
|
-
llmContent += `:
|
|
231993
|
+
const allLines = rawOutput.split(EOL3).filter((line) => line.trim());
|
|
231994
|
+
const totalMatches = allLines.length;
|
|
231995
|
+
const matchTerm = totalMatches === 1 ? "match" : "matches";
|
|
231996
|
+
const header = `Found ${totalMatches} ${matchTerm} for pattern "${this.params.pattern}" ${searchLocationDescription}${filterDescription}:
|
|
231958
231997
|
---
|
|
231959
231998
|
`;
|
|
231960
|
-
|
|
231961
|
-
|
|
231962
|
-
|
|
231963
|
-
|
|
231964
|
-
|
|
231965
|
-
|
|
231966
|
-
|
|
231967
|
-
|
|
231968
|
-
|
|
231969
|
-
|
|
231970
|
-
|
|
231971
|
-
|
|
231972
|
-
|
|
231999
|
+
const maxTruncationNoticeLength = 100;
|
|
232000
|
+
const maxGrepOutputLength = MAX_LLM_CONTENT_LENGTH - header.length - maxTruncationNoticeLength;
|
|
232001
|
+
let truncatedByLineLimit = false;
|
|
232002
|
+
let linesToInclude = allLines;
|
|
232003
|
+
if (this.params.limit !== void 0 && allLines.length > this.params.limit) {
|
|
232004
|
+
linesToInclude = allLines.slice(0, this.params.limit);
|
|
232005
|
+
truncatedByLineLimit = true;
|
|
232006
|
+
}
|
|
232007
|
+
let grepOutput = linesToInclude.join(EOL3);
|
|
232008
|
+
let truncatedByCharLimit = false;
|
|
232009
|
+
if (grepOutput.length > maxGrepOutputLength) {
|
|
232010
|
+
grepOutput = grepOutput.slice(0, maxGrepOutputLength) + "...";
|
|
232011
|
+
truncatedByCharLimit = true;
|
|
232012
|
+
}
|
|
232013
|
+
const finalLines = grepOutput.split(EOL3).filter((line) => line.trim());
|
|
232014
|
+
const includedLines = finalLines.length;
|
|
232015
|
+
let llmContent = header + grepOutput;
|
|
232016
|
+
if (truncatedByLineLimit || truncatedByCharLimit) {
|
|
232017
|
+
const omittedMatches = totalMatches - includedLines;
|
|
232018
|
+
llmContent += ` [${omittedMatches} ${omittedMatches === 1 ? "line" : "lines"} truncated] ...`;
|
|
232019
|
+
}
|
|
232020
|
+
let displayMessage = `Found ${totalMatches} ${matchTerm}`;
|
|
232021
|
+
if (truncatedByLineLimit || truncatedByCharLimit) {
|
|
232022
|
+
displayMessage += ` (truncated)`;
|
|
231973
232023
|
}
|
|
231974
232024
|
return {
|
|
231975
232025
|
llmContent: llmContent.trim(),
|
|
@@ -231984,38 +232034,8 @@ var init_ripGrep = __esm({
|
|
|
231984
232034
|
};
|
|
231985
232035
|
}
|
|
231986
232036
|
}
|
|
231987
|
-
parseRipgrepOutput(output, basePath) {
|
|
231988
|
-
const results = [];
|
|
231989
|
-
if (!output)
|
|
231990
|
-
return results;
|
|
231991
|
-
const lines = output.split(EOL3);
|
|
231992
|
-
for (const line of lines) {
|
|
231993
|
-
if (!line.trim())
|
|
231994
|
-
continue;
|
|
231995
|
-
const firstColonIndex = line.indexOf(":");
|
|
231996
|
-
if (firstColonIndex === -1)
|
|
231997
|
-
continue;
|
|
231998
|
-
const secondColonIndex = line.indexOf(":", firstColonIndex + 1);
|
|
231999
|
-
if (secondColonIndex === -1)
|
|
232000
|
-
continue;
|
|
232001
|
-
const filePathRaw = line.substring(0, firstColonIndex);
|
|
232002
|
-
const lineNumberStr = line.substring(firstColonIndex + 1, secondColonIndex);
|
|
232003
|
-
const lineContent = line.substring(secondColonIndex + 1);
|
|
232004
|
-
const lineNumber = parseInt(lineNumberStr, 10);
|
|
232005
|
-
if (!isNaN(lineNumber)) {
|
|
232006
|
-
const absoluteFilePath = path40.resolve(basePath, filePathRaw);
|
|
232007
|
-
const relativeFilePath = path40.relative(basePath, absoluteFilePath);
|
|
232008
|
-
results.push({
|
|
232009
|
-
filePath: relativeFilePath || path40.basename(absoluteFilePath),
|
|
232010
|
-
lineNumber,
|
|
232011
|
-
line: lineContent
|
|
232012
|
-
});
|
|
232013
|
-
}
|
|
232014
|
-
}
|
|
232015
|
-
return results;
|
|
232016
|
-
}
|
|
232017
232037
|
async performRipgrepSearch(options2) {
|
|
232018
|
-
const { pattern, path: absolutePath,
|
|
232038
|
+
const { pattern, path: absolutePath, glob: glob2 } = options2;
|
|
232019
232039
|
const rgArgs = [
|
|
232020
232040
|
"--line-number",
|
|
232021
232041
|
"--no-heading",
|
|
@@ -232024,26 +232044,23 @@ var init_ripGrep = __esm({
|
|
|
232024
232044
|
"--regexp",
|
|
232025
232045
|
pattern
|
|
232026
232046
|
];
|
|
232027
|
-
|
|
232028
|
-
|
|
232029
|
-
|
|
232030
|
-
|
|
232031
|
-
|
|
232032
|
-
"
|
|
232033
|
-
|
|
232034
|
-
|
|
232035
|
-
|
|
232036
|
-
|
|
232037
|
-
|
|
232038
|
-
"
|
|
232039
|
-
|
|
232040
|
-
excludes.forEach((exclude) => {
|
|
232041
|
-
rgArgs.push("--glob", `!${exclude}`);
|
|
232042
|
-
});
|
|
232047
|
+
const filteringOptions = this.getFileFilteringOptions();
|
|
232048
|
+
if (!filteringOptions.respectGitIgnore) {
|
|
232049
|
+
rgArgs.push("--no-ignore-vcs");
|
|
232050
|
+
}
|
|
232051
|
+
if (filteringOptions.respectQwenIgnore) {
|
|
232052
|
+
const qwenIgnorePath = path40.join(this.config.getTargetDir(), ".qwenignore");
|
|
232053
|
+
if (fs36.existsSync(qwenIgnorePath)) {
|
|
232054
|
+
rgArgs.push("--ignore-file", qwenIgnorePath);
|
|
232055
|
+
}
|
|
232056
|
+
}
|
|
232057
|
+
if (glob2) {
|
|
232058
|
+
rgArgs.push("--glob", glob2);
|
|
232059
|
+
}
|
|
232043
232060
|
rgArgs.push("--threads", "4");
|
|
232044
232061
|
rgArgs.push(absolutePath);
|
|
232045
232062
|
try {
|
|
232046
|
-
const rgPath = await ensureRipgrepPath();
|
|
232063
|
+
const rgPath = this.config.getUseBuiltinRipgrep() ? await ensureRipgrepPath() : "rg";
|
|
232047
232064
|
const output = await new Promise((resolve23, reject) => {
|
|
232048
232065
|
const child = spawn6(rgPath, rgArgs, {
|
|
232049
232066
|
windowsHide: true
|
|
@@ -232075,21 +232092,27 @@ var init_ripGrep = __esm({
|
|
|
232075
232092
|
}
|
|
232076
232093
|
});
|
|
232077
232094
|
});
|
|
232078
|
-
return
|
|
232095
|
+
return output;
|
|
232079
232096
|
} catch (error) {
|
|
232080
232097
|
console.error(`GrepLogic: ripgrep failed: ${getErrorMessage(error)}`);
|
|
232081
232098
|
throw error;
|
|
232082
232099
|
}
|
|
232083
232100
|
}
|
|
232101
|
+
getFileFilteringOptions() {
|
|
232102
|
+
const options2 = this.config.getFileFilteringOptions?.();
|
|
232103
|
+
return {
|
|
232104
|
+
respectGitIgnore: options2?.respectGitIgnore ?? DEFAULT_FILE_FILTERING_OPTIONS.respectGitIgnore,
|
|
232105
|
+
respectQwenIgnore: options2?.respectQwenIgnore ?? DEFAULT_FILE_FILTERING_OPTIONS.respectQwenIgnore
|
|
232106
|
+
};
|
|
232107
|
+
}
|
|
232084
232108
|
/**
|
|
232085
232109
|
* Gets a description of the grep operation
|
|
232086
|
-
* @param params Parameters for the grep operation
|
|
232087
232110
|
* @returns A string describing the grep
|
|
232088
232111
|
*/
|
|
232089
232112
|
getDescription() {
|
|
232090
232113
|
let description = `'${this.params.pattern}'`;
|
|
232091
|
-
if (this.params.
|
|
232092
|
-
description += ` in ${this.params.
|
|
232114
|
+
if (this.params.glob) {
|
|
232115
|
+
description += ` in ${this.params.glob}`;
|
|
232093
232116
|
}
|
|
232094
232117
|
if (this.params.path) {
|
|
232095
232118
|
const resolvedPath = path40.resolve(this.config.getTargetDir(), this.params.path);
|
|
@@ -232114,21 +232137,25 @@ var init_ripGrep = __esm({
|
|
|
232114
232137
|
__name(this, "RipGrepTool");
|
|
232115
232138
|
}
|
|
232116
232139
|
config;
|
|
232117
|
-
static Name =
|
|
232140
|
+
static Name = ToolNames.GREP;
|
|
232118
232141
|
constructor(config) {
|
|
232119
|
-
super(_RipGrepTool.Name, "
|
|
232142
|
+
super(_RipGrepTool.Name, "Grep", 'A powerful search tool built on ripgrep\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 - Use Task tool for open-ended searches requiring multiple rounds\n - Pattern syntax: Uses ripgrep (not grep) - special regex characters need escaping (use `interface\\{\\}` to find `interface{}` in Go code)\n', Kind.Search, {
|
|
232120
232143
|
properties: {
|
|
232121
232144
|
pattern: {
|
|
232122
|
-
|
|
232123
|
-
|
|
232145
|
+
type: "string",
|
|
232146
|
+
description: "The regular expression pattern to search for in file contents"
|
|
232147
|
+
},
|
|
232148
|
+
glob: {
|
|
232149
|
+
type: "string",
|
|
232150
|
+
description: 'Glob pattern to filter files (e.g. "*.js", "*.{ts,tsx}") - maps to rg --glob'
|
|
232124
232151
|
},
|
|
232125
232152
|
path: {
|
|
232126
|
-
|
|
232127
|
-
|
|
232153
|
+
type: "string",
|
|
232154
|
+
description: "File or directory to search in (rg PATH). Defaults to current working directory."
|
|
232128
232155
|
},
|
|
232129
|
-
|
|
232130
|
-
|
|
232131
|
-
|
|
232156
|
+
limit: {
|
|
232157
|
+
type: "number",
|
|
232158
|
+
description: "Limit output to first N lines/entries. Optional - shows all matches if not specified."
|
|
232132
232159
|
}
|
|
232133
232160
|
},
|
|
232134
232161
|
required: ["pattern"],
|
|
@@ -232139,12 +232166,12 @@ var init_ripGrep = __esm({
|
|
|
232139
232166
|
/**
|
|
232140
232167
|
* Checks if a path is within the root directory and resolves it.
|
|
232141
232168
|
* @param relativePath Path relative to the root directory (or undefined for root).
|
|
232142
|
-
* @returns The absolute path
|
|
232169
|
+
* @returns The absolute path to search within.
|
|
232143
232170
|
* @throws {Error} If path is outside root, doesn't exist, or isn't a directory.
|
|
232144
232171
|
*/
|
|
232145
232172
|
resolveAndValidatePath(relativePath) {
|
|
232146
232173
|
if (!relativePath) {
|
|
232147
|
-
return
|
|
232174
|
+
return this.config.getTargetDir();
|
|
232148
232175
|
}
|
|
232149
232176
|
const targetPath = path40.resolve(this.config.getTargetDir(), relativePath);
|
|
232150
232177
|
const workspaceContext = this.config.getWorkspaceContext();
|
|
@@ -232170,11 +232197,16 @@ var init_ripGrep = __esm({
|
|
|
232170
232197
|
* @param params Parameters to validate
|
|
232171
232198
|
* @returns An error message string if invalid, null otherwise
|
|
232172
232199
|
*/
|
|
232173
|
-
|
|
232200
|
+
validateToolParamValues(params) {
|
|
232174
232201
|
const errors = SchemaValidator.validate(this.schema.parametersJsonSchema, params);
|
|
232175
232202
|
if (errors) {
|
|
232176
232203
|
return errors;
|
|
232177
232204
|
}
|
|
232205
|
+
try {
|
|
232206
|
+
new RegExp(params.pattern);
|
|
232207
|
+
} catch (error) {
|
|
232208
|
+
return `Invalid regular expression pattern: ${params.pattern}. Error: ${getErrorMessage(error)}`;
|
|
232209
|
+
}
|
|
232178
232210
|
if (params.path) {
|
|
232179
232211
|
try {
|
|
232180
232212
|
this.resolveAndValidatePath(params.path);
|
|
@@ -243855,6 +243887,7 @@ var init_config3 = __esm({
|
|
|
243855
243887
|
interactive;
|
|
243856
243888
|
trustedFolder;
|
|
243857
243889
|
useRipgrep;
|
|
243890
|
+
useBuiltinRipgrep;
|
|
243858
243891
|
shouldUseNodePtyShell;
|
|
243859
243892
|
skipNextSpeakerCheck;
|
|
243860
243893
|
shellExecutionConfig;
|
|
@@ -243942,11 +243975,10 @@ var init_config3 = __esm({
|
|
|
243942
243975
|
this.chatCompression = params.chatCompression;
|
|
243943
243976
|
this.interactive = params.interactive ?? false;
|
|
243944
243977
|
this.trustedFolder = params.trustedFolder;
|
|
243945
|
-
this.shouldUseNodePtyShell = params.shouldUseNodePtyShell ?? false;
|
|
243946
|
-
this.skipNextSpeakerCheck = params.skipNextSpeakerCheck ?? false;
|
|
243947
243978
|
this.skipLoopDetection = params.skipLoopDetection ?? false;
|
|
243948
243979
|
this.tavilyApiKey = params.tavilyApiKey;
|
|
243949
243980
|
this.useRipgrep = params.useRipgrep ?? true;
|
|
243981
|
+
this.useBuiltinRipgrep = params.useBuiltinRipgrep ?? true;
|
|
243950
243982
|
this.shouldUseNodePtyShell = params.shouldUseNodePtyShell ?? false;
|
|
243951
243983
|
this.skipNextSpeakerCheck = params.skipNextSpeakerCheck ?? true;
|
|
243952
243984
|
this.shellExecutionConfig = {
|
|
@@ -244314,6 +244346,9 @@ var init_config3 = __esm({
|
|
|
244314
244346
|
getUseRipgrep() {
|
|
244315
244347
|
return this.useRipgrep;
|
|
244316
244348
|
}
|
|
244349
|
+
getUseBuiltinRipgrep() {
|
|
244350
|
+
return this.useBuiltinRipgrep;
|
|
244351
|
+
}
|
|
244317
244352
|
getShouldUseNodePtyShell() {
|
|
244318
244353
|
return this.shouldUseNodePtyShell;
|
|
244319
244354
|
}
|
|
@@ -244402,13 +244437,14 @@ var init_config3 = __esm({
|
|
|
244402
244437
|
let useRipgrep = false;
|
|
244403
244438
|
let errorString = void 0;
|
|
244404
244439
|
try {
|
|
244405
|
-
useRipgrep = await canUseRipgrep();
|
|
244440
|
+
useRipgrep = await canUseRipgrep(this.getUseBuiltinRipgrep());
|
|
244406
244441
|
} catch (error) {
|
|
244407
244442
|
errorString = String(error);
|
|
244408
244443
|
}
|
|
244409
244444
|
if (useRipgrep) {
|
|
244410
244445
|
registerCoreTool(RipGrepTool, this);
|
|
244411
244446
|
} else {
|
|
244447
|
+
errorString = errorString || "Ripgrep is not available. Please install ripgrep globally.";
|
|
244412
244448
|
logRipgrepFallback(this, new RipgrepFallbackEvent(errorString));
|
|
244413
244449
|
registerCoreTool(GrepTool, this);
|
|
244414
244450
|
}
|
|
@@ -251803,6 +251839,7 @@ var init_src = __esm({
|
|
|
251803
251839
|
init_textUtils();
|
|
251804
251840
|
init_formatters();
|
|
251805
251841
|
init_generateContentResponseUtilities();
|
|
251842
|
+
init_ripgrepUtils();
|
|
251806
251843
|
init_fileSearch();
|
|
251807
251844
|
init_errorParsing();
|
|
251808
251845
|
init_workspaceContext();
|
|
@@ -316229,7 +316266,7 @@ init_esbuild_shims();
|
|
|
316229
316266
|
|
|
316230
316267
|
// packages/cli/src/generated/git-commit.ts
|
|
316231
316268
|
init_esbuild_shims();
|
|
316232
|
-
var GIT_COMMIT_INFO2 = "
|
|
316269
|
+
var GIT_COMMIT_INFO2 = "388dee5a";
|
|
316233
316270
|
|
|
316234
316271
|
// packages/cli/src/ui/components/AboutBox.tsx
|
|
316235
316272
|
var import_jsx_runtime43 = __toESM(require_jsx_runtime(), 1);
|
|
@@ -317345,7 +317382,7 @@ var ToolsList = /* @__PURE__ */ __name(({
|
|
|
317345
317382
|
showDescriptions,
|
|
317346
317383
|
terminalWidth
|
|
317347
317384
|
}) => /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)(Box_default, { flexDirection: "column", marginBottom: 1, children: [
|
|
317348
|
-
/* @__PURE__ */ (0, import_jsx_runtime51.jsx)(Text, { bold: true, color: theme.text.primary, children: "Available
|
|
317385
|
+
/* @__PURE__ */ (0, import_jsx_runtime51.jsx)(Text, { bold: true, color: theme.text.primary, children: "Available Qwen Code CLI tools:" }),
|
|
317349
317386
|
/* @__PURE__ */ (0, import_jsx_runtime51.jsx)(Box_default, { height: 1 }),
|
|
317350
317387
|
tools.length > 0 ? tools.map((tool) => /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)(Box_default, { flexDirection: "row", children: [
|
|
317351
317388
|
/* @__PURE__ */ (0, import_jsx_runtime51.jsxs)(Text, { color: theme.text.primary, children: [
|
|
@@ -319044,6 +319081,15 @@ var SETTINGS_SCHEMA = {
|
|
|
319044
319081
|
description: "Use ripgrep for file content search instead of the fallback implementation. Provides faster search performance.",
|
|
319045
319082
|
showInDialog: true
|
|
319046
319083
|
},
|
|
319084
|
+
useBuiltinRipgrep: {
|
|
319085
|
+
type: "boolean",
|
|
319086
|
+
label: "Use Builtin Ripgrep",
|
|
319087
|
+
category: "Tools",
|
|
319088
|
+
requiresRestart: false,
|
|
319089
|
+
default: true,
|
|
319090
|
+
description: 'Use the bundled ripgrep binary. When set to false, the system-level "rg" command will be used instead. This setting is only effective when useRipgrep is true.',
|
|
319091
|
+
showInDialog: true
|
|
319092
|
+
},
|
|
319047
319093
|
enableToolOutputTruncation: {
|
|
319048
319094
|
type: "boolean",
|
|
319049
319095
|
label: "Enable Tool Output Truncation",
|
|
@@ -325786,6 +325832,8 @@ var USER_SETTINGS_PATH = Storage.getGlobalSettingsPath();
|
|
|
325786
325832
|
var USER_SETTINGS_DIR2 = path71.dirname(USER_SETTINGS_PATH);
|
|
325787
325833
|
var DEFAULT_EXCLUDED_ENV_VARS = ["DEBUG", "DEBUG_MODE"];
|
|
325788
325834
|
var MIGRATE_V2_OVERWRITE = true;
|
|
325835
|
+
var SETTINGS_VERSION = 2;
|
|
325836
|
+
var SETTINGS_VERSION_KEY = "$version";
|
|
325789
325837
|
var MIGRATION_MAP = {
|
|
325790
325838
|
accessibility: "ui.accessibility",
|
|
325791
325839
|
allowedTools: "tools.allowed",
|
|
@@ -325911,6 +325959,12 @@ function setNestedProperty(obj, path107, value) {
|
|
|
325911
325959
|
}
|
|
325912
325960
|
__name(setNestedProperty, "setNestedProperty");
|
|
325913
325961
|
function needsMigration(settings) {
|
|
325962
|
+
if (SETTINGS_VERSION_KEY in settings) {
|
|
325963
|
+
const version2 = settings[SETTINGS_VERSION_KEY];
|
|
325964
|
+
if (typeof version2 === "number" && version2 >= SETTINGS_VERSION) {
|
|
325965
|
+
return false;
|
|
325966
|
+
}
|
|
325967
|
+
}
|
|
325914
325968
|
const hasV1Keys = Object.entries(MIGRATION_MAP).some(([v1Key, v2Path]) => {
|
|
325915
325969
|
if (v1Key === v2Path || !(v1Key in settings)) {
|
|
325916
325970
|
return false;
|
|
@@ -325931,6 +325985,11 @@ function migrateSettingsToV2(flatSettings) {
|
|
|
325931
325985
|
const flatKeys = new Set(Object.keys(flatSettings));
|
|
325932
325986
|
for (const [oldKey, newPath] of Object.entries(MIGRATION_MAP)) {
|
|
325933
325987
|
if (flatKeys.has(oldKey)) {
|
|
325988
|
+
if (KNOWN_V2_CONTAINERS.has(oldKey) && typeof flatSettings[oldKey] === "object" && flatSettings[oldKey] !== null && !Array.isArray(flatSettings[oldKey])) {
|
|
325989
|
+
v2Settings[oldKey] = flatSettings[oldKey];
|
|
325990
|
+
flatKeys.delete(oldKey);
|
|
325991
|
+
continue;
|
|
325992
|
+
}
|
|
325934
325993
|
setNestedProperty(v2Settings, newPath, flatSettings[oldKey]);
|
|
325935
325994
|
flatKeys.delete(oldKey);
|
|
325936
325995
|
}
|
|
@@ -325954,6 +326013,7 @@ function migrateSettingsToV2(flatSettings) {
|
|
|
325954
326013
|
v2Settings[remainingKey] = newValue;
|
|
325955
326014
|
}
|
|
325956
326015
|
}
|
|
326016
|
+
v2Settings[SETTINGS_VERSION_KEY] = SETTINGS_VERSION;
|
|
325957
326017
|
return v2Settings;
|
|
325958
326018
|
}
|
|
325959
326019
|
__name(migrateSettingsToV2, "migrateSettingsToV2");
|
|
@@ -325990,6 +326050,9 @@ function migrateSettingsToV1(v2Settings) {
|
|
|
325990
326050
|
v2Keys.delete("mcpServers");
|
|
325991
326051
|
}
|
|
325992
326052
|
for (const remainingKey of v2Keys) {
|
|
326053
|
+
if (remainingKey === SETTINGS_VERSION_KEY) {
|
|
326054
|
+
continue;
|
|
326055
|
+
}
|
|
325993
326056
|
const value = v2Settings[remainingKey];
|
|
325994
326057
|
if (value === void 0) {
|
|
325995
326058
|
continue;
|
|
@@ -326195,6 +326258,21 @@ function loadSettings(workspaceDir = process27.cwd()) {
|
|
|
326195
326258
|
}
|
|
326196
326259
|
settingsObject = migratedSettings;
|
|
326197
326260
|
}
|
|
326261
|
+
} else if (!(SETTINGS_VERSION_KEY in settingsObject)) {
|
|
326262
|
+
settingsObject[SETTINGS_VERSION_KEY] = SETTINGS_VERSION;
|
|
326263
|
+
if (MIGRATE_V2_OVERWRITE) {
|
|
326264
|
+
try {
|
|
326265
|
+
fs69.writeFileSync(
|
|
326266
|
+
filePath,
|
|
326267
|
+
JSON.stringify(settingsObject, null, 2),
|
|
326268
|
+
"utf-8"
|
|
326269
|
+
);
|
|
326270
|
+
} catch (e2) {
|
|
326271
|
+
console.error(
|
|
326272
|
+
`Error adding version to settings file: ${getErrorMessage(e2)}`
|
|
326273
|
+
);
|
|
326274
|
+
}
|
|
326275
|
+
}
|
|
326198
326276
|
}
|
|
326199
326277
|
return { settings: settingsObject, rawJson: content };
|
|
326200
326278
|
}
|
|
@@ -338265,7 +338343,7 @@ __name(getPackageJson, "getPackageJson");
|
|
|
338265
338343
|
// packages/cli/src/utils/version.ts
|
|
338266
338344
|
async function getCliVersion() {
|
|
338267
338345
|
const pkgJson = await getPackageJson();
|
|
338268
|
-
return "0.1.
|
|
338346
|
+
return "0.1.3-nightly.20251101.ff8a8ac6";
|
|
338269
338347
|
}
|
|
338270
338348
|
__name(getCliVersion, "getCliVersion");
|
|
338271
338349
|
|
|
@@ -338763,7 +338841,7 @@ async function parseArguments(settings) {
|
|
|
338763
338841
|
'Use the "proxy" setting in settings.json instead. This flag will be removed in a future version.'
|
|
338764
338842
|
).command(
|
|
338765
338843
|
"$0 [query..]",
|
|
338766
|
-
"Launch
|
|
338844
|
+
"Launch Qwen Code CLI",
|
|
338767
338845
|
(yargsInstance2) => yargsInstance2.positional("query", {
|
|
338768
338846
|
description: "Positional prompt. Defaults to one-shot; use -i/--prompt-interactive for interactive."
|
|
338769
338847
|
}).option("model", {
|
|
@@ -339146,6 +339224,7 @@ async function loadCliConfig(settings, extensions, extensionEnablementManager, s
|
|
|
339146
339224
|
interactive,
|
|
339147
339225
|
trustedFolder,
|
|
339148
339226
|
useRipgrep: settings.tools?.useRipgrep,
|
|
339227
|
+
useBuiltinRipgrep: settings.tools?.useBuiltinRipgrep,
|
|
339149
339228
|
shouldUseNodePtyShell: settings.tools?.shell?.enableInteractiveShell,
|
|
339150
339229
|
skipNextSpeakerCheck: settings.model?.skipNextSpeakerCheck,
|
|
339151
339230
|
enablePromptCompletion: settings.general?.enablePromptCompletion ?? false,
|
|
@@ -340228,7 +340307,7 @@ var bugCommand = {
|
|
|
340228
340307
|
let info = `
|
|
340229
340308
|
* **CLI Version:** ${cliVersion}
|
|
340230
340309
|
* **Git Commit:** ${GIT_COMMIT_INFO2}
|
|
340231
|
-
* **Session ID:** ${
|
|
340310
|
+
* **Session ID:** ${config?.getSessionId() || "unknown"}
|
|
340232
340311
|
* **Operating System:** ${osVersion}
|
|
340233
340312
|
* **Sandbox Environment:** ${sandboxEnv}
|
|
340234
340313
|
* **Auth Type:** ${selectedAuthType}`;
|
|
@@ -352954,10 +353033,10 @@ import * as os38 from "node:os";
|
|
|
352954
353033
|
import path105 from "node:path";
|
|
352955
353034
|
var homeDirectoryCheck = {
|
|
352956
353035
|
id: "home-directory",
|
|
352957
|
-
check: /* @__PURE__ */ __name(async (
|
|
353036
|
+
check: /* @__PURE__ */ __name(async (options2) => {
|
|
352958
353037
|
try {
|
|
352959
353038
|
const [workspaceRealPath, homeRealPath] = await Promise.all([
|
|
352960
|
-
fs92.realpath(workspaceRoot),
|
|
353039
|
+
fs92.realpath(options2.workspaceRoot),
|
|
352961
353040
|
fs92.realpath(os38.homedir())
|
|
352962
353041
|
]);
|
|
352963
353042
|
if (workspaceRealPath === homeRealPath) {
|
|
@@ -352971,9 +353050,9 @@ var homeDirectoryCheck = {
|
|
|
352971
353050
|
};
|
|
352972
353051
|
var rootDirectoryCheck = {
|
|
352973
353052
|
id: "root-directory",
|
|
352974
|
-
check: /* @__PURE__ */ __name(async (
|
|
353053
|
+
check: /* @__PURE__ */ __name(async (options2) => {
|
|
352975
353054
|
try {
|
|
352976
|
-
const workspaceRealPath = await fs92.realpath(workspaceRoot);
|
|
353055
|
+
const workspaceRealPath = await fs92.realpath(options2.workspaceRoot);
|
|
352977
353056
|
const errorMessage = "Warning: You are running Qwen Code in the root directory. Your entire folder structure will be used for context. It is strongly recommended to run in a project-specific directory.";
|
|
352978
353057
|
if (path105.dirname(workspaceRealPath) === workspaceRealPath) {
|
|
352979
353058
|
return errorMessage;
|
|
@@ -352984,13 +353063,27 @@ var rootDirectoryCheck = {
|
|
|
352984
353063
|
}
|
|
352985
353064
|
}, "check")
|
|
352986
353065
|
};
|
|
353066
|
+
var ripgrepAvailabilityCheck = {
|
|
353067
|
+
id: "ripgrep-availability",
|
|
353068
|
+
check: /* @__PURE__ */ __name(async (options2) => {
|
|
353069
|
+
if (!options2.useRipgrep) {
|
|
353070
|
+
return null;
|
|
353071
|
+
}
|
|
353072
|
+
const isAvailable = await canUseRipgrep(options2.useBuiltinRipgrep);
|
|
353073
|
+
if (!isAvailable) {
|
|
353074
|
+
return "Ripgrep not available: Please install ripgrep globally to enable faster file content search. Falling back to built-in grep.";
|
|
353075
|
+
}
|
|
353076
|
+
return null;
|
|
353077
|
+
}, "check")
|
|
353078
|
+
};
|
|
352987
353079
|
var WARNING_CHECKS = [
|
|
352988
353080
|
homeDirectoryCheck,
|
|
352989
|
-
rootDirectoryCheck
|
|
353081
|
+
rootDirectoryCheck,
|
|
353082
|
+
ripgrepAvailabilityCheck
|
|
352990
353083
|
];
|
|
352991
|
-
async function getUserStartupWarnings(
|
|
353084
|
+
async function getUserStartupWarnings(options2) {
|
|
352992
353085
|
const results = await Promise.all(
|
|
352993
|
-
WARNING_CHECKS.map((check) => check.check(
|
|
353086
|
+
WARNING_CHECKS.map((check) => check.check(options2))
|
|
352994
353087
|
);
|
|
352995
353088
|
return results.filter((msg) => msg !== null);
|
|
352996
353089
|
}
|
|
@@ -354917,7 +355010,11 @@ ${finalArgs[promptIndex + 1]}`;
|
|
|
354917
355010
|
let input = config.getQuestion();
|
|
354918
355011
|
const startupWarnings = [
|
|
354919
355012
|
...await getStartupWarnings(),
|
|
354920
|
-
...await getUserStartupWarnings(
|
|
355013
|
+
...await getUserStartupWarnings({
|
|
355014
|
+
workspaceRoot: process.cwd(),
|
|
355015
|
+
useRipgrep: settings.merged.tools?.useRipgrep ?? true,
|
|
355016
|
+
useBuiltinRipgrep: settings.merged.tools?.useBuiltinRipgrep ?? true
|
|
355017
|
+
})
|
|
354921
355018
|
];
|
|
354922
355019
|
if (config.isInteractive()) {
|
|
354923
355020
|
await kittyProtocolDetectionComplete;
|