This commit is contained in:
Andrew Pareles 2025-05-29 17:23:55 -07:00
parent 77e562e278
commit 98e07e1c7f
3 changed files with 85 additions and 28 deletions

View file

@ -8,3 +8,5 @@ Look for services and built-in functions that you might need to use to solve the
In typescript, do NOT cast to types if not neccessary. NEVER lazily cast to 'any'. Find the correct type to apply and use it.
Do not add or remove semicolons to any of my files. Just go with convention and make the least number of changes.
Never modify files outside src/vs/workbench/contrib/void without consulting with the user first.

View file

@ -21,7 +21,7 @@ import { getBasename, getFolderName } from '../sidebar-tsx/SidebarChat.js';
import { ChevronRight, File, Folder, FolderClosed, LucideProps } from 'lucide-react';
import { StagingSelectionItem } from '../../../../common/chatThreadServiceTypes.js';
import { DiffEditorWidget } from '../../../../../../../editor/browser/widget/diffEditor/diffEditorWidget.js';
import { extractSearchReplaceBlocks } from '../../../../common/helpers/extractCodeFromResult.js';
import { extractSearchReplaceBlocks, ExtractedSearchReplaceBlock } from '../../../../common/helpers/extractCodeFromResult.js';
import { IAccessibilitySignalService } from '../../../../../../../platform/accessibilitySignal/browser/accessibilitySignalService.js';
import { IEditorProgressService } from '../../../../../../../platform/progress/common/progress.js';
import { detectLanguage } from '../../../../common/helpers/languageHelpers.js';
@ -1844,33 +1844,16 @@ export const VoidButtonBgDarken = ({ children, disabled, onClick, className }: {
// return <div ref={containerRef} className="w-full" />;
// };
/**
* ToolDiffEditor mounts a native VSCode DiffEditorWidget to show a diff between original and modified code blocks.
* Props:
* - uri: URI of the file (for language detection, etc)
* - searchReplaceBlocks: string in search/replace format (from LLM)
* - language?: string (optional, fallback to 'plaintext')
*/
export const VoidDiffEditor = ({ uri, searchReplaceBlocks, language }: { uri?: any, searchReplaceBlocks: string, language?: string }) => {
const SingleDiffEditor = ({ block, lang }: { block: ExtractedSearchReplaceBlock, lang: string | undefined }) => {
const accessor = useAccessor();
const modelService = accessor.get('IModelService');
const instantiationService = accessor.get('IInstantiationService');
const languageService = accessor.get('ILanguageService');
const contextKeyService = accessor.get('IContextKeyService');
const codeEditorService = accessor.get('ICodeEditorService');
// Extract the first block (if present)
const blocks = extractSearchReplaceBlocks(searchReplaceBlocks);
const block = blocks[0] || { orig: '', final: '' };
// Use detectLanguage for language detection if not provided
let lang = language;
if (!lang) {
lang = detectLanguage(languageService, { uri: uri ?? null, fileContents: block.orig });
}
// Use ILanguageSelection for model creation
const languageSelection = useMemo(() => languageService.createById(lang!), [lang, languageService]);
const languageSelection = useMemo(() => languageService.createById(lang), [lang, languageService]);
// Create models for original and modified
const originalModel = useMemo(() =>
@ -1906,7 +1889,7 @@ export const VoidDiffEditor = ({ uri, searchReplaceBlocks, language }: { uri?: a
renderSideBySide: true,
minimap: { enabled: false },
lineNumbers: 'off',
scrollbar: { vertical: 'auto', horizontal: 'auto', verticalScrollbarSize: 8, horizontalScrollbarSize: 8 },
scrollbar: { vertical: 'hidden', horizontal: 'auto', verticalScrollbarSize: 0, horizontalScrollbarSize: 8 },
hover: { enabled: false },
folding: false,
selectionHighlight: false,
@ -1916,20 +1899,92 @@ export const VoidDiffEditor = ({ uri, searchReplaceBlocks, language }: { uri?: a
overviewRulerBorder: false,
glyphMargin: false,
stickyScroll: { enabled: false },
scrollBeyondLastLine: false,
renderGutterMenu: false,
renderIndicators: false,
},
{ originalEditor: { isSimpleWidget: true }, modifiedEditor: { isSimpleWidget: true } }
);
editor.setModel({ original: originalModel, modified: modifiedModel });
editor.layout();
// Calculate the height based on content
const updateHeight = () => {
const contentHeight = Math.max(
originalModel.getLineCount() * 19, // approximate line height
modifiedModel.getLineCount() * 19
) + 19 * 2 + 1; // add padding
// Set reasonable min/max heights
const height = Math.min(Math.max(contentHeight, 100), 300);
if (divRef.current) {
divRef.current.style.height = `${height}px`;
editor.layout();
}
};
updateHeight();
editorRef.current = editor;
// Update height when content changes
const disposable1 = originalModel.onDidChangeContent(() => updateHeight());
const disposable2 = modifiedModel.onDidChangeContent(() => updateHeight());
return () => {
disposable1.dispose();
disposable2.dispose();
editor.dispose();
editorRef.current = null;
};
}, [originalModel, modifiedModel, instantiationService]);
return (
<div className="w-full h-[300px] bg-void-bg-3 rounded" ref={divRef} />
<div className="w-full bg-void-bg-3 @@bg-editor-style-override" ref={divRef} />
);
};
/**
* ToolDiffEditor mounts a native VSCode DiffEditorWidget to show a diff between original and modified code blocks.
* Props:
* - uri: URI of the file (for language detection, etc)
* - searchReplaceBlocks: string in search/replace format (from LLM)
* - language?: string (optional, fallback to 'plaintext')
*/
export const VoidDiffEditor = ({ uri, searchReplaceBlocks, language }: { uri?: any, searchReplaceBlocks: string, language?: string }) => {
const accessor = useAccessor();
const languageService = accessor.get('ILanguageService');
// Extract all blocks
const blocks = extractSearchReplaceBlocks(searchReplaceBlocks);
// Use detectLanguage for language detection if not provided
let lang = language;
if (!lang && blocks.length > 0) {
lang = detectLanguage(languageService, { uri: uri ?? null, fileContents: blocks[0].orig });
}
// If no blocks, show empty state
if (blocks.length === 0) {
return <div className="w-full p-4 text-void-fg-4 text-sm">No changes found</div>;
}
// Display all blocks
return (
<div className="w-full flex flex-col gap-2">
{blocks.map((block, index) => (
<div key={index} className="w-full">
{blocks.length > 1 && (
<div className="text-void-fg-4 text-xs mb-1 px-1">
Change {index + 1} of {blocks.length}
</div>
)}
<SingleDiffEditor block={block} lang={lang} />
</div>
))}
</div>
);
};

View file

@ -456,7 +456,7 @@ export const ModelDump = ({ filteredProviders }: { filteredProviders?: ProviderN
{/* left part is width:full */}
<div className={`flex flex-grow items-center gap-4`}>
<span className='w-full max-w-32'>{isNewProviderName ? providerTitle : ''}</span>
<span className='w-fit truncate'>{modelName}</span>
<span className='w-fit max-w-[400px] truncate'>{modelName}</span>
</div>
{/* right part is anything that fits */}
@ -495,7 +495,7 @@ export const ModelDump = ({ filteredProviders }: { filteredProviders?: ProviderN
{/* X button */}
<div className={`w-5 flex items-center justify-center`}>
{type === 'default' || type === 'autodetected' ? null : <button
{type === 'default' || type === 'autodetected' ? null : <button
onClick={() => { settingsStateService.deleteModel(providerName, modelName); }}
data-tooltip-id='void-tooltip'
data-tooltip-place='right'