Merge remote-tracking branch 'origin/ctrlk-diff-ui' into multiple-webviews

This commit is contained in:
Andrew 2024-10-25 22:31:44 -07:00
commit f4be80b724
2 changed files with 202 additions and 70 deletions

View file

@ -63,78 +63,79 @@ ${completedStr}
\`\`\`
`
// create a promise that can be awaited
let res: Res<CompetedReturn> = () => { }
const promise = new Promise<CompetedReturn>((resolve, reject) => { res = resolve })
const promise = new Promise<CompetedReturn>((resolve, reject) => {
// get the abort method
let _abort = () => { }
let did_abort = false
// get the abort method
let _abort = () => { }
let did_abort = false
// make LLM complete the file to include the diff
sendLLMMessage({
messages: [{ role: 'system', content: writeFileWithDiffInstructions, }, { role: 'user', content: promptContent, }],
onText: (tokenStr, deltaStr) => {
if (did_abort) return;
sendLLMMessage({
messages: [{ role: 'system', content: writeFileWithDiffInstructions, }, { role: 'user', content: promptContent, }],
onText: (tokenStr, deltaStr) => {
const fullCompletedStr = completedStr + deltaStr
if (did_abort) return;
// diff `originalFileStr` and `newFileStr`
const diffs = findDiffs(oldFileStr, fullCompletedStr)
const lastDiff = diffs[diffs.length - 1]
const oldLineAfterLastDiff = lastDiff.originalRange.end.line + 1
const newLineAfterLastDiff = lastDiff.range.end.line + 1
// diff `originalFileStr` and `newFileStr`
const diffs = findDiffs(oldFileStr, fullCompletedStr)
const lastDiff = diffs[diffs.length - 1]
const oldLineAfterLastDiff = lastDiff.originalEndLine + 1
const newLineAfterLastDiff = lastDiff.endLine + 1
// check if we've generated a diff
const didGenerateDiff = newLineAfterLastDiff > next
// check if we've generated a diff
const didGenerateDiff = newLineAfterLastDiff > next
// get the line we are currently generating `newCurrentLine`; make sure it never goes past the last diff we've generated
// - if `deltaStr` contains a diff, then _next = newLineAfterLastDiff - 1
// - if it does not contain a diff, then _next = next + deltaStr.split('\n').length - 1
const newCurrentLine = didGenerateDiff ? newLineAfterLastDiff - 1 : next + deltaStr.split('\n').length - 1
const oldCurrentLine = didGenerateDiff ? oldLineAfterLastDiff - 1 : oldNext + (newCurrentLine - next)
// get the line we are currently generating `newCurrentLine`; make sure it never goes past the last diff we've generated
// - if `deltaStr` contains a diff, then _next = newLineAfterLastDiff - 1
// - if it does not contain a diff, then _next = next + deltaStr.split('\n').length - 1
const newCurrentLine = didGenerateDiff ? newLineAfterLastDiff - 1 : next + deltaStr.split('\n').length - 1
const oldCurrentLine = didGenerateDiff ? oldLineAfterLastDiff - 1 : oldNext + (newCurrentLine - next)
// 1. Apply the changes and modify highlighting
// 1. Apply the changes and modify highlighting
applyCtrlLChangesToFile({ fileUri, newCurrentLine, oldCurrentLine, fullCompletedStr, oldFileStr })
applyCtrlLChangesToFile({ fileUri, newCurrentLine, oldCurrentLine, fullCompletedStr, oldFileStr })
// 2. Check for early stopping
// the conditions for early stopping are:
// - we have generated a diff
// - there is matchup with the original file after the diff
const isMatchupAfterDiff = fullCompletedStr.split('\n').slice(newLineAfterLastDiff).join('\n').length > NUM_MATCHUP_TOKENS
if (didGenerateDiff && isMatchupAfterDiff) {
// 2. Check for early stopping
// the conditions for early stopping are:
// - we have generated a diff
// - there is matchup with the original file after the diff
const isMatchupAfterDiff = fullCompletedStr.split('\n').slice(newLineAfterLastDiff).join('\n').length > NUM_MATCHUP_TOKENS
if (didGenerateDiff && isMatchupAfterDiff) {
// resolve the promise
res({ next: newCurrentLine + 1, oldNext: oldCurrentLine + 1, });
// resolve the promise
resolve({ next: newCurrentLine + 1, oldNext: oldCurrentLine + 1, });
// abort the LLM call
_abort()
did_abort = true
// abort the LLM call
_abort()
did_abort = true
} else {
} else {
}
}
},
onFinalMessage: (deltaStr) => {
},
onFinalMessage: (deltaStr) => {
const newCompletedStr = completedStr + deltaStr
const newCompletedStr = completedStr + deltaStr
applyCtrlLChangesToFile({ fileUri, newCurrentLine: Number.MAX_SAFE_INTEGER, oldCurrentLine: Number.MAX_SAFE_INTEGER, fullCompletedStr: newCompletedStr, oldFileStr, debug: 'FINAL' })
applyCtrlLChangesToFile({ fileUri, newCurrentLine: Number.MAX_SAFE_INTEGER, oldCurrentLine: Number.MAX_SAFE_INTEGER, fullCompletedStr: newCompletedStr, oldFileStr, debug: 'FINAL' })
res({ isFinished: true });
},
onError: (e) => {
res({ isFinished: true });
console.error('Error rewriting file with diff', e);
},
voidConfig,
setAbort: (a) => { setAbort(a); _abort = a; },
resolve({ isFinished: true });
},
onError: (e) => {
resolve({ isFinished: true });
console.error('Error rewriting file with diff', e);
},
voidConfig,
setAbort: (a) => { setAbort(a); _abort = a; },
})
})
return promise
}
@ -161,28 +162,27 @@ Return \`true\` if ANY part of the chunk should be modified, and \`false\` if it
`
// create new promise
let res: Res<boolean> = () => { }
const promise = new Promise<boolean>((resolve, reject) => { res = resolve })
const promise = new Promise<boolean>((resolve, reject) => {
// send message to LLM
sendLLMMessage({
messages: [{ role: 'system', content: searchDiffChunkInstructions, }, { role: 'user', content: promptContent, }],
onFinalMessage: (finalMessage) => {
// send message to LLM
sendLLMMessage({
messages: [{ role: 'system', content: searchDiffChunkInstructions, }, { role: 'user', content: promptContent, }],
onFinalMessage: (finalMessage) => {
const containsTrue = finalMessage
.slice(-10) // check for `true` in last 10 characters
.toLowerCase()
.includes('true')
const containsTrue = finalMessage
.slice(-10) // check for `true` in last 10 characters
.toLowerCase()
.includes('true')
res(containsTrue)
},
onError: (e) => {
res(false);
console.error('Error in shouldApplyDiff: ', e)
},
onText: () => { },
voidConfig,
setAbort,
resolve(containsTrue)
},
onError: (e) => {
resolve(false);
console.error('Error in shouldApplyDiff: ', e)
},
onText: () => { },
voidConfig,
setAbort,
})
})
// return the promise

View file

@ -6,6 +6,138 @@ import { diffLines } from 'diff';
import { BaseDiff } from '../common/shared_types';
// Andrew diff algo:
// import { diffLines, Change } from 'diff';
// export type SuggestedEdit = {
// // start/end of current file
// startLine: number;
// startCol: number;
// endLine: number;
// endCol: number;
// // start/end of original file
// originalStartLine: number,
// originalStartCol: number,
// originalEndLine: number,
// originalEndCol: number,
// type: 'insertion' | 'deletion' | 'edit',
// originalContent: string, // original content (originalfile[originalStart...originalEnd])
// newContent: string,
// }
// export function findDiffs(oldStr: string, newStr: string) {
// // an ordered list of every original line, line added to the new file, and line removed from the old file (order is unambiguous, think about it)
// const lineByLineChanges: Change[] = diffLines(oldStr, newStr);
// lineByLineChanges.push({ value: '' }) // add a dummy so we flush any streaks we haven't yet at the very end (!line.added && !line.removed)
// let oldFileLineNum: number = 0;
// let newFileLineNum: number = 0;
// let streakStartInNewFile: number | undefined = undefined
// let streakStartInOldFile: number | undefined = undefined
// let oldStrLines = oldStr.split('\n')
// let newStrLines = newStr.split('\n')
// const replacements: SuggestedEdit[] = []
// for (let line of lineByLineChanges) {
// // no change on this line
// if (!line.added && !line.removed) {
// // do nothing
// // if we were on a streak of +s and -s, end it
// if (streakStartInNewFile !== undefined) {
// let type: 'edit' | 'insertion' | 'deletion' = 'edit'
// let startLine = streakStartInNewFile
// let endLine = newFileLineNum - 1 // don't include current line, the edit was up to this line but not including it
// let startCol = 0
// let endCol = Number.MAX_SAFE_INTEGER
// let originalStartLine = streakStartInOldFile!
// let originalEndLine = oldFileLineNum - 1 // don't include current line, the edit was up to this line but not including it
// let originalStartCol = 0
// let originalEndCol = Number.MAX_SAFE_INTEGER
// let newContent = newStrLines.slice(startLine, endLine + 1).join('\n')
// let originalContent = oldStrLines.slice(originalStartLine, originalEndLine + 1).join('\n')
// // if the range is empty, mark it as a deletion / insertion (both won't be true at once)
// // DELETION
// if (endLine === startLine - 1) {
// type = 'deletion'
// endLine = startLine
// startCol = 0
// endCol = 0
// newContent += '\n'
// }
// // INSERTION
// else if (originalEndLine === originalStartLine - 1) {
// type = 'insertion'
// originalEndLine = originalStartLine
// originalStartCol = 0
// originalEndCol = 0
// }
// const replacement: SuggestedEdit = {
// type,
// startLine, startCol, endLine, endCol, newContent,
// originalStartLine, originalStartCol, originalEndLine, originalEndCol, originalContent
// } as SuggestedEdit
// replacements.push(replacement)
// streakStartInNewFile = undefined
// streakStartInOldFile = undefined
// }
// oldFileLineNum += line.count ?? 0;
// newFileLineNum += line.count ?? 0;
// }
// // line was removed from old file
// else if (line.removed) {
// // if we weren't on a streak, start one on this current line num
// if (streakStartInNewFile === undefined) {
// streakStartInNewFile = newFileLineNum
// streakStartInOldFile = oldFileLineNum
// }
// oldFileLineNum += line.count ?? 0 // we processed the line so add 1
// }
// // line was added to new file
// else if (line.added) {
// // if we weren't on a streak, start one on this current line num
// if (streakStartInNewFile === undefined) {
// streakStartInNewFile = newFileLineNum
// streakStartInOldFile = oldFileLineNum
// }
// newFileLineNum += line.count ?? 0; // we processed the line so add 1
// }
// } // end for
// console.debug('Replacements', replacements)
// return replacements
// }
// const diffLinesOld = (text1: string, text2: string) => {
// var dmp = new diff_match_patch();