mirror of
https://github.com/voideditor/void
synced 2026-05-23 17:38:23 +00:00
Merge pull request #197 from voideditor/model-selection
Fix line indexing for CtrlK
This commit is contained in:
commit
a3d3309b9d
9 changed files with 149 additions and 95 deletions
|
|
@ -43,19 +43,19 @@ First, run `npm install -g node-gyp`. Then:
|
|||
|
||||
### Building Void
|
||||
|
||||
To build Void, open `void/` inside VSCode. Then:
|
||||
To build Void, open `void/` inside VSCode. Then open your terminal and run:
|
||||
|
||||
1. `npm install` to install all dependencies.
|
||||
2. `npm run watchreact` to build Void's browser dependencies like React.
|
||||
3. Build.
|
||||
3. Build Void.
|
||||
- Press <kbd>Cmd+Shift+B</kbd> (Mac).
|
||||
- Press <kbd>Ctrl+Shift+B</kbd> (Windows/Linux).
|
||||
- This step can take ~5 min. The build is done when you see two check marks.
|
||||
4. Run.
|
||||
4. Run Void.
|
||||
- Run `./scripts/code.sh` (Mac/Linux).
|
||||
- Run `./scripts/code.bat` (Windows).
|
||||
- This command should open up the built IDE. You can always press <kbd>Ctrl+R</kbd> (<kbd>Cmd+R</kbd>) inside the new window to see changes without re-building, or press or <kbd>Ctrl+Shift+P</kbd> in the new window and run "Reload Window".
|
||||
|
||||
- If you would like to reset Void back to its default settings, you can run `./scripts/code.sh --user-data-dir ./.tmp/user-data --extensions-dir ./.tmp/extensions` (mac). This will save all data and extensions to the `.tmp` folder. You can delete this folder to reset your settings.
|
||||
|
||||
#### Building Void from Terminal
|
||||
|
||||
|
|
|
|||
|
|
@ -144,8 +144,8 @@ export const defaultProviderSettings = {
|
|||
export type ProviderName = keyof typeof defaultProviderSettings
|
||||
export const providerNames = Object.keys(defaultProviderSettings) as ProviderName[]
|
||||
|
||||
export const localProviderNames: ProviderName[] = ['ollama'] // all local names
|
||||
export const nonlocalProviderNames = providerNames.filter((name) => !localProviderNames.includes(name)) // all non-local names
|
||||
export const localProviderNames = ['ollama', 'openAICompatible'] satisfies ProviderName[] // all local names
|
||||
export const nonlocalProviderNames = providerNames.filter((name) => !(localProviderNames as string[]).includes(name)) // all non-local names
|
||||
|
||||
type CustomSettingName = UnionOfKeys<typeof defaultProviderSettings[ProviderName]>
|
||||
type CustomProviderSettings<providerName extends ProviderName> = {
|
||||
|
|
@ -379,7 +379,7 @@ export const featureNames = ['Ctrl+L', 'Ctrl+K', 'Autocomplete'] as const
|
|||
|
||||
|
||||
// the models of these can be refreshed (in theory all can, but not all should)
|
||||
export const refreshableProviderNames = ['ollama', 'openAICompatible'] satisfies ProviderName[]
|
||||
export const refreshableProviderNames = localProviderNames
|
||||
export type RefreshableProviderName = typeof refreshableProviderNames[number]
|
||||
|
||||
|
||||
|
|
@ -405,7 +405,7 @@ type FeatureFlagDisplayInfo = {
|
|||
export const displayInfoOfFeatureFlag = (featureFlag: FeatureFlagName): FeatureFlagDisplayInfo => {
|
||||
if (featureFlag === 'autoRefreshModels') {
|
||||
return {
|
||||
description: `Automatically detect local providers and models (like Ollama).`, // ${`refreshableProviderNames.map(providerName => titleOfProviderName(providerName)).join(', ')`}
|
||||
description: `Automatically detect local providers and models (${refreshableProviderNames.map(providerName => displayInfoOfProviderName(providerName).title).join(', ')}).`,
|
||||
}
|
||||
}
|
||||
throw new Error(`featureFlagInfo: Unknown feature flag: "${featureFlag}"`)
|
||||
|
|
|
|||
|
|
@ -117,7 +117,7 @@ type CtrlKZone = {
|
|||
editorId: string; // the editor the input lives on
|
||||
|
||||
_mountInfo: null | {
|
||||
inputBox: InputBox | null; // the input box that lives in the zone
|
||||
inputBoxRef: { current: InputBox | null }; // the input box that lives in the zone
|
||||
dispose: () => void;
|
||||
refresh: () => void;
|
||||
}
|
||||
|
|
@ -136,7 +136,7 @@ type DiffZone = {
|
|||
} | {
|
||||
isStreaming: false;
|
||||
streamRequestIdRef?: undefined;
|
||||
line: null;
|
||||
line?: undefined;
|
||||
};
|
||||
editorId?: undefined;
|
||||
} & CommonZoneProps
|
||||
|
|
@ -210,9 +210,8 @@ class InlineDiffsService extends Disposable implements IInlineDiffsService {
|
|||
this._register(
|
||||
model.onDidChangeContent(e => {
|
||||
// it's as if we just called _write, now all we need to do is realign and refresh
|
||||
const uri = model.uri
|
||||
|
||||
if (this.weAreWriting) return
|
||||
const uri = model.uri
|
||||
this._onUserChangeContent(uri, e)
|
||||
})
|
||||
)
|
||||
|
|
@ -244,6 +243,7 @@ class InlineDiffsService extends Disposable implements IInlineDiffsService {
|
|||
private _onInternalChangeContent(uri: URI, { shouldRealign }: { shouldRealign: false | { newText: string, oldRange: IRange } }) {
|
||||
if (shouldRealign) {
|
||||
const { newText, oldRange } = shouldRealign
|
||||
console.log('realiging', newText, oldRange)
|
||||
this._realignAllDiffAreasLines(uri, newText, oldRange)
|
||||
}
|
||||
this._refreshStylesAndDiffsInURI(uri)
|
||||
|
|
@ -329,7 +329,7 @@ class InlineDiffsService extends Disposable implements IInlineDiffsService {
|
|||
|
||||
let zoneId: string | null = null
|
||||
let viewZone_: IViewZone | null = null
|
||||
let inputBox_: InputBox | null = null
|
||||
const inputBoxRef: { current: InputBox | null } = { current: null }
|
||||
|
||||
const itemId = this._consistentEditorItemService.addToEditor(editor, () => {
|
||||
const domNode = document.createElement('div');
|
||||
|
|
@ -352,7 +352,7 @@ class InlineDiffsService extends Disposable implements IInlineDiffsService {
|
|||
mountCtrlK(domNode, accessor, {
|
||||
diffareaid: ctrlKZone.diffareaid,
|
||||
onGetInputBox: (inputBox) => {
|
||||
inputBox_ = inputBox
|
||||
inputBoxRef.current = inputBox
|
||||
// if it's mounting for the first time, focus it
|
||||
if (!(ctrlKZone.diffareaid in this.mostRecentTextOfCtrlKZoneId)) { // detect first mount this way (a hack)
|
||||
this.mostRecentTextOfCtrlKZoneId[ctrlKZone.diffareaid] = undefined
|
||||
|
|
@ -381,10 +381,8 @@ class InlineDiffsService extends Disposable implements IInlineDiffsService {
|
|||
})
|
||||
})
|
||||
|
||||
|
||||
|
||||
return {
|
||||
inputBox: inputBox_,
|
||||
inputBoxRef,
|
||||
refresh: () => editor.changeViewZones(accessor => {
|
||||
if (zoneId && viewZone_) {
|
||||
viewZone_.afterLineNumber = ctrlKZone.startLine - 1
|
||||
|
|
@ -394,7 +392,7 @@ class InlineDiffsService extends Disposable implements IInlineDiffsService {
|
|||
dispose: () => {
|
||||
this._consistentEditorItemService.removeFromEditor(itemId)
|
||||
},
|
||||
}
|
||||
} satisfies CtrlKZone['_mountInfo']
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -405,6 +403,7 @@ class InlineDiffsService extends Disposable implements IInlineDiffsService {
|
|||
if (diffArea.type !== 'CtrlKZone') continue
|
||||
if (!diffArea._mountInfo) {
|
||||
diffArea._mountInfo = this._addCtrlKZoneInput(diffArea)
|
||||
console.log('MOUNTED', diffArea.diffareaid)
|
||||
}
|
||||
else {
|
||||
diffArea._mountInfo.refresh()
|
||||
|
|
@ -579,10 +578,7 @@ class InlineDiffsService extends Disposable implements IInlineDiffsService {
|
|||
type: 'DiffZone',
|
||||
_diffOfId: {},
|
||||
_URI: uri,
|
||||
_streamState: {
|
||||
isStreaming: false,
|
||||
line: null,
|
||||
} as const,
|
||||
_streamState: { isStreaming: false },
|
||||
_removeStylesFns: new Set(),
|
||||
}
|
||||
}
|
||||
|
|
@ -740,17 +736,14 @@ class InlineDiffsService extends Disposable implements IInlineDiffsService {
|
|||
for (const diffareaid of this.diffAreasOfURI[model.uri.fsPath] || []) {
|
||||
const diffArea = this.diffAreaOfId[diffareaid]
|
||||
|
||||
console.log('DA', diffArea.startLine, diffArea.endLine)
|
||||
console.log('CHANGE', startLine, endLine)
|
||||
|
||||
// if the diffArea is entirely above the range, it is not affected
|
||||
if (diffArea.endLine < startLine) {
|
||||
// console.log('DA FULLY ABOVE (doing nothing)')
|
||||
// console.log('CHANGE FULLY BELOW DA (doing nothing)')
|
||||
continue
|
||||
}
|
||||
// if a diffArea is entirely below the range, shift the diffArea up/down by the delta amount of newlines
|
||||
else if (endLine < diffArea.startLine) {
|
||||
// console.log('DA FULLY BELOW')
|
||||
// console.log('CHANGE FULLY ABOVE DA')
|
||||
const changedRangeHeight = endLine - startLine + 1
|
||||
const deltaNewlines = newTextHeight - changedRangeHeight
|
||||
diffArea.startLine += deltaNewlines
|
||||
|
|
@ -771,7 +764,7 @@ class InlineDiffsService extends Disposable implements IInlineDiffsService {
|
|||
}
|
||||
// if the change contains only the diffArea's top
|
||||
else if (startLine < diffArea.startLine && diffArea.startLine <= endLine) {
|
||||
// console.log('TOP ONLY')
|
||||
// console.log('CHANGE CONTAINS TOP OF DA ONLY')
|
||||
const numOverlappingLines = endLine - diffArea.startLine + 1
|
||||
const numRemainingLinesInDA = diffArea.endLine - diffArea.startLine + 1 - numOverlappingLines
|
||||
const newHeight = (numRemainingLinesInDA - 1) + (newTextHeight - 1) + 1
|
||||
|
|
@ -780,7 +773,7 @@ class InlineDiffsService extends Disposable implements IInlineDiffsService {
|
|||
}
|
||||
// if the change contains only the diffArea's bottom
|
||||
else if (startLine <= diffArea.endLine && diffArea.endLine < endLine) {
|
||||
// console.log('BOTTOM ONLY')
|
||||
// console.log('CHANGE CONTAINS BOTTOM OF DA ONLY')
|
||||
const numOverlappingLines = diffArea.endLine - startLine + 1
|
||||
diffArea.endLine += newTextHeight - numOverlappingLines
|
||||
}
|
||||
|
|
@ -823,47 +816,41 @@ class InlineDiffsService extends Disposable implements IInlineDiffsService {
|
|||
|
||||
// if streaming, use diffs to figure out where to write new code
|
||||
// these are two different coordinate systems - new and old line number
|
||||
let newFileEndLine: number // get new[0...newStoppingPoint] with line=newStoppingPoint highlighted
|
||||
let originalCodeStartLine: number // get original[oldStartingPoint...]
|
||||
let newCodeEndLine: number // get file[diffArea.startLine...newFileEndLine] with line=newFileEndLine highlighted
|
||||
let originalCodeStartLine: number // get original[oldStartingPoint...] (line in the original code, so starts at 1)
|
||||
|
||||
const lastDiff = computedDiffs.pop()
|
||||
|
||||
if (!lastDiff) {
|
||||
console.log('!lastDiff')
|
||||
// if the writing is identical so far, display no changes
|
||||
newFileEndLine = diffZone.startLine
|
||||
originalCodeStartLine = 1
|
||||
newCodeEndLine = 1
|
||||
}
|
||||
else {
|
||||
if (lastDiff.type === 'insertion') {
|
||||
newFileEndLine = lastDiff.endLine
|
||||
originalCodeStartLine = lastDiff.originalStartLine
|
||||
}
|
||||
else if (lastDiff.type === 'deletion') {
|
||||
newFileEndLine = lastDiff.startLine
|
||||
originalCodeStartLine = lastDiff.originalStartLine
|
||||
}
|
||||
else if (lastDiff.type === 'edit') {
|
||||
newFileEndLine = lastDiff.endLine
|
||||
originalCodeStartLine = lastDiff.originalStartLine
|
||||
}
|
||||
else {
|
||||
originalCodeStartLine = lastDiff.originalStartLine
|
||||
if (lastDiff.type === 'insertion' || lastDiff.type === 'edit')
|
||||
newCodeEndLine = lastDiff.endLine
|
||||
else if (lastDiff.type === 'deletion')
|
||||
newCodeEndLine = lastDiff.startLine
|
||||
else
|
||||
throw new Error(`Void: diff.type not recognized on: ${lastDiff}`)
|
||||
}
|
||||
}
|
||||
|
||||
diffZone._streamState.line = newFileEndLine
|
||||
|
||||
// lines are 1-indexed
|
||||
const newFileTop = llmText.split('\n').slice(diffZone.startLine, (newFileEndLine - 1)).join('\n')
|
||||
const oldFileBottom = diffZone.originalCode.split('\n').slice((originalCodeStartLine - 1), Infinity).join('\n')
|
||||
const newCodeTop = llmText.split('\n').slice(0, (newCodeEndLine - 1) + 1).join('\n')
|
||||
const oldFileBottom = diffZone.originalCode.split('\n').slice((originalCodeStartLine - 1) + 1, Infinity).join('\n')
|
||||
|
||||
const newCode = `${newFileTop}\n${oldFileBottom}`
|
||||
const newCode = `${newCodeTop}\n${oldFileBottom}`
|
||||
|
||||
this._writeText(uri, newCode,
|
||||
{ startLineNumber: diffZone.startLine, startColumn: 1, endLineNumber: diffZone.endLine, endColumn: Number.MAX_SAFE_INTEGER, }, // 1-indexed
|
||||
{ shouldRealignDiffAreas: true }
|
||||
)
|
||||
|
||||
// add diffZone.startLine to convert to right coordinate system (line in file, not in diffarea)
|
||||
diffZone._streamState.line = (diffZone.startLine - 1) + newCodeEndLine
|
||||
|
||||
return computedDiffs
|
||||
|
||||
|
|
@ -871,6 +858,54 @@ class InlineDiffsService extends Disposable implements IInlineDiffsService {
|
|||
|
||||
|
||||
|
||||
// // if streaming, use diffs to figure out where to write new code
|
||||
// // these are two different coordinate systems - new and old line number
|
||||
// let newFileEndLine: number // get new[0...newStoppingPoint] with line=newStoppingPoint highlighted
|
||||
// let originalCodeStartLine: number // get original[oldStartingPoint...]
|
||||
|
||||
// const lastDiff = computedDiffs.pop()
|
||||
|
||||
// if (!lastDiff) {
|
||||
// // if the writing is identical so far, display no changes
|
||||
// newFileEndLine = diffZone.startLine
|
||||
// originalCodeStartLine = 1
|
||||
// }
|
||||
// else {
|
||||
// if (lastDiff.type === 'insertion') {
|
||||
// newFileEndLine = lastDiff.endLine
|
||||
// originalCodeStartLine = lastDiff.originalStartLine
|
||||
// }
|
||||
// else if (lastDiff.type === 'deletion') {
|
||||
// newFileEndLine = lastDiff.startLine
|
||||
// originalCodeStartLine = lastDiff.originalStartLine
|
||||
// }
|
||||
// else if (lastDiff.type === 'edit') {
|
||||
// newFileEndLine = lastDiff.endLine
|
||||
// originalCodeStartLine = lastDiff.originalStartLine
|
||||
// }
|
||||
// else {
|
||||
// throw new Error(`Void: diff.type not recognized on: ${lastDiff}`)
|
||||
// }
|
||||
// }
|
||||
|
||||
// diffZone._streamState.line = newFileEndLine
|
||||
|
||||
// // lines are 1-indexed
|
||||
// const newFileTop = llmText.split('\n').slice(diffZone.startLine, (newFileEndLine - 1)).join('\n')
|
||||
// const oldFileBottom = diffZone.originalCode.split('\n').slice((originalCodeStartLine - 1), Infinity).join('\n')
|
||||
|
||||
// const newCode = `${newFileTop}\n${oldFileBottom}`
|
||||
|
||||
// this._writeText(uri, newCode,
|
||||
// { startLineNumber: diffZone.startLine, startColumn: 1, endLineNumber: diffZone.endLine, endColumn: Number.MAX_SAFE_INTEGER, }, // 1-indexed
|
||||
// { shouldRealignDiffAreas: true }
|
||||
// )
|
||||
|
||||
|
||||
// return computedDiffs
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -887,7 +922,7 @@ class InlineDiffsService extends Disposable implements IInlineDiffsService {
|
|||
if (diffArea.type !== 'CtrlKZone') continue
|
||||
const noOverlap = diffArea.startLine > endLine || diffArea.endLine < startLine
|
||||
if (!noOverlap) {
|
||||
setTimeout(() => diffArea._mountInfo?.inputBox?.focus(), 0)
|
||||
setTimeout(() => diffArea._mountInfo?.inputBoxRef.current?.focus(), 0)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
|
@ -904,7 +939,6 @@ class InlineDiffsService extends Disposable implements IInlineDiffsService {
|
|||
_mountInfo: null,
|
||||
}
|
||||
const ctrlKZone = this._addDiffArea(adding)
|
||||
|
||||
this._refreshStylesAndDiffsInURI(uri)
|
||||
|
||||
onFinishEdit()
|
||||
|
|
@ -919,6 +953,7 @@ class InlineDiffsService extends Disposable implements IInlineDiffsService {
|
|||
const uri = ctrlKZone._URI
|
||||
const { onFinishEdit } = this._addToHistory(uri)
|
||||
this._deleteCtrlKZone(ctrlKZone)
|
||||
this._refreshStylesAndDiffsInURI(uri)
|
||||
onFinishEdit()
|
||||
}
|
||||
|
||||
|
|
@ -983,14 +1018,13 @@ class InlineDiffsService extends Disposable implements IInlineDiffsService {
|
|||
startLine = startLine_
|
||||
endLine = endLine_
|
||||
|
||||
if (!_mountInfo?.inputBox) return
|
||||
userMessage = _mountInfo.inputBox?.value
|
||||
if (!_mountInfo?.inputBoxRef.current) return
|
||||
userMessage = _mountInfo.inputBoxRef.current?.value
|
||||
}
|
||||
else {
|
||||
throw new Error(`Void: diff.type not recognized on: ${featureName}`)
|
||||
}
|
||||
|
||||
|
||||
const currentFileStr = this._readURI(uri)
|
||||
if (currentFileStr === null) return
|
||||
const originalCode = currentFileStr.split('\n').slice((startLine - 1), (endLine - 1) + 1).join('\n')
|
||||
|
|
@ -1055,7 +1089,7 @@ class InlineDiffsService extends Disposable implements IInlineDiffsService {
|
|||
const latestOriginalFileStart: IPosition = { lineNumber: 1, column: 1 }
|
||||
|
||||
const onDone = () => {
|
||||
diffZone._streamState = { isStreaming: false, line: null }
|
||||
diffZone._streamState = { isStreaming: false, }
|
||||
|
||||
if (featureName === 'Ctrl+K') {
|
||||
const ctrlKZone = this.diffAreaOfId[opts.diffareaid] as CtrlKZone
|
||||
|
|
@ -1111,11 +1145,7 @@ class InlineDiffsService extends Disposable implements IInlineDiffsService {
|
|||
|
||||
this._llmMessageService.abort(streamRequestId)
|
||||
|
||||
diffZone._streamState = {
|
||||
isStreaming: false,
|
||||
streamRequestIdRef: undefined,
|
||||
line: null
|
||||
}
|
||||
diffZone._streamState = { isStreaming: false, }
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,13 +4,42 @@
|
|||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { spawn, execSync } from 'child_process';
|
||||
// Added lines below
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import { fileURLToPath } from 'url';
|
||||
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = path.dirname(__filename);
|
||||
const __void_name = 'void'
|
||||
|
||||
// hack to refresh styles automatically
|
||||
function saveStylesFile() {
|
||||
setTimeout(() => {
|
||||
try {
|
||||
// Find "void" in __dirname and use that as our base:
|
||||
const voidIdx = __dirname.indexOf(__void_name);
|
||||
const baseDir = __dirname.substring(0, voidIdx + __void_name.length);
|
||||
const target = path.join(
|
||||
baseDir,
|
||||
'src/vs/workbench/contrib/void/browser/react/src2/styles.css'
|
||||
);
|
||||
|
||||
// Or re-write with the same content:
|
||||
const content = fs.readFileSync(target, 'utf8');
|
||||
fs.writeFileSync(target, content, 'utf8');
|
||||
console.log('[scope-tailwind] Force-saved styles.css');
|
||||
} catch (err) {
|
||||
console.error('[scope-tailwind] Error saving styles.css:', err);
|
||||
}
|
||||
}, 5000);
|
||||
}
|
||||
|
||||
const args = process.argv.slice(2);
|
||||
const isWatch = args.includes('--watch') || args.includes('-w');
|
||||
|
||||
if (isWatch) {
|
||||
// Watch mode
|
||||
// Create a watcher for scope-tailwind using nodemon
|
||||
const scopeTailwindWatcher = spawn('npx', [
|
||||
'nodemon',
|
||||
'--watch', 'src',
|
||||
|
|
@ -19,15 +48,17 @@ if (isWatch) {
|
|||
'npx scope-tailwind ./src -o src2/ -s void-scope -c styles.css -p "void-"'
|
||||
]);
|
||||
|
||||
// Create a watcher for tsup in watch mode
|
||||
const tsupWatcher = spawn('npx', [
|
||||
'tsup',
|
||||
'--watch'
|
||||
]);
|
||||
|
||||
// Handle scope-tailwind watcher output
|
||||
scopeTailwindWatcher.stdout.on('data', (data) => {
|
||||
console.log(`[scope-tailwind] ${data}`);
|
||||
// If the output mentions "styles.css", trigger the save:
|
||||
if (data.toString().includes('styles.css')) {
|
||||
saveStylesFile();
|
||||
}
|
||||
});
|
||||
|
||||
scopeTailwindWatcher.stderr.on('data', (data) => {
|
||||
|
|
|
|||
|
|
@ -70,7 +70,6 @@ export const BlockCode = ({ text, buttonsOnHover, language }: { text: string, bu
|
|||
|
||||
return (<>
|
||||
<div className={`relative group w-full bg-vscode-editor-bg overflow-hidden isolate`}>
|
||||
|
||||
{buttonsOnHover === null ? null : (
|
||||
<div className="z-[1] absolute top-0 right-0 opacity-0 group-hover:opacity-100 duration-200">
|
||||
<div className={`flex space-x-2 ${isSingleLine ? '' : 'p-2'}`}>{buttonsOnHover}</div>
|
||||
|
|
|
|||
|
|
@ -45,19 +45,18 @@ const CodeButtonsOnHover = ({ text }: { text: string }) => {
|
|||
})
|
||||
}, [inlineDiffService])
|
||||
|
||||
|
||||
const isSingleLine = !text.includes('\n')
|
||||
|
||||
return <>
|
||||
<button
|
||||
className={`${isSingleLine ? '' : 'p-1'} text-xs hover:brightness-110 bg-vscode-editor-bg border border-vscode-input-border rounded text-xs text-vscode-input-fg`}
|
||||
className={`${isSingleLine ? '' : 'p-1'} text-xs hover:brightness-110 bg-vscode-input-bg border border-vscode-input-border rounded text-xs text-vscode-input-fg`}
|
||||
onClick={onCopy}
|
||||
>
|
||||
{copyButtonState}
|
||||
</button>
|
||||
<button
|
||||
// btn btn-secondary btn-sm border text-xs text-vscode-input-fg border-vscode-input-border rounded
|
||||
className={`${isSingleLine ? '' : 'p-1'} text-xs hover:brightness-110 bg-vscode-editor-bg border border-vscode-input-border rounded text-xs text-vscode-input-fg`}
|
||||
className={`${isSingleLine ? '' : 'p-1'} text-xs hover:brightness-110 bg-vscode-input-bg border border-vscode-input-border rounded text-xs text-vscode-input-fg`}
|
||||
onClick={onApply}
|
||||
>
|
||||
Apply
|
||||
|
|
|
|||
|
|
@ -276,11 +276,11 @@ export const SelectedFiles = (
|
|||
>
|
||||
{selections.map((selection, i) => {
|
||||
|
||||
const showSelectionText = !!(selection.selectionStr && selectionIsOpened[i])
|
||||
const isThisSelectionOpened = !!(selection.selectionStr && selectionIsOpened[i])
|
||||
|
||||
return (
|
||||
<div key={i} // container for `selectionSummary` and `selectionText`
|
||||
className={`${showSelectionText ? 'w-full' : ''}`}
|
||||
className={`${isThisSelectionOpened ? 'w-full' : ''}`}
|
||||
>
|
||||
{/* selection summary */}
|
||||
<div
|
||||
|
|
@ -346,8 +346,8 @@ export const SelectedFiles = (
|
|||
|
||||
</div>
|
||||
{/* selection text */}
|
||||
{showSelectionText &&
|
||||
<div className='w-full p-1 rounded-sm border-vscode-editor-border bg-vscode-sidebar-bg'>
|
||||
{isThisSelectionOpened &&
|
||||
<div className='w-full p-1 rounded-sm border-vscode-editor-border'>
|
||||
<BlockCode text={selection.selectionStr!} language={getLanguageFromFileName(selection.fileURI.path)} />
|
||||
</div>
|
||||
}
|
||||
|
|
@ -383,19 +383,15 @@ const ChatBubble = ({ chatMessage, isLoading }: {
|
|||
}
|
||||
|
||||
return <div
|
||||
// align chatbubble accoridng to role
|
||||
className={`
|
||||
${role === 'user' ? 'self-end' : 'self-start'}
|
||||
${role === 'assistant' ? 'w-full' : ''}
|
||||
`}
|
||||
// style + align chatbubble accoridng to role
|
||||
className={`p-2 mx-2 text-left space-y-2 rounded-lg max-w-full
|
||||
${role === 'user' ? 'self-end' : 'self-start'}
|
||||
${role === 'user' ? 'bg-vscode-input-bg text-vscode-input-fg' : ''}
|
||||
${role === 'assistant' ? 'w-full' : ''}
|
||||
`}
|
||||
>
|
||||
<div
|
||||
// style chatbubble
|
||||
className={`p-2 mx-2 text-left space-y-2 rounded-lg ${role === 'user' ? 'bg-vscode-input-bg text-vscode-input-fg' : ''} max-w-full overflow-auto`}
|
||||
>
|
||||
{chatbubbleContents}
|
||||
{isLoading && <IconLoading className='opacity-50 text-sm' />}
|
||||
</div>
|
||||
{chatbubbleContents}
|
||||
{isLoading && <IconLoading className='opacity-50 text-sm' />}
|
||||
</div>
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -301,7 +301,7 @@ export const VoidCodeEditor = ({ initValue, language }: { initValue: string, lan
|
|||
|
||||
return <div ref={divRef}>
|
||||
<WidgetComponent
|
||||
className='relative z-0 text-sm !bg-vscode-editor-bg'
|
||||
className='relative z-0 text-sm bg-vscode-editor-bg'
|
||||
ctor={useCallback((container) =>
|
||||
instantiationService.createInstance(
|
||||
CodeEditorWidget,
|
||||
|
|
|
|||
|
|
@ -195,7 +195,7 @@ export const ModelDump = () => {
|
|||
|
||||
const disabled = !providerEnabled
|
||||
|
||||
return <div key={`${modelName}${providerName}`} className={`flex items-center justify-between gap-4 hover:bg-black/10 dark:hover:bg-gray-300/10 py-1 px-3 rounded-sm overflow-hidden cursor-default ${isNewProviderName ? 'mt-4' : ''}`}>
|
||||
return <div key={`${modelName}${providerName}`} className={`flex items-center justify-between gap-4 hover:bg-black/10 dark:hover:bg-gray-300/10 py-1 px-3 rounded-sm overflow-hidden cursor-default truncate ${isNewProviderName ? 'mt-4' : ''}`}>
|
||||
{/* left part is width:full */}
|
||||
<div className={`w-full flex items-center gap-4`}>
|
||||
<span className='min-w-40'>{isNewProviderName ? displayInfoOfProviderName(providerName).title : ''}</span>
|
||||
|
|
@ -204,7 +204,7 @@ export const ModelDump = () => {
|
|||
</div>
|
||||
{/* right part is anything that fits */}
|
||||
<div className='w-fit flex items-center gap-4'>
|
||||
<span className='opacity-50 whitespace-nowrap'>{isAutodetected ? '(detected locally)' : isDefault ? '' : '(custom model)'}</span>
|
||||
<span className='opacity-50'>{isAutodetected ? '(detected locally)' : isDefault ? '' : '(custom model)'}</span>
|
||||
|
||||
<VoidSwitch
|
||||
value={disabled ? false : !isHidden}
|
||||
|
|
@ -420,13 +420,12 @@ export const Settings = () => {
|
|||
<h2 className={`text-3xl mb-2`}>Local Providers</h2>
|
||||
{/* <h3 className={`text-md opacity-50 mb-2`}>{`Keep your data private by hosting AI locally on your computer.`}</h3> */}
|
||||
{/* <h3 className={`text-md opacity-50 mb-2`}>{`Instructions:`}</h3> */}
|
||||
<h3 className={`text-md opacity-50 mb-2`}>{`Void can access any model that you host locally.`}</h3>
|
||||
<div className='pl-4 select-text'>
|
||||
<h4 className={`text-xs opacity-50 mb-2`}><ChatMarkdownRender string={`1. Download [Ollama](https://ollama.com/download).`} /></h4>
|
||||
<h4 className={`text-xs opacity-50 mb-2`}><ChatMarkdownRender string={`2. Open your terminal.`} /></h4>
|
||||
<h4 className={`text-xs opacity-50 mb-2`}><ChatMarkdownRender string={`3. Run \`ollama run llama3.1\`. This installs Meta's llama model which is competitive with GPT-series models, and requires 5GB of memory.`} /></h4>
|
||||
<h4 className={`text-xs opacity-50 mb-2`}><ChatMarkdownRender string={`4. Run \`ollama run qwen2.5-coder:1.5b\`. This is a faster autocomplete model and requires 1GB of memory.`} /></h4>
|
||||
<h4 className={`text-xs opacity-50 mb-2`}><ChatMarkdownRender string={`5. Void will automatically detect your Ollama models. You can customize the endpoint and models below.`} /></h4>
|
||||
<h3 className={`text-md mb-2`}>{`Void can access any model that you host locally. By default, we automatically detect your local models.`}</h3>
|
||||
<div className='pl-4 select-text opacity-50'>
|
||||
<h4 className={`text-xs mb-2`}><ChatMarkdownRender string={`1. Download [Ollama](https://ollama.com/download).`} /></h4>
|
||||
<h4 className={`text-xs mb-2`}><ChatMarkdownRender string={`2. Open your terminal.`} /></h4>
|
||||
<h4 className={`text-xs mb-2`}><ChatMarkdownRender string={`3. Run \`ollama run llama3.1\`. This installs Meta's llama model which is competitive with GPT-series models. It requires 5GB of memory.`} /></h4>
|
||||
<h4 className={`text-xs mb-2`}><ChatMarkdownRender string={`4. Run \`ollama run qwen2.5-coder:1.5b\`. This is a faster autocomplete model and requires 1GB of memory.`} /></h4>
|
||||
{/* TODO we should create UI for downloading models without user going into terminal */}
|
||||
</div>
|
||||
|
||||
|
|
@ -435,7 +434,7 @@ export const Settings = () => {
|
|||
</ErrorBoundary>
|
||||
|
||||
<h2 className={`text-3xl mb-2 mt-16`}>More Providers</h2>
|
||||
<h3 className={`text-md opacity-50 mb-2`}>{`Void can also access models like ChatGPT and Claude. We recommend using Anthropic or OpenAI.`}</h3>
|
||||
<h3 className={`text-md mb-2`}>{`Void can also access models like ChatGPT and Claude. We recommend using Anthropic or OpenAI.`}</h3>
|
||||
{/* <h3 className={`text-md opacity-50 mb-2`}>{`Access models like ChatGPT and Claude. We recommend using Anthropic or OpenAI as providers, or Groq as a faster alternative.`}</h3> */}
|
||||
<ErrorBoundary>
|
||||
<VoidProviderSettings providerNames={nonlocalProviderNames} />
|
||||
|
|
|
|||
Loading…
Reference in a new issue