This commit is contained in:
Andrew Pareles 2025-02-13 23:54:22 -08:00
parent 343ee5eb94
commit 0bcd88dad6
6 changed files with 110 additions and 75 deletions

View file

@ -5,10 +5,10 @@
import { Emitter, Event } from '../../../../base/common/event.js';
import { Disposable } from '../../../../base/common/lifecycle.js';
import { URI } from '../../../../base/common/uri.js';
// import { URI } from '../../../../base/common/uri.js';
import { InstantiationType, registerSingleton } from '../../../../platform/instantiation/common/extensions.js';
import { createDecorator } from '../../../../platform/instantiation/common/instantiation.js';
import { IToolService, ToolService } from '../common/toolsService.js';
// import { IToolService, ToolService } from '../common/toolsService.js';
@ -54,7 +54,7 @@ class VoidFastApplyService extends Disposable implements IFastApplyService {
// state: ApplyState
constructor(
@IToolService private readonly toolService: ToolService
// @IToolService private readonly toolService: ToolService
) {
super()
@ -88,97 +88,97 @@ class VoidFastApplyService extends Disposable implements IFastApplyService {
// -iterate on syntax errors (all files can be changed from a syntax error, not just the one with the error)
private async _searchUsingAI({ searchClause }: { searchClause: string }) {
// private async _searchUsingAI({ searchClause }: { searchClause: string }) {
const relevantURIs: URI[] = []
const gatherPrompt = `\
asdasdas
`
const filterPrompt = `\
Is this file relevant?
`
// // const relevantURIs: URI[] = []
// // const gatherPrompt = `\
// // asdasdas
// // `
// // const filterPrompt = `\
// // Is this file relevant?
// // `
// optimizations (DO THESE LATER!!!!!!)
// if tool includes a uri in uriSet, skip it obviously
let uriSet = new Set<URI>()
// gather
let messages = []
while (true) {
const result = await new Promise((res, rej) => {
sendLLMMessage({
messages,
tools: ['search'],
onFinalMessage: ({ result: r, }) => {
res(r)
},
onError: (error) => {
rej(error)
}
})
})
// // // optimizations (DO THESE LATER!!!!!!)
// // // if tool includes a uri in uriSet, skip it obviously
// // let uriSet = new Set<URI>()
// // // gather
// // let messages = []
// // while (true) {
// // const result = await new Promise((res, rej) => {
// // sendLLMMessage({
// // messages,
// // tools: ['search'],
// // onFinalMessage: ({ result: r, }) => {
// // res(r)
// // },
// // onError: (error) => {
// // rej(error)
// // }
// // })
// // })
messages.push({ role: 'tool', content: turnToString(result) })
// // messages.push({ role: 'tool', content: turnToString(result) })
sendLLMMessage({
messages: { 'Output ': result },
onFinalMessage: (r) => {
// output is file1\nfile2\nfile3\n...
}
})
// // sendLLMMessage({
// // messages: { 'Output ': result },
// // onFinalMessage: (r) => {
// // // output is file1\nfile2\nfile3\n...
// // }
// // })
uriSet.add(...)
}
// // uriSet.add(...)
// // }
// writes
if (!replaceClause) return
// // // writes
// // if (!replaceClause) return
for (const uri of uriSet) {
// in future, batch these
applyWorkflow({ uri, applyStr: replaceClause })
}
// // for (const uri of uriSet) {
// // // in future, batch these
// // applyWorkflow({ uri, applyStr: replaceClause })
// // }
// while (true) {
// const result = new Promise((res, rej) => {
// sendLLMMessage({
// messages,
// tools: ['search'],
// onResult: (r) => {
// res(r)
// }
// })
// })
// // while (true) {
// // const result = new Promise((res, rej) => {
// // sendLLMMessage({
// // messages,
// // tools: ['search'],
// // onResult: (r) => {
// // res(r)
// // }
// // })
// // })
// messages.push(result)
// // messages.push(result)
// }
// // }
}
// }
private async _replaceUsingAI({ searchClause, replaceClause, relevantURIs }: { searchClause: string, replaceClause: string, relevantURIs: URI[] }) {
// private async _replaceUsingAI({ searchClause, replaceClause, relevantURIs }: { searchClause: string, replaceClause: string, relevantURIs: URI[] }) {
for (const uri of relevantURIs) {
// for (const uri of relevantURIs) {
uri
// uri
}
// }
// should I change this file?
// if so what changes to make?
// // should I change this file?
// // if so what changes to make?
// fast apply the changes
}
// // fast apply the changes
// }

View file

@ -3,7 +3,7 @@
* Licensed under the Apache License, Version 2.0. See LICENSE.txt for more information.
*--------------------------------------------------------------------------------------*/
import { DIVIDER, FINAL, ORIGINAL } from '../prompt/prompts'
import { DIVIDER, FINAL, ORIGINAL } from '../prompt/prompts.js'
class SurroundingsRemover {
readonly originalS: string

View file

@ -224,7 +224,7 @@ Please finish writing the new file by applying the change to the original file.
const aiRegex_computeReplacementsForFile_systemMessage = `\
export const aiRegex_computeReplacementsForFile_systemMessage = `\
You are a "search and replace" coding assistant.
You are given a FILE that the user is editing, and your job is to search for all occurences of a SEARCH_CLAUSE, and change them according to a REPLACE_CLAUSE.
@ -246,7 +246,7 @@ For example, if the user is asking you to "make this variable a better name", ma
- Make sure you give enough context in the code block to apply the changes to the correct location in the code`
const aiRegex_computeReplacementsForFile_userMessage = async ({ searchClause, replaceClause, fileURI, modelService }: { searchClause: string, replaceClause: string, fileURI: URI, modelService: IModelService }) => {
export const aiRegex_computeReplacementsForFile_userMessage = async ({ searchClause, replaceClause, fileURI, modelService }: { searchClause: string, replaceClause: string, fileURI: URI, modelService: IModelService }) => {
// we may want to do this in batches
const fileSelection: FileSelection = { type: 'File', fileURI, selectionStr: null, range: null }
@ -273,7 +273,7 @@ Please return the changes you want to make to the file in a codeblock, or return
// don't have to tell it it will be given the history; just give it to it
const aiRegex_search_systemMessage = `\
export const aiRegex_search_systemMessage = `\
You are a coding assistant that executes the SEARCH part of a user's search and replace query.
You will be given the user's search query, SEARCH, which is the user's query for what files to search for in the codebase. You may also be given the user's REPLACE query for additional context.

View file

@ -162,7 +162,7 @@ export class ToolService implements IToolService {
const data = await searchService.textSearch(query, CancellationToken.None);
const str = data.results.map(({ resource, results }) => resource)
return str
return str as any
},
}

View file

@ -53,11 +53,37 @@ export const sendAnthropicChat: _InternalSendLLMChatMessageFnType = ({ messages,
onText({ newText, fullText })
})
// can do tool use streaming
const toolCallOfIndex: { [index: string]: { name: string, args: string } } = {}
stream.on('streamEvent', e => {
if (e.type === 'content_block_start') {
if (e.content_block.type !== 'tool_use') return
const index = e.index
const tool = e.content_block
if (!toolCallOfIndex[index])
toolCallOfIndex[index] = { name: '', args: '' }
toolCallOfIndex[index].name += tool.name ?? ''
toolCallOfIndex[index].args += tool.input ?? ''
}
else if (e.type === 'content_block_delta') {
if (e.delta.type !== 'input_json_delta') return
toolCallOfIndex[e.index].args += e.delta.partial_json
}
// TODO!!!!!
// onText({})
})
// when we get the final message on this stream (or when error/fail)
stream.on('finalMessage', (claude_response) => {
stream.on('finalMessage', (response) => {
// stringify the response's content
const content = claude_response.content.map(c => c.type === 'text' ? c.text : c.type).join('\n');
onFinalMessage({ fullText: content })
const content = response.content.map(c => c.type === 'text' ? c.text : '').join('\n')
const tools = response.content.map(c => c.type === 'tool_use' ? { name: c.name, input: c.input } : null)
console.log("TOOLS!!!!", typeof tools[0]?.input, JSON.stringify(tools, null, 2))
onFinalMessage({ fullText: content, })
})
stream.on('error', (error) => {

View file

@ -121,6 +121,7 @@ export const sendOpenAIFIM: _InternalSendLLMFIMMessageFnType = ({ messages, onTe
export const sendOpenAIChat: _InternalSendLLMChatMessageFnType = ({ messages, onText, onFinalMessage, onError, settingsOfProvider, modelName, _setAborter, providerName }) => {
let fullText = ''
const toolCallOfIndex: { [index: string]: { name: string, args: string } } = {}
const openai: OpenAI = newOpenAI({ providerName, settingsOfProvider })
const options: OpenAI.Chat.Completions.ChatCompletionCreateParamsStreaming = {
@ -137,11 +138,19 @@ export const sendOpenAIChat: _InternalSendLLMChatMessageFnType = ({ messages, on
// when receive text
for await (const chunk of response) {
// tool call
for (const tool of chunk.choices[0]?.delta?.tool_calls ?? []) {
const index = tool.index
if (!toolCallOfIndex[index]) toolCallOfIndex[index] = { name: '', args: '' }
toolCallOfIndex[index].name += tool.function?.name ?? ''
toolCallOfIndex[index].args += tool.function?.arguments ?? ''
}
// message
let newText = ''
newText += chunk.choices[0]?.delta?.tool_calls?.[0]?.function?.name ?? ''
newText += chunk.choices[0]?.delta?.tool_calls?.[0]?.function?.arguments ?? ''
newText += chunk.choices[0]?.delta?.content ?? ''
fullText += newText;
onText({ newText, fullText });
}
onFinalMessage({ fullText });