mirror of
https://github.com/voideditor/void
synced 2026-05-24 09:58:23 +00:00
all tools seem to work!
This commit is contained in:
parent
d3e73b92e0
commit
812014d6d3
4 changed files with 95 additions and 38 deletions
|
|
@ -19,3 +19,6 @@ import '../common/metricsService.js'
|
|||
|
||||
// updates
|
||||
import '../common/voidUpdateService.js'
|
||||
|
||||
// tools
|
||||
import '../common/toolsService.js'
|
||||
|
|
|
|||
|
|
@ -1,15 +1,18 @@
|
|||
import { URI } from '../../../base/common/uri'
|
||||
import { IModelService } from '../../../editor/common/services/model'
|
||||
import { VSReadFile } from '../../../workbench/contrib/void/browser/helpers/readFile'
|
||||
import { IFileService, IFileStat } from '../../files/common/files'
|
||||
import { registerSingleton, InstantiationType } from '../../instantiation/common/extensions'
|
||||
import { createDecorator } from '../../instantiation/common/instantiation'
|
||||
import { CancellationToken } from '../../../base/common/cancellation.js'
|
||||
import { URI } from '../../../base/common/uri.js'
|
||||
import { IModelService } from '../../../editor/common/services/model.js'
|
||||
import { VSReadFileRaw } from '../../../workbench/contrib/void/browser/helpers/readFile.js'
|
||||
import { QueryBuilder } from '../../../workbench/services/search/common/queryBuilder.js'
|
||||
import { ISearchService } from '../../../workbench/services/search/common/search.js'
|
||||
import { IFileService, IFileStat } from '../../files/common/files.js'
|
||||
import { registerSingleton, InstantiationType } from '../../instantiation/common/extensions.js'
|
||||
import { createDecorator, IInstantiationService } from '../../instantiation/common/instantiation.js'
|
||||
import { IWorkspaceContextService } from '../../workspace/common/workspace.js'
|
||||
// import { IWorkspacesService } from '../../workspaces/common/workspaces.js'
|
||||
|
||||
|
||||
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
|
||||
// tool use for AI
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -21,6 +24,13 @@ export type InternalToolInfo = {
|
|||
},
|
||||
required: string[], // required paramNames
|
||||
}
|
||||
|
||||
// helper
|
||||
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
|
||||
|
||||
const contextTools = {
|
||||
read_file: {
|
||||
description: 'Returns file contents of a given URI.',
|
||||
|
|
@ -48,7 +58,7 @@ const contextTools = {
|
|||
required: ['query']
|
||||
},
|
||||
|
||||
grep_search: {
|
||||
search: {
|
||||
description: `Returns all code excerpts containing the given string or grep query. This does NOT search pathname. 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 },
|
||||
|
|
@ -66,7 +76,7 @@ const contextTools = {
|
|||
|
||||
type ContextToolName = keyof typeof contextTools
|
||||
type ContextParamNames<T extends ContextToolName> = keyof typeof contextTools[T]['params']
|
||||
type ContextParams<T extends ContextToolName> = { [paramName in ContextParamNames<T>]: string }
|
||||
type ContextParams<T extends ContextToolName> = { [paramName in ContextParamNames<T>]: unknown }
|
||||
|
||||
type ContextToolCallFns = {
|
||||
[ToolName in ContextToolName]: ((p: (ContextParams<ToolName>)) => Promise<string>)
|
||||
|
|
@ -78,20 +88,22 @@ type ContextToolCallFns = {
|
|||
|
||||
|
||||
|
||||
// TODO check to make sure in workspace
|
||||
// TODO check to make sure is not gitignored
|
||||
|
||||
export async function generateDirectoryTreeMd(fileService: IFileService, uri: URI): Promise<string> {
|
||||
|
||||
async function generateDirectoryTreeMd(fileService: IFileService, rootURI: URI): Promise<string> {
|
||||
let output = ''
|
||||
|
||||
function traverseChildren(children: IFileStat[], depth: number) {
|
||||
const indentation = ' '.repeat(depth);
|
||||
for (const child of children) {
|
||||
output += `${indentation}- ${child.name}\n`;
|
||||
output += traverseChildren(child.children ?? [], depth + 1);
|
||||
traverseChildren(child.children ?? [], depth + 1);
|
||||
}
|
||||
}
|
||||
const stat = await fileService.resolve(uri, { resolveMetadata: false });
|
||||
const stat = await fileService.resolve(rootURI, { resolveMetadata: false });
|
||||
|
||||
console.log('statttttttttt', JSON.stringify(stat, null, 2))
|
||||
// kickstart recursion
|
||||
output += `${stat.name}\n`;
|
||||
traverseChildren(stat.children ?? [], 1);
|
||||
|
|
@ -99,30 +111,42 @@ export async function generateDirectoryTreeMd(fileService: IFileService, uri: UR
|
|||
return output;
|
||||
}
|
||||
|
||||
// async function searchPathnameRegex(fileService: IFileService, pathnameRegex: string, workspaceURI: URI) {
|
||||
// let output: string[] = []
|
||||
// let regex: RegExp
|
||||
// try {
|
||||
// regex = new RegExp(pathnameRegex)
|
||||
// } catch (e) {
|
||||
// return [`(Error: invalid regex: ${e})`]
|
||||
// }
|
||||
|
||||
// function traverseChildren(children: IFileStat[]) {
|
||||
// for (const child of children) {
|
||||
// // if it's a file, match its name
|
||||
// if (child.isFile) {
|
||||
// if (regex.test(child.resource.fsPath)) { output.push(child.resource.fsPath) }
|
||||
// }
|
||||
// // otherwise traverse children
|
||||
// else {
|
||||
// traverseChildren(child.children ?? [])
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// const stat = await fileService.resolve(workspaceURI, { resolveMetadata: false });
|
||||
// traverseChildren(stat.children ?? []);
|
||||
// return output;
|
||||
// }
|
||||
|
||||
|
||||
|
||||
const validateURI = (uriStr: unknown) => {
|
||||
if (typeof uriStr !== 'string') throw new Error('(uri was not a string)')
|
||||
console.log('uriStr!!!!', uriStr)
|
||||
const uri = URI.file(uriStr)
|
||||
console.log('uri!!!!', uri)
|
||||
console.log('uri!!!!', uri.fsPath)
|
||||
return uri
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
export interface IToolService {
|
||||
readonly _serviceBrand: undefined;
|
||||
callContextTool: <T extends ContextToolName>(toolName: T, params: ContextParams<T>) => Promise<string>
|
||||
|
|
@ -139,26 +163,47 @@ export class ToolService implements IToolService {
|
|||
constructor(
|
||||
@IFileService fileService: IFileService,
|
||||
@IModelService modelService: IModelService,
|
||||
@IWorkspaceContextService w: IWorkspaceContextService,
|
||||
@ISearchService s: ISearchService,
|
||||
@IInstantiationService instantiationService: IInstantiationService,
|
||||
) {
|
||||
|
||||
|
||||
const queryBuilder = instantiationService.createInstance(QueryBuilder);
|
||||
|
||||
this.contextToolCallFns = {
|
||||
read_file: async ({ uri: uriStr }) => {
|
||||
const uri = validateURI(uriStr)
|
||||
const fileContents = await VSReadFile(modelService, uri)
|
||||
const fileContents = await VSReadFileRaw(fileService, uri)
|
||||
return fileContents ?? '(could not read file)'
|
||||
},
|
||||
list_dir: async ({ uri: uriStr }) => {
|
||||
const uri = validateURI(uriStr)
|
||||
const treeStr = await generateDirectoryTreeMd(fileService, uri)
|
||||
console.log('!!PIZA', treeStr)
|
||||
return treeStr
|
||||
},
|
||||
pathname_search: async ({ query }) => {
|
||||
return ''
|
||||
pathname_search: async ({ query: queryStr }) => {
|
||||
if (typeof queryStr !== 'string') return '(Error: query was not a string)'
|
||||
const query = queryBuilder.file(w.getWorkspace().folders.map(f => f.uri), { filePattern: queryStr, });
|
||||
|
||||
const data = await s.fileSearch(query, CancellationToken.None);
|
||||
const str = data.results.map(({ resource, results }) => resource.fsPath).join('\n')
|
||||
return str
|
||||
},
|
||||
grep_search: async ({ query }) => {
|
||||
return ''
|
||||
search: async ({ query: queryStr }) => {
|
||||
if (typeof queryStr !== 'string') return '(Error: query was not a string)'
|
||||
const query = queryBuilder.text({ pattern: queryStr, }, w.getWorkspace().folders.map(f => f.uri));
|
||||
|
||||
const data = await s.textSearch(query, CancellationToken.None);
|
||||
const str = data.results.map(({ resource, results }) => resource.fsPath).join('\n')
|
||||
return str
|
||||
},
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
callContextTool: IToolService['callContextTool'] = (toolName, params) => {
|
||||
|
|
|
|||
|
|
@ -4,7 +4,9 @@ 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
|
||||
|
||||
supports_streaming: boolean (o1 does NOT)
|
||||
max_tokens: number
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import { URI } from '../../../../../base/common/uri'
|
||||
import { EndOfLinePreference } from '../../../../../editor/common/model'
|
||||
import { IModelService } from '../../../../../editor/common/services/model.js'
|
||||
import { IFileService } from '../../../../../platform/files/common/files'
|
||||
|
||||
// read files from VSCode
|
||||
export const VSReadFile = async (modelService: IModelService, uri: URI): Promise<string | null> => {
|
||||
|
|
@ -8,3 +9,9 @@ export const VSReadFile = async (modelService: IModelService, uri: URI): Promise
|
|||
if (!model) return null
|
||||
return model.getValue(EndOfLinePreference.LF)
|
||||
}
|
||||
|
||||
export const VSReadFileRaw = async (fileService: IFileService, uri: URI) => {
|
||||
const res = await fileService.readFile(uri)
|
||||
const str = res.value.toString()
|
||||
return str
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue