Compare commits

...

5 Commits

Author SHA1 Message Date
koalazf.99
514f292770 add config: tool output char limit 2025-09-17 14:13:58 +08:00
koalazf.99
a0d77f5a44 add: remove loop detect in yolo 2025-09-16 22:50:30 +08:00
koalazf.99
a9a84014e4 remove editCorrector / compress logic in yolo 2025-09-16 19:10:12 +08:00
koalazf.99
92af02c494 remove read_folder context before user input 2025-09-16 16:27:01 +08:00
koalazf.99
740768dc1b dev yolo 2025-09-16 13:57:28 +08:00
13 changed files with 231 additions and 76 deletions

View File

@@ -603,7 +603,9 @@ export async function loadCliConfig(
interactive, interactive,
trustedFolder, trustedFolder,
shouldUseNodePtyShell: settings.shouldUseNodePtyShell, shouldUseNodePtyShell: settings.shouldUseNodePtyShell,
skipStartupContext: settings.skipStartupContext,
skipNextSpeakerCheck: settings.skipNextSpeakerCheck, skipNextSpeakerCheck: settings.skipNextSpeakerCheck,
toolOutputCharLimit: settings.toolOutputCharLimit,
}); });
} }

View File

@@ -577,6 +577,16 @@ export const SETTINGS_SCHEMA = {
description: 'The maximum number of tokens allowed in a session.', description: 'The maximum number of tokens allowed in a session.',
showInDialog: false, showInDialog: false,
}, },
toolOutputCharLimit: {
type: 'number',
label: 'Tool Output Character Limit',
category: 'General',
requiresRestart: false,
default: undefined as number | undefined,
description:
'Max characters for tool outputs (read_file, read_many_files, shell). If set, text content is truncated to this limit.',
showInDialog: true,
},
systemPromptMappings: { systemPromptMappings: {
type: 'object', type: 'object',
label: 'System Prompt Mappings', label: 'System Prompt Mappings',
@@ -595,12 +605,22 @@ export const SETTINGS_SCHEMA = {
description: 'The API key for the Tavily API.', description: 'The API key for the Tavily API.',
showInDialog: false, showInDialog: false,
}, },
skipStartupContext: {
type: 'boolean',
label: 'Skip Startup Context',
category: 'General',
requiresRestart: false,
default: true,
description:
'Do not prepend environment/folder structure context or the initial acknowledgment message.',
showInDialog: true,
},
skipNextSpeakerCheck: { skipNextSpeakerCheck: {
type: 'boolean', type: 'boolean',
label: 'Skip Next Speaker Check', label: 'Skip Next Speaker Check',
category: 'General', category: 'General',
requiresRestart: false, requiresRestart: false,
default: false, default: true,
description: 'Skip the next speaker check.', description: 'Skip the next speaker check.',
showInDialog: true, showInDialog: true,
}, },

View File

@@ -12,6 +12,7 @@ import {
isTelemetrySdkInitialized, isTelemetrySdkInitialized,
GeminiEventType, GeminiEventType,
parseAndFormatApiError, parseAndFormatApiError,
ApprovalMode,
} from '@qwen-code/qwen-code-core'; } from '@qwen-code/qwen-code-core';
import { Content, Part, FunctionCall } from '@google/genai'; import { Content, Part, FunctionCall } from '@google/genai';
@@ -39,6 +40,12 @@ export async function runNonInteractive(
const geminiClient = config.getGeminiClient(); const geminiClient = config.getGeminiClient();
// In YOLO mode, disable next_speaker check to avoid auto-continue.
if (config.getApprovalMode && config.getApprovalMode() === ApprovalMode.YOLO) {
(config as unknown as { getSkipNextSpeakerCheck: () => boolean }).getSkipNextSpeakerCheck =
() => true;
}
const abortController = new AbortController(); const abortController = new AbortController();
let currentMessages: Content[] = [ let currentMessages: Content[] = [
{ role: 'user', parts: [{ text: input }] }, { role: 'user', parts: [{ text: input }] },

View File

@@ -77,6 +77,11 @@ export interface BugCommandSettings {
export interface ChatCompressionSettings { export interface ChatCompressionSettings {
contextPercentageThreshold?: number; contextPercentageThreshold?: number;
/**
* When true, disables automatic chat history compression while in YOLO approval mode.
* Manual compression via commands remains available.
*/
disableInYolo?: boolean;
} }
export interface SummarizeToolOutputSettings { export interface SummarizeToolOutputSettings {
@@ -232,7 +237,10 @@ export interface ConfigParameters {
interactive?: boolean; interactive?: boolean;
trustedFolder?: boolean; trustedFolder?: boolean;
shouldUseNodePtyShell?: boolean; shouldUseNodePtyShell?: boolean;
skipStartupContext?: boolean;
skipNextSpeakerCheck?: boolean; skipNextSpeakerCheck?: boolean;
// Character limit for tool text outputs (files and shell)
toolOutputCharLimit?: number;
} }
export class Config { export class Config {
@@ -317,8 +325,10 @@ export class Config {
private readonly interactive: boolean; private readonly interactive: boolean;
private readonly trustedFolder: boolean | undefined; private readonly trustedFolder: boolean | undefined;
private readonly shouldUseNodePtyShell: boolean; private readonly shouldUseNodePtyShell: boolean;
private readonly skipStartupContext: boolean;
private readonly skipNextSpeakerCheck: boolean; private readonly skipNextSpeakerCheck: boolean;
private initialized: boolean = false; private initialized: boolean = false;
private readonly toolOutputCharLimit?: number;
constructor(params: ConfigParameters) { constructor(params: ConfigParameters) {
this.sessionId = params.sessionId; this.sessionId = params.sessionId;
@@ -398,7 +408,9 @@ export class Config {
this.interactive = params.interactive ?? false; this.interactive = params.interactive ?? false;
this.trustedFolder = params.trustedFolder; this.trustedFolder = params.trustedFolder;
this.shouldUseNodePtyShell = params.shouldUseNodePtyShell ?? false; this.shouldUseNodePtyShell = params.shouldUseNodePtyShell ?? false;
this.skipNextSpeakerCheck = params.skipNextSpeakerCheck ?? false; this.skipStartupContext = params.skipStartupContext ?? true;
this.skipNextSpeakerCheck = params.skipNextSpeakerCheck ?? true;
this.toolOutputCharLimit = params.toolOutputCharLimit;
// Web search // Web search
this.tavilyApiKey = params.tavilyApiKey; this.tavilyApiKey = params.tavilyApiKey;
@@ -857,10 +869,22 @@ export class Config {
return this.shouldUseNodePtyShell; return this.shouldUseNodePtyShell;
} }
getSkipStartupContext(): boolean {
return this.skipStartupContext;
}
getSkipNextSpeakerCheck(): boolean { getSkipNextSpeakerCheck(): boolean {
return this.skipNextSpeakerCheck; return this.skipNextSpeakerCheck;
} }
/**
* Returns the configured maximum number of characters for tool outputs.
* If undefined, no character-based truncation is applied by tools.
*/
getToolOutputCharLimit(): number | undefined {
return this.toolOutputCharLimit;
}
async getGitService(): Promise<GitService> { async getGitService(): Promise<GitService> {
if (!this.gitService) { if (!this.gitService) {
this.gitService = new GitService(this.targetDir); this.gitService = new GitService(this.targetDir);

View File

@@ -24,7 +24,7 @@ import {
GeminiEventType, GeminiEventType,
ChatCompressionInfo, ChatCompressionInfo,
} from './turn.js'; } from './turn.js';
import { Config } from '../config/config.js'; import { ApprovalMode, Config } from '../config/config.js';
import { UserTierId } from '../code_assist/types.js'; import { UserTierId } from '../code_assist/types.js';
import { import {
getCoreSystemPrompt, getCoreSystemPrompt,
@@ -228,19 +228,24 @@ export class GeminiClient {
async startChat(extraHistory?: Content[]): Promise<GeminiChat> { async startChat(extraHistory?: Content[]): Promise<GeminiChat> {
this.forceFullIdeContext = true; this.forceFullIdeContext = true;
const envParts = await getEnvironmentContext(this.config); const envParts = this.config.getSkipStartupContext()
? []
: await getEnvironmentContext(this.config);
const toolRegistry = this.config.getToolRegistry(); const toolRegistry = this.config.getToolRegistry();
const toolDeclarations = toolRegistry.getFunctionDeclarations(); const toolDeclarations = toolRegistry.getFunctionDeclarations();
const tools: Tool[] = [{ functionDeclarations: toolDeclarations }]; const tools: Tool[] = [{ functionDeclarations: toolDeclarations }];
const history: Content[] = [ const history: Content[] = [
{ ...(
role: 'user', envParts.length
parts: envParts, ? [
}, { role: 'user', parts: envParts },
{ {
role: 'model', role: 'model',
parts: [{ text: 'Got it. Thanks for the context!' }], parts: [{ text: 'Got it. Thanks for the context!' }],
}, },
]
: []
),
...(extraHistory ?? []), ...(extraHistory ?? []),
]; ];
try { try {
@@ -473,10 +478,18 @@ export class GeminiClient {
// Track the original model from the first call to detect model switching // Track the original model from the first call to detect model switching
const initialModel = originalModel || this.config.getModel(); const initialModel = originalModel || this.config.getModel();
const compressed = await this.tryCompressChat(prompt_id); const chatCompression = this.config.getChatCompression();
const disableAutoCompressionInYolo =
this.config.getApprovalMode() === ApprovalMode.YOLO &&
// Default to disabling auto-compression in YOLO unless explicitly set to false
(chatCompression?.disableInYolo ?? true);
if (compressed) { if (!disableAutoCompressionInYolo) {
yield { type: GeminiEventType.ChatCompressed, value: compressed }; const compressed = await this.tryCompressChat(prompt_id);
if (compressed) {
yield { type: GeminiEventType.ChatCompressed, value: compressed };
}
} }
// Check session token limit after compression using accurate token counting // Check session token limit after compression using accurate token counting
@@ -551,17 +564,25 @@ export class GeminiClient {
const turn = new Turn(this.getChat(), prompt_id); const turn = new Turn(this.getChat(), prompt_id);
const loopDetected = await this.loopDetector.turnStarted(signal); // Disable loop detection entirely in YOLO mode
if (loopDetected) { const loopDetectionDisabled =
yield { type: GeminiEventType.LoopDetected }; this.config.getApprovalMode() === ApprovalMode.YOLO;
return turn;
if (!loopDetectionDisabled) {
const loopDetected = await this.loopDetector.turnStarted(signal);
if (loopDetected) {
yield { type: GeminiEventType.LoopDetected };
return turn;
}
} }
const resultStream = turn.run(request, signal); const resultStream = turn.run(request, signal);
for await (const event of resultStream) { for await (const event of resultStream) {
if (this.loopDetector.addAndCheck(event)) { if (!loopDetectionDisabled) {
yield { type: GeminiEventType.LoopDetected }; if (this.loopDetector.addAndCheck(event)) {
return turn; yield { type: GeminiEventType.LoopDetected };
return turn;
}
} }
yield event; yield event;
if (event.type === GeminiEventType.Error) { if (event.type === GeminiEventType.Error) {

View File

@@ -781,11 +781,15 @@ export class SubAgentScope {
); );
} }
const envParts = await getEnvironmentContext(this.runtimeContext); const envParts = this.runtimeContext.getSkipStartupContext()
const envHistory: Content[] = [ ? []
{ role: 'user', parts: envParts }, : await getEnvironmentContext(this.runtimeContext);
{ role: 'model', parts: [{ text: 'Got it. Thanks for the context!' }] }, const envHistory: Content[] = envParts.length
]; ? [
{ role: 'user', parts: envParts },
{ role: 'model', parts: [{ text: 'Got it. Thanks for the context!' }] },
]
: [];
const start_history = [ const start_history = [
...envHistory, ...envHistory,

View File

@@ -156,6 +156,8 @@ class EditToolInvocation implements ToolInvocation<EditToolParams, ToolResult> {
params, params,
this.config.getGeminiClient(), this.config.getGeminiClient(),
abortSignal, abortSignal,
// Disable LLM-based corrections in YOLO mode
this.config.getApprovalMode() !== ApprovalMode.YOLO,
); );
finalOldString = correctedEdit.params.old_string; finalOldString = correctedEdit.params.old_string;
finalNewString = correctedEdit.params.new_string; finalNewString = correctedEdit.params.new_string;

View File

@@ -122,21 +122,31 @@ class ReadFileToolInvocation extends BaseToolInvocation<
} }
let llmContent: PartUnion; let llmContent: PartUnion;
const charLimit = this.config.getToolOutputCharLimit();
if (result.isTruncated) { if (result.isTruncated) {
const [start, end] = result.linesShown!; const [start, end] = result.linesShown!;
const total = result.originalLineCount!; const total = result.originalLineCount!;
const nextOffset = this.params.offset const nextOffset = this.params.offset
? this.params.offset + end - start + 1 ? this.params.offset + end - start + 1
: end; : end;
llmContent = ` const header = `\nIMPORTANT: The file content has been truncated.\nStatus: Showing lines ${start}-${end} of ${total} total lines.\nAction: To read more of the file, you can use the 'offset' and 'limit' parameters in a subsequent 'read_file' call. For example, to read the next section of the file, use offset: ${nextOffset}.\n\n--- FILE CONTENT (truncated) ---\n`;
IMPORTANT: The file content has been truncated. const body = typeof result.llmContent === 'string' ? result.llmContent : '';
Status: Showing lines ${start}-${end} of ${total} total lines. let truncatedBody = body;
Action: To read more of the file, you can use the 'offset' and 'limit' parameters in a subsequent 'read_file' call. For example, to read the next section of the file, use offset: ${nextOffset}. if (typeof charLimit === 'number' && charLimit > 0 && body.length > charLimit) {
truncatedBody = `${body.slice(0, charLimit)}\n[... File content truncated to ${charLimit} characters ...]`;
--- FILE CONTENT (truncated) --- }
${result.llmContent}`; llmContent = header + truncatedBody;
} else { } else {
llmContent = result.llmContent || ''; let body = result.llmContent || '';
if (
typeof body === 'string' &&
typeof charLimit === 'number' &&
charLimit > 0 &&
body.length > charLimit
) {
body = `${body.slice(0, charLimit)}\n[... File content truncated to ${charLimit} characters ...]`;
}
llmContent = body;
} }
const lines = const lines =

View File

@@ -228,6 +228,7 @@ ${finalExclusionPatternsForDescription
const skippedFiles: Array<{ path: string; reason: string }> = []; const skippedFiles: Array<{ path: string; reason: string }> = [];
const processedFilesRelativePaths: string[] = []; const processedFilesRelativePaths: string[] = [];
const contentParts: PartListUnion = []; const contentParts: PartListUnion = [];
const charLimit = this.config.getToolOutputCharLimit();
const effectiveExcludes = useDefaultExcludes const effectiveExcludes = useDefaultExcludes
? [...DEFAULT_EXCLUDES, ...exclude] ? [...DEFAULT_EXCLUDES, ...exclude]
@@ -436,6 +437,9 @@ ${finalExclusionPatternsForDescription
); );
const results = await Promise.allSettled(fileProcessingPromises); const results = await Promise.allSettled(fileProcessingPromises);
let remainingContentChars =
typeof charLimit === 'number' && charLimit > 0 ? charLimit : Number.POSITIVE_INFINITY;
let globalTruncated = false;
for (const result of results) { for (const result of results) {
if (result.status === 'fulfilled') { if (result.status === 'fulfilled') {
@@ -449,22 +453,47 @@ ${finalExclusionPatternsForDescription
}); });
} else { } else {
// Handle successfully processed files // Handle successfully processed files
const { filePath, relativePathForDisplay, fileReadResult } = const { filePath, relativePathForDisplay, fileReadResult } = fileResult;
fileResult;
if (typeof fileReadResult.llmContent === 'string') { if (typeof fileReadResult.llmContent === 'string') {
// Separator does not count toward char budget
const separator = DEFAULT_OUTPUT_SEPARATOR_FORMAT.replace( const separator = DEFAULT_OUTPUT_SEPARATOR_FORMAT.replace(
'{filePath}', '{filePath}',
filePath, filePath,
); );
let fileContentForLlm = '';
let prefix = `${separator}\n\n`;
// Warning header (if any) does not count toward char budget
if (fileReadResult.isTruncated) { if (fileReadResult.isTruncated) {
fileContentForLlm += `[WARNING: This file was truncated. To view the full content, use the 'read_file' tool on this specific file.]\n\n`; prefix += `[WARNING: This file was truncated. To view the full content, use the 'read_file' tool on this specific file.]\n\n`;
}
contentParts.push(prefix);
// Apply global char budget to the actual file content only
if (remainingContentChars > 0) {
const body = fileReadResult.llmContent;
if (body.length <= remainingContentChars) {
contentParts.push(body + '\n\n');
remainingContentChars -= body.length;
} else {
contentParts.push(
body.slice(0, Math.max(0, remainingContentChars)),
);
contentParts.push(
`\n[... Content truncated to ${charLimit} characters across files ...]\n`,
);
remainingContentChars = 0;
globalTruncated = true;
}
} else if (!globalTruncated && typeof charLimit === 'number') {
// No remaining budget, emit a single global truncation marker after first overflow
contentParts.push(
`\n[... Content truncated to ${charLimit} characters across files ...]\n`,
);
globalTruncated = true;
} }
fileContentForLlm += fileReadResult.llmContent;
contentParts.push(`${separator}\n\n${fileContentForLlm}\n\n`);
} else { } else {
// This is a Part for image/pdf, which we don't add the separator to. // Non-text parts (image/pdf) do not count toward char budget
contentParts.push(fileReadResult.llmContent); contentParts.push(fileReadResult.llmContent);
} }
@@ -538,6 +567,10 @@ ${finalExclusionPatternsForDescription
'No files matching the criteria were found or all were skipped.', 'No files matching the criteria were found or all were skipped.',
); );
} }
if (globalTruncated && typeof charLimit === 'number') {
displayMessage += `\n\nNote: Output truncated to ${charLimit} characters (text content only).`;
}
return { return {
llmContent: contentParts, llmContent: contentParts,
returnDisplay: displayMessage.trim(), returnDisplay: displayMessage.trim(),

View File

@@ -279,6 +279,24 @@ class ShellToolInvocation extends BaseToolInvocation<
} }
} }
// Apply character truncation (middle) to both llmContent and returnDisplay if configured
const charLimit = this.config.getToolOutputCharLimit();
const middleTruncate = (s: string, limit: number): string => {
if (!s || s.length <= limit) return s;
const marker = '\n[... Output truncated due to length ...]\n';
const keep = Math.max(0, Math.floor((limit - marker.length) / 2));
if (keep <= 0) {
return s.slice(0, limit);
}
return s.slice(0, keep) + marker + s.slice(s.length - keep);
};
if (typeof charLimit === 'number' && charLimit > 0) {
llmContent = middleTruncate(llmContent, charLimit);
if (returnDisplayMessage) {
returnDisplayMessage = middleTruncate(returnDisplayMessage, charLimit);
}
}
const summarizeConfig = this.config.getSummarizeToolOutputConfig(); const summarizeConfig = this.config.getSummarizeToolOutputConfig();
if (summarizeConfig && summarizeConfig[ShellTool.Name]) { if (summarizeConfig && summarizeConfig[ShellTool.Name]) {
const summary = await summarizeToolOutput( const summary = await summarizeToolOutput(

View File

@@ -116,6 +116,8 @@ export async function getCorrectedFileContent(
}, },
config.getGeminiClient(), config.getGeminiClient(),
abortSignal, abortSignal,
// Disable LLM-based corrections in YOLO mode
config.getApprovalMode() !== ApprovalMode.YOLO,
); );
correctedContent = correctedParams.new_string; correctedContent = correctedParams.new_string;
} else { } else {
@@ -124,6 +126,8 @@ export async function getCorrectedFileContent(
proposedContent, proposedContent,
config.getGeminiClient(), config.getGeminiClient(),
abortSignal, abortSignal,
// Disable LLM-based corrections in YOLO mode
config.getApprovalMode() !== ApprovalMode.YOLO,
); );
} }
return { originalContent, correctedContent, fileExists }; return { originalContent, correctedContent, fileExists };

View File

@@ -160,6 +160,7 @@ export async function ensureCorrectEdit(
originalParams: EditToolParams, // This is the EditToolParams from edit.ts, without \'corrected\' originalParams: EditToolParams, // This is the EditToolParams from edit.ts, without \'corrected\'
client: GeminiClient, client: GeminiClient,
abortSignal: AbortSignal, abortSignal: AbortSignal,
llmCorrectionsEnabled: boolean = true,
): Promise<CorrectedEditResult> { ): Promise<CorrectedEditResult> {
const cacheKey = `${currentContent}---${originalParams.old_string}---${originalParams.new_string}`; const cacheKey = `${currentContent}---${originalParams.old_string}---${originalParams.new_string}`;
const cachedResult = editCorrectionCache.get(cacheKey); const cachedResult = editCorrectionCache.get(cacheKey);
@@ -178,7 +179,7 @@ export async function ensureCorrectEdit(
let occurrences = countOccurrences(currentContent, finalOldString); let occurrences = countOccurrences(currentContent, finalOldString);
if (occurrences === expectedReplacements) { if (occurrences === expectedReplacements) {
if (newStringPotentiallyEscaped) { if (newStringPotentiallyEscaped && llmCorrectionsEnabled) {
finalNewString = await correctNewStringEscaping( finalNewString = await correctNewStringEscaping(
client, client,
finalOldString, finalOldString,
@@ -225,7 +226,7 @@ export async function ensureCorrectEdit(
if (occurrences === expectedReplacements) { if (occurrences === expectedReplacements) {
finalOldString = unescapedOldStringAttempt; finalOldString = unescapedOldStringAttempt;
if (newStringPotentiallyEscaped) { if (newStringPotentiallyEscaped && llmCorrectionsEnabled) {
finalNewString = await correctNewString( finalNewString = await correctNewString(
client, client,
originalParams.old_string, // original old originalParams.old_string, // original old
@@ -263,38 +264,48 @@ export async function ensureCorrectEdit(
} }
} }
const llmCorrectedOldString = await correctOldStringMismatch( if (llmCorrectionsEnabled) {
client, const llmCorrectedOldString = await correctOldStringMismatch(
currentContent, client,
unescapedOldStringAttempt, currentContent,
abortSignal, unescapedOldStringAttempt,
); abortSignal,
const llmOldOccurrences = countOccurrences( );
currentContent, const llmOldOccurrences = countOccurrences(
llmCorrectedOldString, currentContent,
); llmCorrectedOldString,
);
if (llmOldOccurrences === expectedReplacements) { if (llmOldOccurrences === expectedReplacements) {
finalOldString = llmCorrectedOldString; finalOldString = llmCorrectedOldString;
occurrences = llmOldOccurrences; occurrences = llmOldOccurrences;
if (newStringPotentiallyEscaped) { if (newStringPotentiallyEscaped) {
const baseNewStringForLLMCorrection = unescapeStringForGeminiBug( const baseNewStringForLLMCorrection = unescapeStringForGeminiBug(
originalParams.new_string, originalParams.new_string,
); );
finalNewString = await correctNewString( finalNewString = await correctNewString(
client, client,
originalParams.old_string, // original old originalParams.old_string, // original old
llmCorrectedOldString, // corrected old llmCorrectedOldString, // corrected old
baseNewStringForLLMCorrection, // base new for correction baseNewStringForLLMCorrection, // base new for correction
abortSignal, abortSignal,
); );
}
} else {
// LLM correction also failed for old_string
const result: CorrectedEditResult = {
params: { ...originalParams },
occurrences: 0, // Explicitly 0 as LLM failed
};
editCorrectionCache.set(cacheKey, result);
return result;
} }
} else { } else {
// LLM correction also failed for old_string // LLM corrections disabled -> return as-is to surface mismatch upstream
const result: CorrectedEditResult = { const result: CorrectedEditResult = {
params: { ...originalParams }, params: { ...originalParams },
occurrences: 0, // Explicitly 0 as LLM failed occurrences: 0,
}; };
editCorrectionCache.set(cacheKey, result); editCorrectionCache.set(cacheKey, result);
return result; return result;
@@ -336,6 +347,7 @@ export async function ensureCorrectFileContent(
content: string, content: string,
client: GeminiClient, client: GeminiClient,
abortSignal: AbortSignal, abortSignal: AbortSignal,
llmCorrectionsEnabled: boolean = true,
): Promise<string> { ): Promise<string> {
const cachedResult = fileContentCorrectionCache.get(content); const cachedResult = fileContentCorrectionCache.get(content);
if (cachedResult) { if (cachedResult) {
@@ -349,11 +361,9 @@ export async function ensureCorrectFileContent(
return content; return content;
} }
const correctedContent = await correctStringEscaping( const correctedContent = llmCorrectionsEnabled
content, ? await correctStringEscaping(content, client, abortSignal)
client, : content;
abortSignal,
);
fileContentCorrectionCache.set(content, correctedContent); fileContentCorrectionCache.set(content, correctedContent);
return correctedContent; return correctedContent;
} }

View File

@@ -11,7 +11,7 @@ import mime from 'mime-types';
import { FileSystemService } from '../services/fileSystemService.js'; import { FileSystemService } from '../services/fileSystemService.js';
// Constants for text file processing // Constants for text file processing
export const DEFAULT_MAX_LINES_TEXT_FILE = 2000; export const DEFAULT_MAX_LINES_TEXT_FILE = 500;
const MAX_LINE_LENGTH_TEXT_FILE = 2000; const MAX_LINE_LENGTH_TEXT_FILE = 2000;
// Default values for encoding and separator format // Default values for encoding and separator format