From 18b278577d5776f5f4dc2e1261926292e14deb8d Mon Sep 17 00:00:00 2001 From: Andrew Pareles Date: Sat, 8 Feb 2025 21:17:38 -0800 Subject: [PATCH] tools --- .../platform/void/common/voidSettingsTypes.ts | 2 +- .../void/electron-main/llmMessage/greptile.ts | 68 ----------- .../void/electron-main/llmMessage/openai.ts | 5 +- .../void/electron-main/llmMessageChannel.ts | 2 +- .../void/electron-main/templates/templates.ts | 12 ++ .../void/electron-main/templates/tools.ts | 111 ++++++++++++++++++ 6 files changed, 129 insertions(+), 71 deletions(-) delete mode 100644 src/vs/platform/void/electron-main/llmMessage/greptile.ts create mode 100644 src/vs/platform/void/electron-main/templates/templates.ts create mode 100644 src/vs/platform/void/electron-main/templates/tools.ts diff --git a/src/vs/platform/void/common/voidSettingsTypes.ts b/src/vs/platform/void/common/voidSettingsTypes.ts index c9eadefd..0a5bdc64 100644 --- a/src/vs/platform/void/common/voidSettingsTypes.ts +++ b/src/vs/platform/void/common/voidSettingsTypes.ts @@ -253,7 +253,7 @@ export const displayInfoOfProviderName = (providerName: ProviderName): DisplayIn } else if (providerName === 'groq') { return { - title: 'Groq API', + title: 'Groq.com API', } } else if (providerName === 'mistral') { diff --git a/src/vs/platform/void/electron-main/llmMessage/greptile.ts b/src/vs/platform/void/electron-main/llmMessage/greptile.ts deleted file mode 100644 index f61f87af..00000000 --- a/src/vs/platform/void/electron-main/llmMessage/greptile.ts +++ /dev/null @@ -1,68 +0,0 @@ -/*-------------------------------------------------------------------------------------- - * Copyright 2025 Glass Devtools, Inc. All rights reserved. - * Licensed under the Apache License, Version 2.0. See LICENSE.txt for more information. - *--------------------------------------------------------------------------------------*/ - -// // Greptile -// // https://docs.greptile.com/api-reference/query -// // https://docs.greptile.com/quickstart#sample-response-streamed - -// import { SendLLMMessageFnTypeInternal } from '../../common/llmMessageTypes.js'; - -// export const sendGreptileMsg: SendLLMMessageFnTypeInternal = ({ messages, onText, onFinalMessage, onError, settingsOfProvider, _setAborter }) => { - -// let fullText = '' - -// const thisConfig = settingsOfProvider.greptile - -// fetch('https://api.greptile.com/v2/query', { -// method: 'POST', -// headers: { -// 'Authorization': `Bearer ${thisConfig.apikey}`, -// 'X-Github-Token': `${thisConfig.githubPAT}`, -// 'Content-Type': `application/json`, -// }, -// body: JSON.stringify({ -// messages, -// stream: true, -// repositories: [thisConfig.repoinfo], -// }), -// }) -// // this is {message}\n{message}\n{message}...\n -// .then(async response => { -// const text = await response.text() -// console.log('got greptile', text) -// return JSON.parse(`[${text.trim().split('\n').join(',')}]`) -// }) -// // TODO make this actually stream, right now it just sends one message at the end -// // TODO add _setAborter() when add streaming -// .then(async responseArr => { - -// for (const response of responseArr) { -// const type: string = response['type'] -// const message = response['message'] - -// // when receive text -// if (type === 'message') { -// fullText += message -// onText({ newText: message, fullText }) -// } -// else if (type === 'sources') { -// const { filepath, linestart: _, lineend: _2 } = message as { filepath: string; linestart: number | null; lineend: number | null } -// fullText += filepath -// onText({ newText: filepath, fullText }) -// } -// // type: 'status' with an empty 'message' means last message -// else if (type === 'status') { -// if (!message) { -// onFinalMessage({ fullText }) -// } -// } -// } - -// }) -// .catch(error => { -// onError({ error }) -// }); - -// } diff --git a/src/vs/platform/void/electron-main/llmMessage/openai.ts b/src/vs/platform/void/electron-main/llmMessage/openai.ts index 268eadfb..8fd49684 100644 --- a/src/vs/platform/void/electron-main/llmMessage/openai.ts +++ b/src/vs/platform/void/electron-main/llmMessage/openai.ts @@ -9,7 +9,11 @@ import { Model } from 'openai/resources/models.js'; // import { parseMaxTokensStr } from './util.js'; +// https://cdn.openai.com/spec/model-spec-2024-05-08.html#follow-the-chain-of-command +// https://platform.openai.com/docs/guides/reasoning#advice-on-prompting + +// might not currently be used in the code export const openaiCompatibleList: _InternalModelListFnType = async ({ onSuccess: onSuccess_, onError: onError_, settingsOfProvider }) => { const onSuccess = ({ models }: { models: Model[] }) => { onSuccess_({ models }) @@ -116,7 +120,6 @@ export const sendOpenAIChat: _InternalSendLLMChatMessageFnType = ({ messages, on model: modelName, messages: messages, stream: true, - // max_completion_tokens: parseMaxTokensStr(thisConfig.maxTokens) } openai.chat.completions diff --git a/src/vs/platform/void/electron-main/llmMessageChannel.ts b/src/vs/platform/void/electron-main/llmMessageChannel.ts index 2c44e2ec..3575e34e 100644 --- a/src/vs/platform/void/electron-main/llmMessageChannel.ts +++ b/src/vs/platform/void/electron-main/llmMessageChannel.ts @@ -66,7 +66,7 @@ export class LLMMessageChannel implements IServerChannel { } } - // browser uses this to call + // browser uses this to call (see this.channel.call() in llmMessageService.ts for all usages) async call(_: unknown, command: string, params: any): Promise { try { if (command === 'sendLLMMessage') { diff --git a/src/vs/platform/void/electron-main/templates/templates.ts b/src/vs/platform/void/electron-main/templates/templates.ts new file mode 100644 index 00000000..0f74197e --- /dev/null +++ b/src/vs/platform/void/electron-main/templates/templates.ts @@ -0,0 +1,12 @@ +/* + +modelName -> { + system_message_type: 'system' | 'developer' (openai) | null // if null, we will just do a string of system message + supports_tools: boolean // we will just do a string of tool use if it doesn't support + supports_autocomplete_FIM (suffix) // we will just do a description of FIM if it doens't support <|fim_hole|> + max_tokens + + +} + +*/ diff --git a/src/vs/platform/void/electron-main/templates/tools.ts b/src/vs/platform/void/electron-main/templates/tools.ts new file mode 100644 index 00000000..70c250e6 --- /dev/null +++ b/src/vs/platform/void/electron-main/templates/tools.ts @@ -0,0 +1,111 @@ + +import Anthropic from '@anthropic-ai/sdk' +import OpenAI from 'openai' + +const pagination = { + desc: `Very large results may be paginated (indicated in the result). Pagination fails gracefully if out of bounds or invalid page number.`, + param: { pageNumber: { type: 'number', description: 'The page number (optional, defaults to 1).' }, } +} as const + +// we do this using Anthropic's style and convert to OpenAI style later +type InternalToolInfo = { + description: string, + params: { + [paramName: string]: { type: string, description: string | undefined } // name -> type + }, + required: string[], // required paramNames +} +const contextTools = { + read_file: { + description: 'Returns file contents of a given URI.', + params: { + uri: { type: 'string', description: undefined }, + }, + required: ['uri'], + }, + + list_dir: { + description: `Returns all file names and folder names in a given URI. ${pagination.desc}`, + params: { + uri: { type: 'string', description: undefined }, + ...pagination.param + }, + required: ['uri'], + }, + + pathname_search: { + description: `Returns all pathnames that match a given grep query. You should use this when looking for a file with a specific name or path. This does NOT search file content. ${pagination.desc}`, + params: { + query: { type: 'string', description: undefined }, + ...pagination.param, + }, + required: ['query'] + }, + + grep_search: { + description: `Returns all code excerpts containing the given string or grep query. Does not search filename. As a follow-up, you may want to use read_file to view the full file contents of the results. ${pagination.desc}`, + params: { + query: { type: 'string', description: undefined }, + ...pagination.param, + }, + required: ['query'], + }, + + // semantic_search: { + // description: 'Searches files semantically for the given string query.', + // // RAG + // }, + +} as const satisfies { [name: string]: InternalToolInfo } + +type ContextToolName = keyof typeof contextTools +type ContextParams = keyof typeof contextTools[T]['params'] + +const contextFunctions: { [ToolName in ContextToolName]: (p: ({ [paramName in ContextParams]: string })) => string } = { + read_file: ({ uri }) => { + return '' + }, + list_dir: ({ }) => { + return '' + }, + pathname_search: ({ }) => { + return '' + }, + grep_search: ({ }) => { + return '' + }, + +} + + + +const toOpenAITool = (toolName: string, toolInfo: InternalToolInfo) => { + const { description, params, required } = toolInfo + return { + type: 'function', + function: { + name: toolName, + description: description, + parameters: { + type: 'object', + properties: params, + required: required, + } + } + } satisfies OpenAI.Chat.Completions.ChatCompletionTool +} + + + +const toAnthropicTool = (toolName: string, toolInfo: InternalToolInfo) => { + const { description, params, required } = toolInfo + return { + name: toolName, + description: description, + input_schema: { + type: 'object', + properties: params, + required: required, + } + } satisfies Anthropic.Messages.Tool +}