mirror of
https://github.com/voideditor/void
synced 2026-05-24 09:58:23 +00:00
file service read
This commit is contained in:
parent
02f64b7ff6
commit
858b6f6a91
8 changed files with 142 additions and 25 deletions
|
|
@ -12,6 +12,7 @@ import { ITextModelService } from '../../../../editor/common/services/resolverSe
|
|||
import { Range } from '../../../../editor/common/core/range.js';
|
||||
import { CancellationToken } from '../../../../base/common/cancellation.js';
|
||||
import { CodeActionContext, CodeActionTriggerType } from '../../../../editor/common/languages.js';
|
||||
import { URI } from '../../../../base/common/uri.js';
|
||||
|
||||
export interface IMarkerCheckService {
|
||||
readonly _serviceBrand: undefined;
|
||||
|
|
@ -99,6 +100,21 @@ class MarkerCheckService extends Disposable implements IMarkerCheckService {
|
|||
}
|
||||
|
||||
|
||||
|
||||
|
||||
fixErrorsInFiles(uris: URI[], contextSoFar: []) {
|
||||
const allMarkers = this._markerService.read();
|
||||
|
||||
|
||||
// check errors in files
|
||||
|
||||
|
||||
// give LLM errors in files
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
// private _onMarkersChanged = (changedResources: readonly URI[]): void => {
|
||||
// for (const resource of changedResources) {
|
||||
// const markers = this._markerService.read({ resource });
|
||||
|
|
|
|||
|
|
@ -16,9 +16,9 @@ import { isCodeEditor } from '../../../../editor/browser/editorBrowser.js';
|
|||
import { EditorResourceAccessor } from '../../../common/editor.js';
|
||||
import { IModelService } from '../../../../editor/common/services/model.js';
|
||||
import { extractCodeFromRegular } from './helpers/extractCodeFromResult.js';
|
||||
import { isWindows } from '../../../../base/common/platform.js';
|
||||
import { registerWorkbenchContribution2, WorkbenchPhase } from '../../../common/contributions.js';
|
||||
import { ILLMMessageService } from '../common/llmMessageService.js';
|
||||
import { _ln, allLinebreakSymbols } from '../common/voidFileService.js';
|
||||
// import { IContextGatheringService } from './contextGatheringService.js';
|
||||
|
||||
// The extension this was called from is here - https://github.com/voideditor/void/blob/autocomplete/extensions/void/src/extension/extension.ts
|
||||
|
|
@ -415,9 +415,6 @@ const toInlineCompletions = ({ autocompletionMatchup, autocompletion, prefixAndS
|
|||
// }
|
||||
|
||||
|
||||
const allLinebreakSymbols = ['\r\n', '\n']
|
||||
const _ln = isWindows ? allLinebreakSymbols[0] : allLinebreakSymbols[1]
|
||||
|
||||
type PrefixAndSuffixInfo = { prefix: string, suffix: string, prefixLines: string[], suffixLines: string[], prefixToTheLeftOfCursor: string, suffixToTheRightOfCursor: string }
|
||||
const getPrefixAndSuffixInfo = (model: ITextModel, position: Position): PrefixAndSuffixInfo => {
|
||||
|
||||
|
|
|
|||
|
|
@ -12,12 +12,11 @@ import { URI } from '../../../../base/common/uri.js';
|
|||
import { Emitter, Event } from '../../../../base/common/event.js';
|
||||
import { IRange } from '../../../../editor/common/core/range.js';
|
||||
import { ILLMMessageService } from '../common/llmMessageService.js';
|
||||
import { IModelService } from '../../../../editor/common/services/model.js';
|
||||
import { chat_userMessageContent, chat_systemMessage, chat_userMessageContentWithAllFilesToo as chat_userMessageContentWithAllFiles, chat_selectionsString } from './prompt/prompts.js';
|
||||
import { IFileService } from '../../../../platform/files/common/files.js';
|
||||
import { InternalToolInfo, IToolsService, ToolCallReturnType, ToolFns, ToolName, voidTools } from '../common/toolsService.js';
|
||||
import { toLLMChatMessage } from '../common/llmMessageTypes.js';
|
||||
import { IWorkspaceContextService } from '../../../../platform/workspace/common/workspace.js';
|
||||
import { IVoidFileService } from '../common/voidFileService.js';
|
||||
|
||||
|
||||
const findLastIndex = <T>(arr: T[], condition: (t: T) => boolean): number => {
|
||||
|
|
@ -189,8 +188,7 @@ class ChatThreadService extends Disposable implements IChatThreadService {
|
|||
|
||||
constructor(
|
||||
@IStorageService private readonly _storageService: IStorageService,
|
||||
@IModelService private readonly _modelService: IModelService,
|
||||
@IFileService private readonly _fileService: IFileService,
|
||||
@IVoidFileService private readonly _voidFileService: IVoidFileService,
|
||||
@ILLMMessageService private readonly _llmMessageService: ILLMMessageService,
|
||||
@IToolsService private readonly _toolsService: IToolsService,
|
||||
@IWorkspaceContextService private readonly _workspaceContextService: IWorkspaceContextService,
|
||||
|
|
@ -358,7 +356,7 @@ class ChatThreadService extends Disposable implements IChatThreadService {
|
|||
// add user's message to chat history
|
||||
const instructions = userMessage
|
||||
const userMessageContent = await chat_userMessageContent(instructions, currSelns)
|
||||
const selectionsStr = await chat_selectionsString(prevSelns, currSelns, this._modelService, this._fileService)
|
||||
const selectionsStr = await chat_selectionsString(prevSelns, currSelns, this._voidFileService)
|
||||
const userMessageFullContent = chat_userMessageContentWithAllFiles(userMessageContent, selectionsStr)
|
||||
|
||||
const userHistoryElt: ChatMessage = { role: 'user', content: userMessageContent, displayContent: instructions, selections: currSelns, state: defaultMessageState }
|
||||
|
|
|
|||
|
|
@ -41,8 +41,7 @@ import { ICommandService } from '../../../../platform/commands/common/commands.j
|
|||
import { ILLMMessageService } from '../common/llmMessageService.js';
|
||||
import { LLMChatMessage, errorDetails } from '../common/llmMessageTypes.js';
|
||||
import { IMetricsService } from '../common/metricsService.js';
|
||||
import { VSReadFile } from './helpers/readFile.js';
|
||||
import { IFileService } from '../../../../platform/files/common/files.js';
|
||||
import { IVoidFileService } from '../common/voidFileService.js';
|
||||
|
||||
const configOfBG = (color: Color) => {
|
||||
return { dark: color, light: color, hcDark: color, hcLight: color, }
|
||||
|
|
@ -255,7 +254,7 @@ class EditCodeService extends Disposable implements IEditCodeService {
|
|||
@IMetricsService private readonly _metricsService: IMetricsService,
|
||||
@INotificationService private readonly _notificationService: INotificationService,
|
||||
@ICommandService private readonly _commandService: ICommandService,
|
||||
@IFileService private readonly _fileService: IFileService,
|
||||
@IVoidFileService private readonly _voidFileService: IVoidFileService,
|
||||
) {
|
||||
super();
|
||||
|
||||
|
|
@ -1184,7 +1183,7 @@ class EditCodeService extends Disposable implements IEditCodeService {
|
|||
const uri = uri_
|
||||
|
||||
// generate search/replace block text
|
||||
const origFileContents = await VSReadFile(uri, this._modelService, this._fileService)
|
||||
const origFileContents = await this._voidFileService.readFile(uri)
|
||||
if (origFileContents === null) return
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -7,10 +7,9 @@
|
|||
import { URI } from '../../../../../base/common/uri.js';
|
||||
import { filenameToVscodeLanguage } from '../helpers/detectLanguage.js';
|
||||
import { CodeSelection, StagingSelectionItem, FileSelection } from '../chatThreadService.js';
|
||||
import { VSReadFile } from '../helpers/readFile.js';
|
||||
import { IModelService } from '../../../../../editor/common/services/model.js';
|
||||
import { os } from '../helpers/systemInfo.js';
|
||||
import { IFileService } from '../../../../../platform/files/common/files.js';
|
||||
import { IVoidFileService } from '../../common/voidFileService.js';
|
||||
|
||||
|
||||
// this is just for ease of readability
|
||||
|
|
@ -169,10 +168,10 @@ ${tripleTick[1]}
|
|||
}
|
||||
|
||||
const failToReadStr = 'Could not read content. This file may have been deleted. If you expected content here, you can tell the user about this as they might not know.'
|
||||
const stringifyFileSelections = async (fileSelections: FileSelection[], modelService: IModelService, fileService: IFileService) => {
|
||||
const stringifyFileSelections = async (fileSelections: FileSelection[], voidFileService: IVoidFileService) => {
|
||||
if (fileSelections.length === 0) return null
|
||||
const fileSlns: FileSelnLocal[] = await Promise.all(fileSelections.map(async (sel) => {
|
||||
const content = await VSReadFile(sel.fileURI, modelService, fileService) ?? failToReadStr
|
||||
const content = await voidFileService.readFile(sel.fileURI) ?? failToReadStr
|
||||
return { ...sel, content }
|
||||
}))
|
||||
return fileSlns.map(sel => stringifyFileSelection(sel)).join('\n')
|
||||
|
|
@ -195,7 +194,7 @@ export const chat_userMessageContent = async (instructions: string, currSelns: S
|
|||
return str;
|
||||
};
|
||||
|
||||
export const chat_selectionsString = async (prevSelns: StagingSelectionItem[] | null, currSelns: StagingSelectionItem[] | null, modelService: IModelService, fileService: IFileService) => {
|
||||
export const chat_selectionsString = async (prevSelns: StagingSelectionItem[] | null, currSelns: StagingSelectionItem[] | null, voidFileService: IVoidFileService) => {
|
||||
|
||||
// ADD IN FILES AT TOP
|
||||
const allSelections = [...currSelns || [], ...prevSelns || []]
|
||||
|
|
@ -220,7 +219,7 @@ export const chat_selectionsString = async (prevSelns: StagingSelectionItem[] |
|
|||
}
|
||||
}
|
||||
|
||||
const filesStr = await stringifyFileSelections(fileSelections, modelService, fileService)
|
||||
const filesStr = await stringifyFileSelections(fileSelections, voidFileService)
|
||||
const selnsStr = stringifyCodeSelections(codeSelections)
|
||||
|
||||
|
||||
|
|
@ -297,12 +296,12 @@ 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`
|
||||
|
||||
|
||||
export const aiRegex_computeReplacementsForFile_userMessage = async ({ searchClause, replaceClause, fileURI, modelService, fileService }: { searchClause: string, replaceClause: string, fileURI: URI, modelService: IModelService, fileService: IFileService }) => {
|
||||
export const aiRegex_computeReplacementsForFile_userMessage = async ({ searchClause, replaceClause, fileURI, voidFileService }: { searchClause: string, replaceClause: string, fileURI: URI, modelService: IModelService, voidFileService: IVoidFileService }) => {
|
||||
|
||||
// we may want to do this in batches
|
||||
const fileSelection: FileSelection = { type: 'File', fileURI, selectionStr: null, range: null }
|
||||
|
||||
const file = await stringifyFileSelections([fileSelection], modelService, fileService)
|
||||
const file = await stringifyFileSelections([fileSelection], voidFileService)
|
||||
|
||||
return `\
|
||||
## FILE
|
||||
|
|
|
|||
|
|
@ -5,9 +5,9 @@ import { IFileService } from '../../../../platform/files/common/files.js'
|
|||
import { registerSingleton, InstantiationType } from '../../../../platform/instantiation/common/extensions.js'
|
||||
import { createDecorator, IInstantiationService } from '../../../../platform/instantiation/common/instantiation.js'
|
||||
import { IWorkspaceContextService } from '../../../../platform/workspace/common/workspace.js'
|
||||
import { VSReadFile } 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 { IVoidFileService } from './voidFileService.js'
|
||||
|
||||
|
||||
// tool use for AI
|
||||
|
|
@ -196,6 +196,7 @@ export class ToolsService implements IToolsService {
|
|||
@IWorkspaceContextService workspaceContextService: IWorkspaceContextService,
|
||||
@ISearchService searchService: ISearchService,
|
||||
@IInstantiationService instantiationService: IInstantiationService,
|
||||
@IVoidFileService voidFileService: IVoidFileService,
|
||||
) {
|
||||
|
||||
const queryBuilder = instantiationService.createInstance(QueryBuilder);
|
||||
|
|
@ -208,7 +209,7 @@ export class ToolsService implements IToolsService {
|
|||
const uri = validateURI(uriStr)
|
||||
const pageNumber = validatePageNum(pageNumberUnknown)
|
||||
|
||||
const readFileContents = await VSReadFile(uri, modelService, fileService)
|
||||
const readFileContents = await voidFileService.readFile(uri)
|
||||
|
||||
const fromIdx = MAX_FILE_CHARS_PAGE * (pageNumber - 1)
|
||||
const toIdx = MAX_FILE_CHARS_PAGE * pageNumber - 1
|
||||
|
|
|
|||
109
src/vs/workbench/contrib/void/common/voidFileService.ts
Normal file
109
src/vs/workbench/contrib/void/common/voidFileService.ts
Normal file
|
|
@ -0,0 +1,109 @@
|
|||
/*--------------------------------------------------------------------------------------
|
||||
* Copyright 2025 Glass Devtools, Inc. All rights reserved.
|
||||
* Licensed under the Apache License, Version 2.0. See LICENSE.txt for more information.
|
||||
*--------------------------------------------------------------------------------------*/
|
||||
|
||||
import { isWindows } from '../../../../base/common/platform.js';
|
||||
import { URI } from '../../../../base/common/uri.js';
|
||||
import { EndOfLinePreference } from '../../../../editor/common/model.js';
|
||||
import { IModelService } from '../../../../editor/common/services/model.js';
|
||||
import { IFileService } from '../../../../platform/files/common/files.js';
|
||||
import { registerSingleton, InstantiationType } from '../../../../platform/instantiation/common/extensions.js';
|
||||
import { createDecorator } from '../../../../platform/instantiation/common/instantiation.js';
|
||||
|
||||
|
||||
// linebreak symbols
|
||||
export const allLinebreakSymbols = ['\r\n', '\n']
|
||||
export const _ln = isWindows ? allLinebreakSymbols[0] : allLinebreakSymbols[1]
|
||||
|
||||
export interface IVoidFileService {
|
||||
readonly _serviceBrand: undefined;
|
||||
|
||||
readFile(uri: URI, range?: { startLineNumber: number, endLineNumber: number }): Promise<string>;
|
||||
|
||||
}
|
||||
|
||||
export const IVoidFileService = createDecorator<IVoidFileService>('VoidFileService');
|
||||
|
||||
// implemented by calling channel
|
||||
export class VoidFileService implements IVoidFileService {
|
||||
readonly _serviceBrand: undefined;
|
||||
|
||||
constructor(
|
||||
@IModelService private readonly modelService: IModelService,
|
||||
@IFileService private readonly fileService: IFileService,
|
||||
) {
|
||||
|
||||
}
|
||||
|
||||
readFile = async (uri: URI, range?: { startLineNumber: number, endLineNumber: number }): Promise<string> => {
|
||||
|
||||
// attempt to read the model
|
||||
const modelResult = await this._readModel(uri, range);
|
||||
if (modelResult) return modelResult;
|
||||
|
||||
// if no model, read the raw file
|
||||
const fileResult = await this._readFileRaw(uri, range);
|
||||
if (fileResult) return fileResult;
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
_readFileRaw = async (uri: URI, range?: { startLineNumber: number, endLineNumber: number }): Promise<string | null> => {
|
||||
|
||||
try { // this throws an error if no file exists (eg it was deleted)
|
||||
|
||||
const res = await this.fileService.readFile(uri);
|
||||
|
||||
if (range) {
|
||||
return res.value.toString()
|
||||
.split(_ln)
|
||||
.slice(range.startLineNumber - 1, range.endLineNumber)
|
||||
.join(_ln)
|
||||
}
|
||||
|
||||
return res.value.toString();
|
||||
|
||||
|
||||
} catch (e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
_readModel = async (uri: URI, range?: { startLineNumber: number, endLineNumber: number }): Promise<string | null> => {
|
||||
|
||||
// read saved model (sometimes null if the user reloads application)
|
||||
let model = this.modelService.getModel(uri);
|
||||
|
||||
// check all opened models for the same `fsPath`
|
||||
if (!model) {
|
||||
const models = this.modelService.getModels();
|
||||
for (const m of models) {
|
||||
if (m.uri.fsPath === uri.fsPath) {
|
||||
model = m
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if still not found, return
|
||||
if (!model) { return null }
|
||||
|
||||
// if range, read it
|
||||
if (range) {
|
||||
return model.getValueInRange({
|
||||
startLineNumber: range.startLineNumber,
|
||||
endLineNumber: range.endLineNumber,
|
||||
startColumn: 1,
|
||||
endColumn: Number.MAX_VALUE
|
||||
}, EndOfLinePreference.LF);
|
||||
} else {
|
||||
return model.getValue(EndOfLinePreference.LF)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
registerSingleton(IVoidFileService, VoidFileService, InstantiationType.Eager);
|
||||
|
|
@ -1,7 +1,5 @@
|
|||
import { ToolName, toolNames } from '../../common/toolsService.js';
|
||||
|
||||
|
||||
|
||||
const toolNamesSet = new Set<string>(toolNames)
|
||||
|
||||
export const isAToolName = (toolName: string): toolName is ToolName => {
|
||||
|
|
|
|||
Loading…
Reference in a new issue