add automatic file adding

This commit is contained in:
Mathew Pareles 2025-03-19 21:58:12 -07:00
parent dd321121e3
commit 0dae638be7
4 changed files with 85 additions and 4 deletions

View file

@ -27,6 +27,8 @@ import { ITerminalToolService } from './terminalToolService.js';
import { IMetricsService } from '../common/metricsService.js';
import { shorten } from '../../../../base/common/labels.js';
import { IVoidModelService } from '../common/voidModelService.js';
import { IEditorService } from '../../../services/editor/common/editorService.js';
import { ICodeEditorService } from '../../../../editor/browser/services/codeEditorService.js';
const findLastIndex = <T>(arr: T[], condition: (t: T) => boolean): number => {
for (let i = arr.length - 1; i >= 0; i--) {
@ -208,6 +210,8 @@ class ChatThreadService extends Disposable implements IChatThreadService {
@ILanguageFeaturesService private readonly _languageFeaturesService: ILanguageFeaturesService,
@ITerminalToolService private readonly _terminalToolService: ITerminalToolService,
@IMetricsService private readonly _metricsService: IMetricsService,
@IEditorService private readonly _editorService: IEditorService,
@ICodeEditorService private readonly _codeEditorService: ICodeEditorService,
) {
super()
this.state = { allThreads: {}, currentThreadId: null as unknown as string } // default state
@ -222,8 +226,66 @@ class ChatThreadService extends Disposable implements IChatThreadService {
// always be in a thread
this.openNewThread()
// when the user changes files, automatically add the new file as a stagingSelection
this._register(this._editorService.onDidActiveEditorChange(() => this._addCurrentFileAsStagingSelectionDuringFileChange()));
}
private _addCurrentFileAsStagingSelectionDuringFileChange() {
// add the current file to the thread/message being edited
const model = this._codeEditorService.getActiveCodeEditor()?.getModel() ?? null
if (!model) { return; }
const newSelection: StagingSelectionItem = {
type: 'File',
fileURI: model.uri,
language: model.getLanguageId(),
selectionStr: null,
range: null,
state: { isOpened: false, wasAddedAsCurrentFile: true }
}
const focusedMessageIdx = this.getCurrentFocusedMessageIdx();
// add the selection
if (focusedMessageIdx === undefined) { // user is in the default thread
const oldStagingSelections = this.getCurrentThreadState().stagingSelections || [];
// if the file already exists, do nothing
const alreadyHasFile = oldStagingSelections.some(s => s.type === 'File' && s.fileURI.toString() === newSelection.fileURI.toString())
if (alreadyHasFile) { return; }
// add the file
const filteredStagingSelections = oldStagingSelections.filter(s => !s.state?.wasAddedAsCurrentFile); // remove all old selectons that were added during a file change
const newSelections = [...filteredStagingSelections, newSelection];
this.setCurrentThreadState({ stagingSelections: newSelections });
} else { // user is editing a message
// const oldStagingSelections = this.getCurrentMessageState(focusedMessageIdx).stagingSelections || [];
// // if the file already exists, do nothing
// const alreadyHasFile = oldStagingSelections.some(s => s.type === 'File' && s.fileURI.toString() === newSelection.fileURI.toString())
// if (alreadyHasFile) { return; }
// const filteredStagingSelections = oldStagingSelections.filter(s => !s.state?.wasAddedDuringFileChange); // remove all old selectons that were added during a file change
// const newSelections = [...filteredStagingSelections, newSelection];
// this.setCurrentMessageState(focusedMessageIdx, { stagingSelections: newSelections });
}
}
// !!! this is important for properly restoring URIs from storage
// should probably re-use code from void/src/vs/base/common/marshalling.ts instead. but this is simple enough
private _convertThreadDataFromStorage(threadsStr: string): ChatThreads {

View file

@ -518,7 +518,7 @@ export const SelectedFiles = (
language: (await modelReferenceService.getModelSafe(uri)).model?.getLanguageId() || 'plaintext',
selectionStr: null,
range: null,
state: { isOpened: false },
state: { isOpened: false, wasAddedAsCurrentFile: false },
})
}
return answer
@ -548,6 +548,7 @@ export const SelectedFiles = (
const isThisSelectionOpened = (!!selection.selectionStr && selection.state.isOpened && type === 'staging')
const isThisSelectionAFile = selection.selectionStr === null
const isThisSelectionProspective = i > selections.length - 1
const isThisSelectionAddedAsCurrentFile = selection.state.wasAddedAsCurrentFile
const thisKey = `${isThisSelectionProspective}-${i}-${selections.length}`
@ -582,14 +583,21 @@ export const SelectedFiles = (
if (isThisSelectionProspective) { // add prospective selection to selections
setSelections([...selections, selection])
} else if (isThisSelectionAFile) { // open files
commandService.executeCommand('vscode.open', selection.fileURI, {
preview: true,
// preserveFocus: false,
});
if (isThisSelectionAddedAsCurrentFile) {
// make it so the file is added permanently, not just as the current file
const newSelection: StagingSelectionItem = { ...selection, state: { ...selection.state, wasAddedAsCurrentFile: false } }
setSelections([...selections.slice(0, i), newSelection, ...selections.slice(i + 1)])
}
} else { // show text
const selection = selections[i]
const newSelection = { ...selection, state: { isOpened: !selection.state.isOpened } }
const newSelection = { ...selection, state: { ...selection.state, isOpened: !selection.state.isOpened } }
const newSelections = [
...selections.slice(0, i),
newSelection,
@ -611,6 +619,15 @@ export const SelectedFiles = (
+ (isThisSelectionAFile ? '' : ` (${selection.range.startLineNumber}-${selection.range.endLineNumber})`)
}
{/* {isThisSelectionAFile && currentURI?.toString() === selection.fileURI.toString() &&
<span className={`text-[8px] ml-0.5 ${isThisSelectionAddedAsCurrentFile ? 'void-opacity-60 text-void-fg-4 ' : ''}`}>
{`(Current File)`}
</span>
} */}
{isThisSelectionAddedAsCurrentFile && <span className={`text-[8px] ml-0.5 'void-opacity-60 text-void-fg-4`}>
{`(Current File)`}
</span>}
{type === 'staging' && !isThisSelectionProspective ? // X button
<IconX
className='cursor-pointer z-1 stroke-[2]'

View file

@ -122,14 +122,14 @@ registerAction2(class extends Action2 {
language: model.getLanguageId(),
selectionStr: null,
range: null,
state: { isOpened: false, }
state: { isOpened: false, wasAddedAsCurrentFile: false }
} : {
type: 'Selection',
fileURI: model.uri,
language: model.getLanguageId(),
selectionStr: selectionStr,
range: selectionRange,
state: { isOpened: true, }
state: { isOpened: true, wasAddedAsCurrentFile: false }
}
// update the staging selections

View file

@ -55,6 +55,7 @@ export type CodeSelection = {
range: IRange;
state: {
isOpened: boolean;
wasAddedAsCurrentFile: boolean;
};
}
@ -66,6 +67,7 @@ export type FileSelection = {
range: null;
state: {
isOpened: boolean;
wasAddedAsCurrentFile: boolean;
};
}