diff --git a/src/tasks/logs/mutators/mutateAppendSectionToLog.ts b/src/tasks/logs/mutators/mutateAppendSectionToLog.ts index 6aa8193..c4afdaf 100644 --- a/src/tasks/logs/mutators/mutateAppendSectionToLog.ts +++ b/src/tasks/logs/mutators/mutateAppendSectionToLog.ts @@ -1,13 +1,16 @@ import { LogContext } from '../LogContext'; import { mutateAppendToLogNoNewline } from './mutateAppendToLogNoNewline'; -export function mutateAppendSectionToLog(task: LogContext, section: string): void { +export function mutateAppendSectionToLog( + task: LogContext, + section: string, +): void { mutateAppendToLogNoNewline( task, - [ + `${[ `////////////////////////////////////////////////////////////////////////////////`, `// ${section}`, `////////////////////////////////////////////////////////////////////////////////`, - ].join('\n') + '\n\n', + ].join('\n')}\n\n`, ); } diff --git a/src/tasks/logs/mutators/mutateAppendToLog.ts b/src/tasks/logs/mutators/mutateAppendToLog.ts index 42ebcbd..6158142 100644 --- a/src/tasks/logs/mutators/mutateAppendToLog.ts +++ b/src/tasks/logs/mutators/mutateAppendToLog.ts @@ -2,5 +2,5 @@ import { TaskContext } from '../../TaskContext'; import { mutateAppendToLogNoNewline } from './mutateAppendToLogNoNewline'; export function mutateAppendToLog(task: TaskContext, content: string): void { - mutateAppendToLogNoNewline(task, content + '\n'); + mutateAppendToLogNoNewline(task, `${content}\n`); } diff --git a/src/tasks/logs/mutators/mutateAppendToLogNoNewline.ts b/src/tasks/logs/mutators/mutateAppendToLogNoNewline.ts index ccb486d..d218627 100644 --- a/src/tasks/logs/mutators/mutateAppendToLogNoNewline.ts +++ b/src/tasks/logs/mutators/mutateAppendToLogNoNewline.ts @@ -1,8 +1,10 @@ import { getLogProvider } from '../../../managers/LogProvider'; -import { TaskContext } from '../../TaskContext'; import { LogContext } from '../LogContext'; -export function mutateAppendToLogNoNewline(task: LogContext, content: string): void { +export function mutateAppendToLogNoNewline( + task: LogContext, + content: string, +): void { task.logContent += content; getLogProvider().reportChangeInTask(task.id); diff --git a/src/tasks/mutators/mutateGenerateShortName.ts b/src/tasks/mutators/mutateGenerateShortName.ts index 912b436..8017c6e 100644 --- a/src/tasks/mutators/mutateGenerateShortName.ts +++ b/src/tasks/mutators/mutateGenerateShortName.ts @@ -1,4 +1,5 @@ import { z } from 'zod'; + import { gptExecute } from '../../gpt/gptExecute'; import { GPTMode } from '../../gpt/types'; import { TaskContext } from '../TaskContext'; @@ -10,7 +11,9 @@ export interface ShortNameContext { selectedText: string; } -export async function mutateGenerateShortName(task: TaskContext & ShortNameContext) { +export async function mutateGenerateShortName( + task: TaskContext & ShortNameContext, +) { task.shortName = '...'; task.onChange(true); diff --git a/src/tasks/mutators/mutateReportSmallProgress.ts b/src/tasks/mutators/mutateReportSmallProgress.ts index fbde9b5..51b570d 100644 --- a/src/tasks/mutators/mutateReportSmallProgress.ts +++ b/src/tasks/mutators/mutateReportSmallProgress.ts @@ -1,6 +1,9 @@ import { TaskContext } from '../TaskContext'; -export function mutateReportSmallProgress(task: TaskContext, fractionOfBigTask = 0.005) { +export function mutateReportSmallProgress( + task: TaskContext, + fractionOfBigTask = 0.005, +) { const totalPending = task.stageTargetProgress - task.progress; const increment = totalPending * fractionOfBigTask; task.progress = task.progress + increment; diff --git a/src/tasks/mutators/mutateRunTaskStages.ts b/src/tasks/mutators/mutateRunTaskStages.ts index e98d3aa..44e35a3 100644 --- a/src/tasks/mutators/mutateRunTaskStages.ts +++ b/src/tasks/mutators/mutateRunTaskStages.ts @@ -1,10 +1,10 @@ -import { mutateAppendToLog } from '../logs/mutators/mutateAppendToLog'; import { getEditorManager } from '../../managers/EditorManager'; +import { WorkspaceFilesKnowledge } from '../../minionTasks/generateDescriptionForWorkspaceFiles'; import { calculateAndFormatExecutionTime } from '../../utils/calculateAndFormatExecutionTime'; +import { mutateAppendToLog } from '../logs/mutators/mutateAppendToLog'; import { TaskContext } from '../TaskContext'; import { TaskCanceled } from '../utils/TaskCanceled'; import { mutateStopExecution } from './mutateStopExecution'; -import { WorkspaceFilesKnowledge } from '../../minionTasks/generateDescriptionForWorkspaceFiles'; export function mutateRunTaskStages( task: TC, @@ -16,7 +16,7 @@ export function mutateRunTaskStages( getExternalData?: () => Promise, test?: boolean, ) { - return new Promise(async (resolve, reject) => { + return new Promise((resolve, reject) => { if (task.stopped) { return; } @@ -26,15 +26,15 @@ export function mutateRunTaskStages( try { task.progress = 0; - await execute(task, getExternalData, test); - await mutateStopExecution(task); + execute(task, getExternalData, test); + mutateStopExecution(task); } catch (error) { if (!(error instanceof TaskCanceled)) { getEditorManager().showErrorMessage(`Error in execution: ${error}`); console.error('Error in execution', error); } - await mutateStopExecution( + mutateStopExecution( task, error instanceof Error ? `Error: ${error.message}` : String(error), ); diff --git a/src/tasks/mutators/mutateStageFinishing.ts b/src/tasks/mutators/mutateStageFinishing.ts index 41e421f..c463137 100644 --- a/src/tasks/mutators/mutateStageFinishing.ts +++ b/src/tasks/mutators/mutateStageFinishing.ts @@ -1,11 +1,15 @@ import { getEditorManager } from '../../managers/EditorManager'; import { playNotificationSound } from '../../utils/playSound'; -import { TaskContext } from '../TaskContext'; import { mutateAppendSectionToLog } from '../logs/mutators/mutateAppendSectionToLog'; +import { TaskContext } from '../TaskContext'; import { ShortNameContext } from './mutateGenerateShortName'; -export async function mutateStageFinishing(task: TC) { - getEditorManager().showInformationMessage(`${task.shortName} is ready to be applied!`); +export async function mutateStageFinishing< + TC extends TaskContext & ShortNameContext, +>(task: TC) { + getEditorManager().showInformationMessage( + `${task.shortName} is ready to be applied!`, + ); mutateAppendSectionToLog(task, task.executionStage); diff --git a/src/tasks/mutators/mutateStartStage.ts b/src/tasks/mutators/mutateStartStage.ts index c565374..28651d0 100644 --- a/src/tasks/mutators/mutateStartStage.ts +++ b/src/tasks/mutators/mutateStartStage.ts @@ -11,6 +11,9 @@ export function mutateStartStage({ progressIncrement?: number; progress?: number; }) { - task.stageTargetProgress = Math.min(1.0, progress !== undefined ? progress : task.progress + progressIncrement); + task.stageTargetProgress = Math.min( + 1.0, + progress !== undefined ? progress : task.progress + progressIncrement, + ); task.executionStage = name; } diff --git a/src/tasks/mutators/mutateStopExecution.ts b/src/tasks/mutators/mutateStopExecution.ts index 53887be..e01b7d2 100644 --- a/src/tasks/mutators/mutateStopExecution.ts +++ b/src/tasks/mutators/mutateStopExecution.ts @@ -1,5 +1,5 @@ -import { TaskContext } from '../TaskContext'; import { FINISHED_STAGE_NAME } from '../stageNames'; +import { TaskContext } from '../TaskContext'; export async function mutateStopExecution( task: TaskContext, diff --git a/src/utils/MultiSet.ts b/src/utils/MultiSet.ts index 5174d6a..459781c 100644 --- a/src/utils/MultiSet.ts +++ b/src/utils/MultiSet.ts @@ -40,8 +40,8 @@ export class MultiSet { // eslint-disable-next-line eqeqeq if (v != null && v > 0) { return v; - } else { - return 0; } + + return 0; } } diff --git a/src/utils/calculateAndFormatExecutionTime.ts b/src/utils/calculateAndFormatExecutionTime.ts index 054dcb3..0193ec0 100644 --- a/src/utils/calculateAndFormatExecutionTime.ts +++ b/src/utils/calculateAndFormatExecutionTime.ts @@ -1,10 +1,17 @@ // Function to calculate and format the execution time in HH:mm:SS format -export function calculateAndFormatExecutionTime(executionDuration: number): string { +export function calculateAndFormatExecutionTime( + executionDuration: number, +): string { // Function to format the time parts in HH:mm:SS format - function formatExecutionTime(hours: number, minutes: number, seconds: number): string { + function formatExecutionTime( + hours: number, + minutes: number, + seconds: number, + ): string { const paddedHours = hours.toString().padStart(2, '0'); const paddedMinutes = minutes.toString().padStart(2, '0'); const paddedSeconds = seconds.toFixed(0).padStart(2, '0'); + return `${paddedHours}:${paddedMinutes}:${paddedSeconds}`; } diff --git a/src/utils/code/comments.ts b/src/utils/code/comments.ts index 56b2fef..d32d807 100644 --- a/src/utils/code/comments.ts +++ b/src/utils/code/comments.ts @@ -27,5 +27,6 @@ export function getCommentForLanguage(language: string, content: string) { export function canAddComment(language: string): boolean { // Add new language cases here if necessary const unsupportedLanguages = ['json']; + return !unsupportedLanguages.includes(language); } diff --git a/src/utils/code/fuzzyReplaceText.ts b/src/utils/code/fuzzyReplaceText.ts index a38016b..93a08fa 100644 --- a/src/utils/code/fuzzyReplaceText.ts +++ b/src/utils/code/fuzzyReplaceText.ts @@ -1,22 +1,45 @@ -import { applyIndent, codeStringSimilarity, equalsStringSimilarity, levenshteinDistanceSimilarity, removeIndent } from '../string/stringUtils'; +import { + applyIndent, + codeStringSimilarity, + equalsStringSimilarity, + levenshteinDistanceSimilarity, + removeIndent, +} from '../string/stringUtils'; import { stripAllComments } from './stripAllComments'; -export type SingleLineSimilarityFunction = (original: string, replacement: string) => number; -export type MultiLineSimilarityFunction = (original: string[], replacement: string[]) => number; +export type SingleLineSimilarityFunction = ( + original: string, + replacement: string, +) => number; +export type MultiLineSimilarityFunction = ( + original: string[], + replacement: string[], +) => number; const DEFAULT_SIMILARITY_THRESHOLD = 0.75; -function fuzzyGetIndentationDifference(currentLine: string, replaceTextLine: string, similarityFunction: (a: string, b: string) => number) { +function fuzzyGetIndentationDifference( + currentLine: string, + replaceTextLine: string, + similarityFunction: (a: string, b: string) => number, +) { return { confidence: similarityFunction(currentLine.trim(), replaceTextLine.trim()), indent: getIndentationDifference(currentLine, replaceTextLine), }; } -function getIndentationDifference(currentLine: string, replaceTextLine: string) { +function getIndentationDifference( + currentLine: string, + replaceTextLine: string, +) { const currentIndent = currentLine.match(/(^\s*)/)?.[1] || ''; const replaceTextIndent = replaceTextLine.match(/(^\s*)/)?.[1] || ''; - const indentDifference = currentIndent.slice(0, currentIndent.length - replaceTextIndent.length); + const indentDifference = currentIndent.slice( + 0, + currentIndent.length - replaceTextIndent.length, + ); + return indentDifference; } @@ -36,7 +59,8 @@ function ignoreLeadingAndTrailingWhiteSpaceSimilariryunction( const POSTFIX_WEIGTH = 0.05; return ( - contentSimilarityFunction(currentLine.trim(), replaceTextLine.trim()) * CONTENT_WEIGTH + + contentSimilarityFunction(currentLine.trim(), replaceTextLine.trim()) * + CONTENT_WEIGTH + equalsStringSimilarity(currentPrefix, replaceTextPrefix) * PREFIX_WEIGTH + equalsStringSimilarity(currentPostfix, replaceTextPostfix) * POSTFIX_WEIGTH ); @@ -57,10 +81,18 @@ function normalizeIndent(slice: string[]) { /** * Try to guess identation from the current slice and replaceTextLines */ -function findIndentationDifference(currentSlice: string[], replaceTextLines: string[], similarityFunction: (a: string, b: string) => number) { +function findIndentationDifference( + currentSlice: string[], + replaceTextLines: string[], + similarityFunction: (a: string, b: string) => number, +) { const indentationDifferences: number[] = []; - for (let i = 0; i < Math.min(currentSlice.length, replaceTextLines.length); i++) { + for ( + let i = 0; + i < Math.min(currentSlice.length, replaceTextLines.length); + i++ + ) { const replaceLine = replaceTextLines[i]; const replaceIndentation = replaceLine.match(/^\s*/)?.[0].length || 0; const currentLine = currentSlice[i]; @@ -77,6 +109,7 @@ function findIndentationDifference(currentSlice: string[], replaceTextLines: str resultLines.push(indentation); } resultLines.sort((a, b) => b.length - a.length); + return resultLines; } @@ -84,7 +117,10 @@ export function exactLinesSimilarityAndMap( original: string[], find: string[], lineSimilarityFunction: SingleLineSimilarityFunction, - mapFindLine: (original: string | undefined, findLine: string) => string = (original, findLine) => findLine, + mapFindLine: (original: string | undefined, findLine: string) => string = ( + original, + findLine, + ) => findLine, ): { similiarity: number; mappedFind: string[] } { const mappedFind: string[] = []; let originalLine = 0; @@ -96,13 +132,15 @@ export function exactLinesSimilarityAndMap( const baseSkippedValue = 0.02; const scalableSkippedValue = 0.98; const skipScaling = 1 - 1 / (1 + line.trim().length); + return baseSkippedValue + scalableSkippedValue * skipScaling; } const options = [ { condition: () => originalLine < original.length && findLine < find.length, - simiarity: () => lineSimilarityFunction(original[originalLine], find[findLine]), + simiarity: () => + lineSimilarityFunction(original[originalLine], find[findLine]), skippedOriginalLines: () => 0, skippedFindLines: () => 0, apply: () => { @@ -116,12 +154,23 @@ export function exactLinesSimilarityAndMap( const skippedOriginalLines = 1; return { - condition: () => originalLine + skippedOriginalLines < original.length && findLine < find.length, - simiarity: () => lineSimilarityFunction(original[originalLine + skippedOriginalLines], find[findLine]), + condition: () => + originalLine + skippedOriginalLines < original.length && + findLine < find.length, + simiarity: () => + lineSimilarityFunction( + original[originalLine + skippedOriginalLines], + find[findLine], + ), skippedOriginalLines: () => skippedOriginalLines, skippedFindLines: () => 0, apply: () => { - mappedFind.push(mapFindLine(original[originalLine + skippedOriginalLines], find[findLine])); + mappedFind.push( + mapFindLine( + original[originalLine + skippedOriginalLines], + find[findLine], + ), + ); originalLine++; findLine++; @@ -135,15 +184,26 @@ export function exactLinesSimilarityAndMap( const skippedFindLines = 1; return { - condition: () => originalLine < original.length && findLine + skippedFindLines < find.length, - simiarity: () => lineSimilarityFunction(original[originalLine], find[findLine + skippedFindLines]), + condition: () => + originalLine < original.length && + findLine + skippedFindLines < find.length, + simiarity: () => + lineSimilarityFunction( + original[originalLine], + find[findLine + skippedFindLines], + ), skippedOriginalLines: () => 0, skippedFindLines: () => skippedFindLines, apply: () => { for (let i = 0; i < skippedFindLines; i++) { mappedFind.push(mapFindLine(undefined, find[findLine + i])); } - mappedFind.push(mapFindLine(original[originalLine], find[findLine + skippedFindLines])); + mappedFind.push( + mapFindLine( + original[originalLine], + find[findLine + skippedFindLines], + ), + ); originalLine++; findLine++; @@ -154,7 +214,8 @@ export function exactLinesSimilarityAndMap( }; })(), { - condition: () => originalLine < original.length && findLine >= find.length, + condition: () => + originalLine < original.length && findLine >= find.length, simiarity: () => 0, skippedOriginalLines: () => 1, skippedFindLines: () => 0, @@ -163,7 +224,8 @@ export function exactLinesSimilarityAndMap( }, }, { - condition: () => originalLine >= original.length && findLine < find.length, + condition: () => + originalLine >= original.length && findLine < find.length, simiarity: () => 0, skippedOriginalLines: () => 0, skippedFindLines: () => 1, @@ -177,6 +239,7 @@ export function exactLinesSimilarityAndMap( let similaritySum = 0; let linesSkipped = 0; + // eslint-disable-next-line no-constant-condition while (true) { let bestOption; let bestSimialrity = Number.MIN_SAFE_INTEGER; @@ -200,11 +263,19 @@ export function exactLinesSimilarityAndMap( break; } - for (let orgIndex = 0; orgIndex < bestOption.skippedOriginalLines(); orgIndex++) { + for ( + let orgIndex = 0; + orgIndex < bestOption.skippedOriginalLines(); + orgIndex++ + ) { linesSkipped += lineSkippedValue(original[originalLine + orgIndex]); } - for (let findIndex = 0; findIndex < bestOption.skippedFindLines(); findIndex++) { + for ( + let findIndex = 0; + findIndex < bestOption.skippedFindLines(); + findIndex++ + ) { linesSkipped += lineSkippedValue(find[findLine + findIndex]); } @@ -220,19 +291,32 @@ export function exactLinesSimilarityAndMap( return { similiarity: 0, mappedFind }; } - const averageSimilarity = originalSimilarityLines === 0 ? 1 : similaritySum / originalSimilarityLines; - const noSkipRatio = (3 * (1 - linesSkipped / original.length) + 1 * (1 / (1 + linesSkipped))) / 4; + const averageSimilarity = + originalSimilarityLines === 0 ? 1 : similaritySum / originalSimilarityLines; + const noSkipRatio = + (3 * (1 - linesSkipped / original.length) + 1 * (1 / (1 + linesSkipped))) / + 4; return { similiarity: averageSimilarity * noSkipRatio, mappedFind }; } -export const coreSimilarityFunction = (original: string[], replacement: string[]) => { +export const coreSimilarityFunction = ( + original: string[], + replacement: string[], +) => { if (original.join('\n') === replacement.join('\n')) { return 1; } - const similartyWithWsDistance = exactLinesSimilarityAndMap(original, replacement, (a, b) => - ignoreLeadingAndTrailingWhiteSpaceSimilariryunction(a, b, codeStringSimilarity), + const similartyWithWsDistance = exactLinesSimilarityAndMap( + original, + replacement, + (a, b) => + ignoreLeadingAndTrailingWhiteSpaceSimilariryunction( + a, + b, + codeStringSimilarity, + ), ).similiarity; const similarityNotIgnoringWhitespace = exactLinesSimilarityAndMap( @@ -241,9 +325,15 @@ export const coreSimilarityFunction = (original: string[], replacement: string[] levenshteinDistanceSimilarity, ).similiarity; - const core = Math.max(similartyWithWsDistance, similarityNotIgnoringWhitespace); + const core = Math.max( + similartyWithWsDistance, + similarityNotIgnoringWhitespace, + ); - const similarity = 0.6 * core + 0.2 * similartyWithWsDistance + 0.2 * similarityNotIgnoringWhitespace; + const similarity = + 0.6 * core + + 0.2 * similartyWithWsDistance + + 0.2 * similarityNotIgnoringWhitespace; if (isNaN(similarity)) { throw new Error('similarity is NaN'); @@ -251,12 +341,18 @@ export const coreSimilarityFunction = (original: string[], replacement: string[] { // Just for testing - // eslint-disable-next-line @typescript-eslint/no-unused-vars - const similartyWithWsDistance = exactLinesSimilarityAndMap(original, replacement, (a, b) => - ignoreLeadingAndTrailingWhiteSpaceSimilariryunction(a, b, codeStringSimilarity), + + const similartyWithWsDistance = exactLinesSimilarityAndMap( + original, + replacement, + (a, b) => + ignoreLeadingAndTrailingWhiteSpaceSimilariryunction( + a, + b, + codeStringSimilarity, + ), ).similiarity; - // eslint-disable-next-line @typescript-eslint/no-unused-vars const similarityNotIgnoringWhitespace = exactLinesSimilarityAndMap( normalizeIndent(stripAllComments(original)), normalizeIndent(stripAllComments(replacement)), @@ -292,12 +388,23 @@ export async function fuzzyFindText({ let maxSimilarityLineStartIndex = -1; let maxSimilarityLineEndIndex = -1; - const minLinesToReplace = Math.max(0, findTextLines.length - lineNumTolerance); + const minLinesToReplace = Math.max( + 0, + findTextLines.length - lineNumTolerance, + ); - for (let start = 0; start < currentCodeLines.length - minLinesToReplace; start++) { + for ( + let start = 0; + start < currentCodeLines.length - minLinesToReplace; + start++ + ) { let maxLinesToReplace = minLinesToReplace + 3; // This will get enlarged let lastSimilarity = 0; - for (let end = start + minLinesToReplace; end <= Math.min(currentCodeLines.length, start + maxLinesToReplace); end++) { + for ( + let end = start + minLinesToReplace; + end <= Math.min(currentCodeLines.length, start + maxLinesToReplace); + end++ + ) { const currentSlice = currentCodeLines.slice(start, end); const similarity = similarityFunction(currentSlice, findTextLines); @@ -315,7 +422,9 @@ export async function fuzzyFindText({ } } - await new Promise((resolve) => setTimeout(resolve, 1)); + await new Promise((resolve) => { + setTimeout(resolve, 1); + }); } return { @@ -357,14 +466,17 @@ export async function fuzzyReplaceTextInner({ const findTextLines = findText.split('\n'); const withTextLines = withText.split('\n'); - function mapFindWithIndent(originalLine: string | undefined, searchLine: string) { + function mapFindWithIndent( + originalLine: string | undefined, + searchLine: string, + ) { if (originalLine === undefined) { return lastIndent + searchLine; - } else { - const indentDiff = getIndentationDifference(originalLine, searchLine); - lastIndent = indentDiff; - return indentDiff + searchLine; } + const indentDiff = getIndentationDifference(originalLine, searchLine); + lastIndent = indentDiff; + + return indentDiff + searchLine; } let lastIndent = ''; @@ -382,26 +494,43 @@ export async function fuzzyReplaceTextInner({ const withTextUpToFirstNonEmptyLine = withTextLines.slice(0, 1); const withTextRest = withTextLines.slice(1); - const indentAdjustedFindLinesUpToFirstNonEmptyLine = indentAdjustedFindLines.slice(0, 1); + const indentAdjustedFindLinesUpToFirstNonEmptyLine = + indentAdjustedFindLines.slice(0, 1); const indentAdjustedFindLinesRest = indentAdjustedFindLines.slice(1); - const indentAdjustedWithTextupToFirstNonEmptyLine = exactLinesSimilarityAndMap( - indentAdjustedFindLinesUpToFirstNonEmptyLine, - withTextUpToFirstNonEmptyLine, - (a, b) => levenshteinDistanceSimilarity(a, b), - mapFindWithIndent, - ).mappedFind; - - const overalIndentDifference = findIndentationDifference(currentSlice, withTextLines, equalsStringSimilarity) || ''; - const indentAdjustedWithTextRest = applyIndent(withTextRest, overalIndentDifference); - const indentAdjustedWithLines = [...indentAdjustedWithTextupToFirstNonEmptyLine, ...indentAdjustedWithTextRest]; + const indentAdjustedWithTextupToFirstNonEmptyLine = + exactLinesSimilarityAndMap( + indentAdjustedFindLinesUpToFirstNonEmptyLine, + withTextUpToFirstNonEmptyLine, + (a, b) => levenshteinDistanceSimilarity(a, b), + mapFindWithIndent, + ).mappedFind; + + const overalIndentDifference = + findIndentationDifference( + currentSlice, + withTextLines, + equalsStringSimilarity, + ) || ''; + const indentAdjustedWithTextRest = applyIndent( + withTextRest, + overalIndentDifference, + ); + const indentAdjustedWithLines = [ + ...indentAdjustedWithTextupToFirstNonEmptyLine, + ...indentAdjustedWithTextRest, + ]; const adjustedWithText = indentAdjustedWithLines.join('\n'); const preChange = currentCodeLines.slice(0, startIndex).join('\n'); const postChange = currentCodeLines.slice(endIndex).join('\n'); - return [preChange + (preChange ? '\n' : ''), adjustedWithText, (postChange ? '\n' : '') + postChange]; + return [ + preChange + (preChange ? '\n' : ''), + adjustedWithText, + (postChange ? '\n' : '') + postChange, + ]; } } diff --git a/src/utils/code/stripAllComments.ts b/src/utils/code/stripAllComments.ts index 81d4b60..19e11af 100644 --- a/src/utils/code/stripAllComments.ts +++ b/src/utils/code/stripAllComments.ts @@ -13,7 +13,8 @@ export function stripAllComments(code: string[]): string[] { let foundComment = false; for (let li = 0; li < line.length; li++) { - const startsJavascriptLineComment = !inBlockComment && line[li] === '/' && line[li + 1] === '/'; + const startsJavascriptLineComment = + !inBlockComment && line[li] === '/' && line[li + 1] === '/'; const startsPythonLineComment = !inBlockComment && line[li] === '#'; if (startsJavascriptLineComment || startsPythonLineComment) { @@ -21,10 +22,18 @@ export function stripAllComments(code: string[]): string[] { break; // This is a single line comment } - const startsJavascriptBlockComment = !inBlockComment && line[li] === '/' && line[li + 1] === '*'; - const startsPythonBlockComment = !inBlockComment && (line.substring(li, li + 3) === "'''" || line.substring(li, li + 3) === '"""'); - const endsJavascriptBlockComment = inBlockComment && line[li] === '*' && line[li + 1] === '/'; - const endsPythonBlockComment = inBlockComment && (line.substring(li, li + 3) === "'''" || line.substring(li, li + 3) === '"""'); + const startsJavascriptBlockComment = + !inBlockComment && line[li] === '/' && line[li + 1] === '*'; + const startsPythonBlockComment = + !inBlockComment && + (line.substring(li, li + 3) === "'''" || + line.substring(li, li + 3) === '"""'); + const endsJavascriptBlockComment = + inBlockComment && line[li] === '*' && line[li + 1] === '/'; + const endsPythonBlockComment = + inBlockComment && + (line.substring(li, li + 3) === "'''" || + line.substring(li, li + 3) === '"""'); if (startsJavascriptBlockComment) { foundComment = true; diff --git a/src/utils/isZodString.ts b/src/utils/isZodString.ts index a6dc7c2..d46ad8f 100644 --- a/src/utils/isZodString.ts +++ b/src/utils/isZodString.ts @@ -2,5 +2,6 @@ import { z } from 'zod'; export function isZodString(schema: z.ZodType): boolean { const parseResult = schema.safeParse(''); + return parseResult.success; } diff --git a/src/utils/playSound.ts b/src/utils/playSound.ts index 171ce53..c5ed1a6 100644 --- a/src/utils/playSound.ts +++ b/src/utils/playSound.ts @@ -1,26 +1,32 @@ -import * as path from 'path'; -import { PathLike } from 'fs'; import { exec } from 'child_process'; +import { PathLike } from 'fs'; +import path from 'path'; +import { promisify } from 'util'; -// eslint-disable-next-line @typescript-eslint/no-var-requires -const execPromise = require('util').promisify(exec); +const execPromise = promisify(exec); /* AIX PLAY COMMAND */ -const aixPlayCommand = (filePath: PathLike, volume: number) => `aplay \"${filePath}\" -v ${volume}`; +const aixPlayCommand = (filePath: PathLike, volume: number) => + `aplay \"${filePath}\" -v ${volume}`; /* DARWIN PLAY COMMAND */ -const darwinPlayCommand = (filePath: PathLike, volume: number) => `afplay \"${filePath}\" -v ${volume}`; +const darwinPlayCommand = (filePath: PathLike, volume: number) => + `afplay \"${filePath}\" -v ${volume}`; /* FREEBSD PLAY COMMAND */ -const freebsdPlayCommand = (filePath: PathLike, volume: number) => `play -v ${volume} \"${filePath}\"`; +const freebsdPlayCommand = (filePath: PathLike, volume: number) => + `play -v ${volume} \"${filePath}\"`; /* LINUX PLAY COMMAND */ -const linuxPlayCommand = (filePath: PathLike, volume: number) => `paplay --volume=${Math.round(volume * 32768)} \"${filePath}\"`; +const linuxPlayCommand = (filePath: PathLike, volume: number) => + `paplay --volume=${Math.round(volume * 32768)} \"${filePath}\"`; /* OPENBSD PLAY COMMAND */ -const openbsdPlayCommand = (filePath: PathLike, volume: number) => `aucat -i \"${filePath}\" -v ${volume}`; +const openbsdPlayCommand = (filePath: PathLike, volume: number) => + `aucat -i \"${filePath}\" -v ${volume}`; /* SUNOS PLAY COMMAND */ -const sunosPlayCommand = (filePath: PathLike, volume: number) => `audioplay \"${filePath}\" -v ${volume}`; +const sunosPlayCommand = (filePath: PathLike, volume: number) => + `audioplay \"${filePath}\" -v ${volume}`; /* WIN32 PLAY COMMAND */ const addPresentationCore = `Add-Type -AssemblyName presentationCore;`; @@ -30,7 +36,9 @@ const playAudio = `$player.Play();`; const stopAudio = `Start-Sleep 1; Start-Sleep -s $player.NaturalDuration.TimeSpan.TotalSeconds;Exit;`; const win32PlayCommand = (filePath: PathLike, volume: number) => - `powershell -c ${addPresentationCore} ${createMediaPlayer} ${loadAudioFile(filePath)} $player.Volume = ${volume}; ${playAudio} ${stopAudio}`; + `powershell -c ${addPresentationCore} ${createMediaPlayer} ${loadAudioFile( + filePath, + )} $player.Volume = ${volume}; ${playAudio} ${stopAudio}`; async function playSound(path: string, volume = 0.5) { /** @@ -38,7 +46,8 @@ async function playSound(path: string, volume = 0.5) { * Mac: afplay's volume is from 0 to 255, default is 1. However, volume > 2 usually result in distortion. * Therefore, it is better to limit the volume on Mac, and set a common scale of 0 to 1 for simplicity */ - const volumeAdjustedByOS = process.platform === 'darwin' ? Math.min(2, volume * 2) : volume; + const volumeAdjustedByOS = + process.platform === 'darwin' ? Math.min(2, volume * 2) : volume; if (!process.platform) { throw Error('OS not detected'); @@ -73,11 +82,7 @@ async function playSound(path: string, volume = 0.5) { break; } - try { - await execPromise(playCommand, { windowsHide: true }); - } catch (err) { - throw err; - } + await execPromise(playCommand, { windowsHide: true }); } let globalExtensionPath: string; diff --git a/src/utils/random/getRandomIndex.ts b/src/utils/random/getRandomIndex.ts index 455b55b..1da568d 100644 --- a/src/utils/random/getRandomIndex.ts +++ b/src/utils/random/getRandomIndex.ts @@ -4,5 +4,6 @@ export function getRandomIndex(arr: T[], random = Math.random): number { if (arr.length === 0) { throw new Error('Empty array'); } + return getRandomInt(0, arr.length - 1, random); } diff --git a/src/utils/random/getRandomInt.ts b/src/utils/random/getRandomInt.ts index 6dd94d0..a886a7e 100644 --- a/src/utils/random/getRandomInt.ts +++ b/src/utils/random/getRandomInt.ts @@ -1,5 +1,6 @@ export function getRandomInt(_min: number, _max: number, random = Math.random) { const min = Math.ceil(_min); const max = Math.floor(_max); + return Math.floor(random() * (max - min + 1)) + min; } diff --git a/src/utils/random/getRandomSubarray.ts b/src/utils/random/getRandomSubarray.ts index 71ba361..6522854 100644 --- a/src/utils/random/getRandomSubarray.ts +++ b/src/utils/random/getRandomSubarray.ts @@ -1,10 +1,15 @@ import { shuffleArray } from './shuffleArray'; -export function getRandomSubarray(arr: T[], size: number, uniqueKey?: (item: T) => string, random = Math.random): T[] { +export function getRandomSubarray( + arr: T[], + size: number, + uniqueKey?: (item: T) => string, + random = Math.random, +): T[] { const shuffled = arr.slice(0); shuffleArray(shuffled, random); - if (uniqueKey != null) { + if (uniqueKey) { const r: T[] = []; const usedDict: { [key: string]: boolean } = {}; @@ -18,7 +23,7 @@ export function getRandomSubarray(arr: T[], size: number, uniqueKey?: (item: } return r; - } else { - return shuffled.slice(0, size); } + + return shuffled.slice(0, size); } diff --git a/src/utils/random/uniqueWeightedRandomElements.ts b/src/utils/random/uniqueWeightedRandomElements.ts index 305c0ed..92a6023 100644 --- a/src/utils/random/uniqueWeightedRandomElements.ts +++ b/src/utils/random/uniqueWeightedRandomElements.ts @@ -17,7 +17,9 @@ export function uniqueWeightedRandomElements( } if (ret.length !== count) { - throw new Error('Something wrong with the options, unable to generate viable result'); + throw new Error( + 'Something wrong with the options, unable to generate viable result', + ); } return ret; diff --git a/src/utils/random/weightedRandomElement.ts b/src/utils/random/weightedRandomElement.ts index a0b8161..2042d8c 100644 --- a/src/utils/random/weightedRandomElement.ts +++ b/src/utils/random/weightedRandomElement.ts @@ -4,8 +4,13 @@ import { weightedRandomIndex } from './weightedRandomIndex'; /** * */ -export function weightedRandomElement(options: T[], attr: KeyOfType, random = Math.random): T { +export function weightedRandomElement( + options: T[], + attr: KeyOfType, + random = Math.random, +): T { if (options.length === 0) throw new Error('Empty options'); const index = weightedRandomIndex(options, attr, random); + return options[index]; } diff --git a/src/utils/random/weightedRandomElements.ts b/src/utils/random/weightedRandomElements.ts index 77e88a4..31c6633 100644 --- a/src/utils/random/weightedRandomElements.ts +++ b/src/utils/random/weightedRandomElements.ts @@ -1,7 +1,12 @@ import { KeyOfType } from '../typescript/KeyOfType'; import { weightedRandomElement } from './weightedRandomElement'; -export function weightedRandomElements(options: T[], attr: KeyOfType, _count: number, random = Math.random): T[] { +export function weightedRandomElements( + options: T[], + attr: KeyOfType, + _count: number, + random = Math.random, +): T[] { const ret: T[] = []; const count = Math.max(0, _count); @@ -10,7 +15,9 @@ export function weightedRandomElements(options: T[ } if (ret.length !== count) { - throw new Error('Something wrong with the options, unable to generate viable result'); + throw new Error( + 'Something wrong with the options, unable to generate viable result', + ); } return ret; diff --git a/src/utils/random/weightedRandomIndex.ts b/src/utils/random/weightedRandomIndex.ts index 2caa53b..3ae29c8 100644 --- a/src/utils/random/weightedRandomIndex.ts +++ b/src/utils/random/weightedRandomIndex.ts @@ -1,9 +1,15 @@ import { KeyOfType } from '../typescript/KeyOfType'; -export function weightedRandomIndex(options: T[], attr: KeyOfType, random = Math.random): number { +export function weightedRandomIndex( + options: T[], + attr: KeyOfType, + random = Math.random, +): number { const weights: number[] = []; - for (let i = 0; i < options.length; i++) weights[i] = Math.max(0, options[i][attr] as number) + (weights[i - 1] || 0); + for (let i = 0; i < options.length; i++) + weights[i] = + Math.max(0, options[i][attr] as number) + (weights[i - 1] || 0); const r = random() * weights[weights.length - 1]; @@ -11,7 +17,9 @@ export function weightedRandomIndex(options: T[], attr: KeyOfType, for (i = 0; i < weights.length; i++) if (weights[i] > r) break; if (i >= options.length) { - throw new Error('Something wrong with the options, unable to generate viable result'); + throw new Error( + 'Something wrong with the options, unable to generate viable result', + ); } return i; diff --git a/src/utils/string/decomposeMarkdownString.ts b/src/utils/string/decomposeMarkdownString.ts index 292738f..617ebca 100644 --- a/src/utils/string/decomposeMarkdownString.ts +++ b/src/utils/string/decomposeMarkdownString.ts @@ -1,6 +1,9 @@ import { getCommentForLanguage } from '../code/comments'; -export function splitCommentIntoLines(comment: string, maxChars = 80): string[] { +export function splitCommentIntoLines( + comment: string, + maxChars = 80, +): string[] { const finalLines: string[] = []; const lines = comment.split('\n'); @@ -15,11 +18,15 @@ export function splitCommentIntoLines(comment: string, maxChars = 80): string[] words.forEach((word) => { // Handle the case when a single word is longer than maxChars if (word.length > maxChars) { - const subStrings = word.match(new RegExp(`.{1,${maxChars}}`, 'g')) || []; + const subStrings = + word.match(new RegExp(`.{1,${maxChars}}`, 'g')) || []; subStrings.forEach((subString) => finalLines.push(subString)); } // Handle the case when adding the word doesn't exceed maxChars - else if (currentLine.length + word.length + (currentLine.length > 0 ? 1 : 0) <= maxChars) { + else if ( + currentLine.length + word.length + (currentLine.length > 0 ? 1 : 0) <= + maxChars + ) { currentLine += currentLine.length > 0 ? ' ' : ''; currentLine += word; } @@ -44,10 +51,13 @@ export function splitCommentIntoLines(comment: string, maxChars = 80): string[] * @param {string} languageId The language ID of the document. * @returns {string[]} An array of string parts, formatted as comments and code blocks. */ -export function decomposeMarkdownString(markdownString: string, languageId: string): string[] { +export function decomposeMarkdownString( + markdownString: string, + languageId: string, +): string[] { const lines = markdownString.split('\n'); let inCodeBlock = false; - // eslint-disable-next-line @typescript-eslint/no-unused-vars + let codeLanguage = ''; const decomposedStringParts: string[] = []; @@ -83,7 +93,7 @@ export function decomposeMarkdownString(markdownString: string, languageId: stri * @param {string[]} lines The input array of lines. * @returns {string[]} The output array with empty lines removed from the beginning and end. */ -// eslint-disable-next-line @typescript-eslint/no-unused-vars + function trimEmptyLines(lines: string[]): string[] { let start = 0; let end = lines.length - 1; @@ -111,13 +121,22 @@ function trimEmptyLines(lines: string[]): string[] { * @param {string[]} decomposedStringParts Array holding the decomposed markdown string parts. * @returns {void} */ -function dumpCommentBuffer(languageId: string, commentBuffer: string[], decomposedStringParts: string[]): void { +function dumpCommentBuffer( + languageId: string, + commentBuffer: string[], + decomposedStringParts: string[], +): void { if (commentBuffer.length > 0) { const trimmedCommentLines = commentBuffer; //check if that was needed: trimEmptyLines( - const splitComment = splitCommentIntoLines(trimmedCommentLines.join('\n')).join('\n').trim(); + const splitComment = splitCommentIntoLines(trimmedCommentLines.join('\n')) + .join('\n') + .trim(); if (splitComment.length > 0) { - const languageSpecificComment = getCommentForLanguage(languageId, splitComment); + const languageSpecificComment = getCommentForLanguage( + languageId, + splitComment, + ); decomposedStringParts.push(languageSpecificComment); } diff --git a/src/utils/string/formatPrompt.ts b/src/utils/string/formatPrompt.ts index f9b4149..d8f39aa 100644 --- a/src/utils/string/formatPrompt.ts +++ b/src/utils/string/formatPrompt.ts @@ -43,5 +43,6 @@ export function formatPrompt(prompt: string) { // Remove the same amount of indentation from all lines const formattedLines = lines.map((line) => line.slice(minIndentation)); + return formattedLines.join('\n'); } diff --git a/src/utils/string/stringUtils.ts b/src/utils/string/stringUtils.ts index 97ea5a7..71dac99 100644 --- a/src/utils/string/stringUtils.ts +++ b/src/utils/string/stringUtils.ts @@ -1,12 +1,19 @@ -export function commonStringEnd(commonIndent: string, lineIndent: string): string { +export function commonStringEnd( + commonIndent: string, + lineIndent: string, +): string { let commonEnd = ''; for (let i = 0; i < Math.min(commonIndent.length, lineIndent.length); i++) { - if (commonIndent[commonIndent.length - i - 1] === lineIndent[lineIndent.length - i - 1]) { + if ( + commonIndent[commonIndent.length - i - 1] === + lineIndent[lineIndent.length - i - 1] + ) { commonEnd = commonIndent[commonIndent.length - i - 1] + commonEnd; } else { break; } } + return commonEnd; } @@ -19,6 +26,7 @@ export function commonStringStart(commonIndent: string, lineIndent: string) { break; } } + return commonStart; } @@ -39,16 +47,17 @@ export function commonStringEndArray(indents: string[]) { } export function removeIndent(slice: string[], indent?: string) { - if (indent === undefined) { + let indentCopy = indent; + if (indentCopy === undefined) { const indents = slice.map((line) => line.match(/(^\s*)/)?.[1] || ''); - indent = commonStringEndArray(indents); + indentCopy = commonStringEndArray(indents); } - if (indent === undefined) { + if (indentCopy === undefined) { return slice; } - return slice.map((line) => line.slice(indent?.length)); + return slice.map((line) => line.slice(indentCopy?.length)); } export function applyIndent(slice: string[], indent: string[] | string) { @@ -99,6 +108,7 @@ export function levenshteinDistanceSimilarity(a: string, b: string): number { if (len === 0) { return 1; } + return 1 - levenshteinDistance(a, b) / len; } diff --git a/src/utils/typescript/shouldNeverGetHere.ts b/src/utils/typescript/shouldNeverGetHere.ts index bc23171..b27914f 100644 --- a/src/utils/typescript/shouldNeverGetHere.ts +++ b/src/utils/typescript/shouldNeverGetHere.ts @@ -28,5 +28,7 @@ export function shouldNeverGetHere(value: never, noThrow?: boolean): never { return value; } - throw new Error(`Unhandled discriminated union member: ${JSON.stringify(value)}`); + throw new Error( + `Unhandled discriminated union member: ${JSON.stringify(value)}`, + ); } diff --git a/src/utils/utils.ts b/src/utils/utils.ts index a56562c..e66a549 100644 --- a/src/utils/utils.ts +++ b/src/utils/utils.ts @@ -1,4 +1,7 @@ export const sum = (array: T[], query?: (obj: T) => number): number => - query ? array.reduce((a, b) => a + query(b), 0) : (array as number[]).reduce((a, b) => a + b, 0); + query + ? array.reduce((a, b) => a + query(b), 0) + : (array as number[]).reduce((a, b) => a + b, 0); -export const withDefault = (value: T | null | undefined, defaultValue: T) => (value === null ? defaultValue : value); +export const withDefault = (value: T | null | undefined, defaultValue: T) => + value === null ? defaultValue : value;