mirror of
https://github.com/voideditor/void
synced 2026-05-24 09:58:23 +00:00
Merge remote-tracking branch 'origin/main' into model-selection
This commit is contained in:
commit
3241178238
9 changed files with 300 additions and 78 deletions
78
src/vs/workbench/contrib/void/browser/fileService.ts
Normal file
78
src/vs/workbench/contrib/void/browser/fileService.ts
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
import { localize2 } from '../../../../nls.js';
|
||||
import { URI } from '../../../../base/common/uri.js';
|
||||
import { Action2, registerAction2, MenuId } from '../../../../platform/actions/common/actions.js';
|
||||
import { ServicesAccessor } from '../../../../editor/browser/editorExtensions.js';
|
||||
import { INotificationService } from '../../../../platform/notification/common/notification.js';
|
||||
import { IFileService } from '../../../../platform/files/common/files.js';
|
||||
import { IClipboardService } from '../../../../platform/clipboard/common/clipboardService.js';
|
||||
import { IDirectoryStrService } from '../common/directoryStrService.js';
|
||||
import { messageOfSelection } from '../common/prompt/prompts.js';
|
||||
import { IVoidModelService } from '../common/voidModelService.js';
|
||||
|
||||
|
||||
|
||||
class FilePromptActionService extends Action2 {
|
||||
private static readonly VOID_COPY_FILE_PROMPT_ID = 'void.copyfileprompt'
|
||||
|
||||
constructor() {
|
||||
super({
|
||||
id: FilePromptActionService.VOID_COPY_FILE_PROMPT_ID,
|
||||
title: localize2('voidCopyPrompt', 'Void: Copy Prompt'),
|
||||
menu: [{
|
||||
id: MenuId.ExplorerContext,
|
||||
group: '8_void',
|
||||
order: 1,
|
||||
}]
|
||||
});
|
||||
}
|
||||
|
||||
async run(accessor: ServicesAccessor, uri: URI): Promise<void> {
|
||||
try {
|
||||
const fileService = accessor.get(IFileService);
|
||||
const clipboardService = accessor.get(IClipboardService)
|
||||
const directoryStrService = accessor.get(IDirectoryStrService)
|
||||
const voidModelService = accessor.get(IVoidModelService)
|
||||
|
||||
const stat = await fileService.stat(uri)
|
||||
|
||||
const folderOpts = {
|
||||
maxChildren: 1000,
|
||||
maxCharsPerFile: 2_000_000,
|
||||
} as const
|
||||
|
||||
let m: string = 'No contents detected'
|
||||
if (stat.isFile) {
|
||||
m = await messageOfSelection({
|
||||
type: 'File',
|
||||
uri,
|
||||
language: (await voidModelService.getModelSafe(uri)).model?.getLanguageId() || '',
|
||||
state: { wasAddedAsCurrentFile: false, },
|
||||
}, {
|
||||
folderOpts,
|
||||
directoryStrService,
|
||||
fileService,
|
||||
})
|
||||
}
|
||||
|
||||
if (stat.isDirectory) {
|
||||
m = await messageOfSelection({
|
||||
type: 'Folder',
|
||||
uri,
|
||||
}, {
|
||||
folderOpts,
|
||||
fileService,
|
||||
directoryStrService,
|
||||
})
|
||||
}
|
||||
|
||||
await clipboardService.writeText(m)
|
||||
|
||||
} catch (error) {
|
||||
const notificationService = accessor.get(INotificationService)
|
||||
notificationService.error(error + '')
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
registerAction2(FilePromptActionService)
|
||||
|
|
@ -239,17 +239,94 @@ export const StatusIndicatorForApplyButton = ({ applyBoxId, uri }: { applyBoxId:
|
|||
}
|
||||
|
||||
|
||||
export const ApplyButtonsHTML = ({
|
||||
const terminalLanguages = new Set([
|
||||
'bash',
|
||||
'shellscript',
|
||||
'shell',
|
||||
'powershell',
|
||||
'bat',
|
||||
'zsh',
|
||||
'sh',
|
||||
'fish',
|
||||
'nushell',
|
||||
'ksh',
|
||||
'xonsh',
|
||||
'elvish',
|
||||
])
|
||||
|
||||
const ApplyButtonsForTerminal = ({
|
||||
codeStr,
|
||||
applyBoxId,
|
||||
uri,
|
||||
language,
|
||||
}: {
|
||||
codeStr: string,
|
||||
applyBoxId: string,
|
||||
} & ({
|
||||
language?: string,
|
||||
uri: URI | 'current';
|
||||
})
|
||||
) => {
|
||||
}) => {
|
||||
const accessor = useAccessor()
|
||||
const metricsService = accessor.get('IMetricsService')
|
||||
const terminalToolService = accessor.get('ITerminalToolService')
|
||||
|
||||
const settingsState = useSettingsState()
|
||||
|
||||
const [isShellRunning, setIsShellRunning] = useState<boolean>(false)
|
||||
const interruptToolRef = useRef<(() => void) | null>(null)
|
||||
const isDisabled = isShellRunning
|
||||
|
||||
const onClickSubmit = useCallback(async () => {
|
||||
if (isShellRunning) return
|
||||
try {
|
||||
setIsShellRunning(true)
|
||||
const terminalId = await terminalToolService.createPersistentTerminal({ cwd: null })
|
||||
const { interrupt } = await terminalToolService.runCommand(
|
||||
codeStr,
|
||||
{ type: 'persistent', persistentTerminalId: terminalId }
|
||||
);
|
||||
interruptToolRef.current = interrupt
|
||||
metricsService.capture('Execute Shell', { length: codeStr.length })
|
||||
} catch (e) {
|
||||
setIsShellRunning(false)
|
||||
console.error('Failed to execute in terminal:', e)
|
||||
}
|
||||
}, [codeStr, uri, applyBoxId, metricsService, terminalToolService, isShellRunning])
|
||||
|
||||
if (isShellRunning) {
|
||||
return (
|
||||
<IconShell1
|
||||
Icon={X}
|
||||
onClick={() => {
|
||||
interruptToolRef.current?.();
|
||||
setIsShellRunning(false);
|
||||
}}
|
||||
{...tooltipPropsForApplyBlock({ tooltipName: 'Stop' })}
|
||||
/>
|
||||
);
|
||||
}
|
||||
if (isDisabled) {
|
||||
return null
|
||||
}
|
||||
return <IconShell1
|
||||
Icon={Play}
|
||||
onClick={onClickSubmit}
|
||||
{...tooltipPropsForApplyBlock({ tooltipName: 'Apply' })}
|
||||
/>
|
||||
}
|
||||
|
||||
|
||||
|
||||
const ApplyButtonsForEdit = ({
|
||||
codeStr,
|
||||
applyBoxId,
|
||||
uri,
|
||||
language,
|
||||
}: {
|
||||
codeStr: string,
|
||||
applyBoxId: string,
|
||||
language?: string,
|
||||
uri: URI | 'current';
|
||||
}) => {
|
||||
const accessor = useAccessor()
|
||||
const editCodeService = accessor.get('IEditCodeService')
|
||||
const metricsService = accessor.get('IMetricsService')
|
||||
|
|
@ -260,7 +337,6 @@ export const ApplyButtonsHTML = ({
|
|||
|
||||
const { currStreamStateRef, setApplying } = useApplyStreamState({ applyBoxId })
|
||||
|
||||
|
||||
const onClickSubmit = useCallback(async () => {
|
||||
if (currStreamStateRef.current === 'streaming') return
|
||||
|
||||
|
|
@ -287,7 +363,7 @@ export const ApplyButtonsHTML = ({
|
|||
})
|
||||
metricsService.capture('Apply Code', { length: codeStr.length }) // capture the length only
|
||||
|
||||
}, [setApplying, currStreamStateRef, editCodeService, codeStr, uri, applyBoxId, metricsService])
|
||||
}, [setApplying, currStreamStateRef, editCodeService, codeStr, uri, applyBoxId, metricsService, notificationService])
|
||||
|
||||
|
||||
const onClickStop = useCallback(() => {
|
||||
|
|
@ -309,9 +385,7 @@ export const ApplyButtonsHTML = ({
|
|||
if (uri) editCodeService.acceptOrRejectAllDiffAreas({ uri: uri, behavior: 'reject', removeCtrlKs: false })
|
||||
}, [uri, applyBoxId, editCodeService])
|
||||
|
||||
|
||||
const currStreamState = currStreamStateRef.current
|
||||
|
||||
if (currStreamState === 'streaming') {
|
||||
return <IconShell1
|
||||
Icon={Square}
|
||||
|
|
@ -319,12 +393,9 @@ export const ApplyButtonsHTML = ({
|
|||
{...tooltipPropsForApplyBlock({ tooltipName: 'Stop' })}
|
||||
/>
|
||||
}
|
||||
|
||||
if (isDisabled) {
|
||||
return null
|
||||
}
|
||||
|
||||
|
||||
if (currStreamState === 'idle-no-changes') {
|
||||
return <IconShell1
|
||||
Icon={Play}
|
||||
|
|
@ -332,7 +403,6 @@ export const ApplyButtonsHTML = ({
|
|||
{...tooltipPropsForApplyBlock({ tooltipName: 'Apply' })}
|
||||
/>
|
||||
}
|
||||
|
||||
if (currStreamState === 'idle-has-changes') {
|
||||
return <Fragment>
|
||||
<IconShell1
|
||||
|
|
@ -353,6 +423,27 @@ export const ApplyButtonsHTML = ({
|
|||
|
||||
|
||||
|
||||
export const ApplyButtonsHTML = (params: {
|
||||
codeStr: string,
|
||||
applyBoxId: string,
|
||||
language?: string,
|
||||
uri: URI | 'current';
|
||||
}) => {
|
||||
const { language } = params
|
||||
const isShellLanguage = !!language && terminalLanguages.has(language)
|
||||
|
||||
if (isShellLanguage) {
|
||||
return <ApplyButtonsForTerminal {...params} />
|
||||
}
|
||||
else {
|
||||
return <ApplyButtonsForEdit {...params} />
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
export const EditToolAcceptRejectButtonsHTML = ({
|
||||
codeStr,
|
||||
applyBoxId,
|
||||
|
|
@ -456,7 +547,7 @@ export const BlockCodeApplyWrapper = ({
|
|||
<div className={`${canApply ? '' : 'hidden'} flex items-center gap-1`}>
|
||||
<JumpToFileButton uri={uri} />
|
||||
{currStreamState === 'idle-no-changes' && <CopyButton codeStr={codeStr} toolTipName='Copy' />}
|
||||
<ApplyButtonsHTML uri={uri} applyBoxId={applyBoxId} codeStr={codeStr} />
|
||||
<ApplyButtonsHTML uri={uri} applyBoxId={applyBoxId} codeStr={codeStr} language={language} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -89,10 +89,7 @@ registerAction2(class extends Action2 {
|
|||
});
|
||||
}
|
||||
async run(accessor: ServicesAccessor): Promise<void> {
|
||||
|
||||
|
||||
// Get the views service to check if the sidebar is open
|
||||
// const viewsService = accessor.get(IViewsService)
|
||||
// Get services
|
||||
const commandService = accessor.get(ICommandService)
|
||||
const viewsService = accessor.get(IViewsService)
|
||||
const metricsService = accessor.get(IMetricsService)
|
||||
|
|
@ -101,31 +98,28 @@ registerAction2(class extends Action2 {
|
|||
|
||||
metricsService.capture('Ctrl+L', {})
|
||||
|
||||
// capture selection and model before opening the chat panel
|
||||
const editor = editorService.getActiveCodeEditor()
|
||||
const model = editor?.getModel()
|
||||
if (!model) return
|
||||
|
||||
const selectionRange = roundRangeToLines(editor?.getSelection(), { emptySelectionBehavior: 'null' })
|
||||
|
||||
// open panel
|
||||
const wasAlreadyOpen = viewsService.isViewContainerVisible(VOID_VIEW_CONTAINER_ID)
|
||||
if (!wasAlreadyOpen) {
|
||||
await commandService.executeCommand(VOID_OPEN_SIDEBAR_ACTION_ID)
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
// if was already open
|
||||
|
||||
const model = accessor.get(ICodeEditorService).getActiveCodeEditor()?.getModel()
|
||||
if (!model) return
|
||||
|
||||
const editor = editorService.getActiveCodeEditor()
|
||||
const selectionRange = roundRangeToLines(editor?.getSelection(), { emptySelectionBehavior: 'null' })
|
||||
|
||||
// if has no selection, close + return
|
||||
// if (!selectionRange) {
|
||||
// viewsService.closeViewContainer(VOID_VIEW_CONTAINER_ID);
|
||||
// return;
|
||||
// }
|
||||
|
||||
|
||||
// Add selection to chat
|
||||
// add line selection
|
||||
if (selectionRange) {
|
||||
editor?.setSelection({ startLineNumber: selectionRange.startLineNumber, endLineNumber: selectionRange.endLineNumber, startColumn: 1, endColumn: Number.MAX_SAFE_INTEGER })
|
||||
editor?.setSelection({
|
||||
startLineNumber: selectionRange.startLineNumber,
|
||||
endLineNumber: selectionRange.endLineNumber,
|
||||
startColumn: 1,
|
||||
endColumn: Number.MAX_SAFE_INTEGER
|
||||
})
|
||||
chatThreadService.addNewStagingSelection({
|
||||
type: 'CodeSelection',
|
||||
uri: model.uri,
|
||||
|
|
@ -142,12 +136,9 @@ registerAction2(class extends Action2 {
|
|||
language: model.getLanguageId(),
|
||||
state: { wasAddedAsCurrentFile: false },
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
await chatThreadService.focusCurrentChat()
|
||||
|
||||
|
||||
}
|
||||
})
|
||||
|
||||
|
|
|
|||
|
|
@ -22,7 +22,12 @@ export interface ITerminalToolService {
|
|||
readonly _serviceBrand: undefined;
|
||||
|
||||
listPersistentTerminalIds(): string[];
|
||||
runCommand(command: string, opts: { type: 'persistent', persistentTerminalId: string } | { type: 'ephemeral', cwd: string | null, terminalId: string }): Promise<{ interrupt: () => void; resPromise: Promise<{ result: string, resolveReason: TerminalResolveReason }> }>;
|
||||
runCommand(command: string, opts:
|
||||
| { type: 'persistent', persistentTerminalId: string }
|
||||
| { type: 'temporary', cwd: string | null, terminalId: string }
|
||||
// | { type: 'apply', terminalId: string }
|
||||
): Promise<{ interrupt: () => void; resPromise: Promise<{ result: string, resolveReason: TerminalResolveReason }> }>;
|
||||
|
||||
focusPersistentTerminal(terminalId: string): Promise<void>
|
||||
persistentTerminalExists(terminalId: string): boolean
|
||||
|
||||
|
|
@ -277,6 +282,8 @@ export class TerminalToolService extends Disposable implements ITerminalToolServ
|
|||
terminal.dispose()
|
||||
if (!isPersistent)
|
||||
delete this.temporaryTerminalInstanceOfId[params.terminalId]
|
||||
else
|
||||
delete this.persistentTerminalInstanceOfId[params.persistentTerminalId]
|
||||
}
|
||||
|
||||
const waitForResult = async () => {
|
||||
|
|
|
|||
|
|
@ -430,7 +430,7 @@ export class ToolsService implements IToolsService {
|
|||
},
|
||||
// ---
|
||||
run_command: async ({ command, cwd, terminalId }) => {
|
||||
const { resPromise, interrupt } = await this.terminalToolService.runCommand(command, { type: 'ephemeral', cwd, terminalId })
|
||||
const { resPromise, interrupt } = await this.terminalToolService.runCommand(command, { type: 'temporary', cwd, terminalId })
|
||||
return { result: resPromise, interruptTool: interrupt }
|
||||
},
|
||||
run_persistent_command: async ({ command, persistentTerminalId }) => {
|
||||
|
|
|
|||
|
|
@ -58,6 +58,9 @@ import './voidOnboardingService.js'
|
|||
// register misc service
|
||||
import './miscWokrbenchContrib.js'
|
||||
|
||||
// register file service (for explorer context menu)
|
||||
import './fileService.js'
|
||||
|
||||
// ---------- common (unclear if these actually need to be imported, because they're already imported wherever they're used) ----------
|
||||
|
||||
// llmMessage
|
||||
|
|
|
|||
|
|
@ -129,6 +129,7 @@ export const defaultModelsOfProvider = {
|
|||
mistral: [ // https://docs.mistral.ai/getting-started/models/models_overview/
|
||||
'codestral-latest',
|
||||
'mistral-large-latest',
|
||||
'mistral-medium-latest',
|
||||
'ministral-3b-latest',
|
||||
'ministral-8b-latest',
|
||||
],
|
||||
|
|
@ -188,7 +189,13 @@ export type VoidStaticModelInfo = { // not stateful
|
|||
|
||||
|
||||
export type ModelOverrides = Pick<VoidStaticModelInfo,
|
||||
'contextWindow' | 'reservedOutputTokenSpace' | 'specialToolFormat' | 'supportsSystemMessage' | 'supportsFIM' | 'reasoningCapabilities'
|
||||
| 'contextWindow'
|
||||
| 'reservedOutputTokenSpace'
|
||||
| 'specialToolFormat'
|
||||
| 'supportsSystemMessage'
|
||||
| 'supportsFIM'
|
||||
| 'reasoningCapabilities'
|
||||
| 'additionalOpenAIPayload'
|
||||
>
|
||||
|
||||
|
||||
|
|
@ -883,6 +890,15 @@ const mistralModelOptions = { // https://mistral.ai/products/la-plateforme#prici
|
|||
supportsSystemMessage: 'system-role',
|
||||
reasoningCapabilities: false,
|
||||
},
|
||||
'mistral-medium-latest': { // https://openrouter.ai/mistralai/mistral-medium-3
|
||||
contextWindow: 131_000,
|
||||
reservedOutputTokenSpace: 8_192,
|
||||
cost: { input: 0.40, output: 2.00 },
|
||||
supportsFIM: false,
|
||||
downloadable: { sizeGb: 'not-known' },
|
||||
supportsSystemMessage: 'system-role',
|
||||
reasoningCapabilities: false,
|
||||
},
|
||||
'codestral-latest': {
|
||||
contextWindow: 256_000,
|
||||
reservedOutputTokenSpace: 8_192,
|
||||
|
|
|
|||
|
|
@ -481,7 +481,6 @@ ${directoryStr}
|
|||
details.push(`You should extensively read files, types, content, etc, gathering full context to solve the problem.`)
|
||||
}
|
||||
|
||||
|
||||
details.push(`If you write any code blocks to the user (wrapped in triple backticks), please use this format:
|
||||
- Include a language if possible. Terminal should have the language 'shell'.
|
||||
- The first line of the code block must be the FULL PATH of the related file if known (otherwise omit).
|
||||
|
|
@ -529,7 +528,9 @@ ${details.map((d, i) => `${i + 1}. ${d}`).join('\n\n')}`)
|
|||
// chat_systemMessage({ chatMode, workspaceFolders: [], openedURIs: [], activeURI: 'pee', persistentTerminalIDs: [], directoryStr: 'lol', }))
|
||||
// }
|
||||
|
||||
const readFile = async (fileService: IFileService, uri: URI, fileSizeLimit: number): Promise<{
|
||||
export const DEFAULT_FILE_SIZE_LIMIT = 2_000_000
|
||||
|
||||
export const readFile = async (fileService: IFileService, uri: URI, fileSizeLimit: number): Promise<{
|
||||
val: string,
|
||||
truncated: boolean,
|
||||
fullFileLen: number,
|
||||
|
|
@ -553,46 +554,70 @@ const readFile = async (fileService: IFileService, uri: URI, fileSizeLimit: numb
|
|||
|
||||
|
||||
|
||||
export const messageOfSelection = async (
|
||||
s: StagingSelectionItem,
|
||||
opts: {
|
||||
directoryStrService: IDirectoryStrService,
|
||||
fileService: IFileService,
|
||||
folderOpts: {
|
||||
maxChildren: number,
|
||||
maxCharsPerFile: number,
|
||||
}
|
||||
}
|
||||
) => {
|
||||
const lineNumAddition = (range: [number, number]) => ` (lines ${range[0]}:${range[1]})`
|
||||
|
||||
if (s.type === 'File' || s.type === 'CodeSelection') {
|
||||
const { val } = await readFile(opts.fileService, s.uri, DEFAULT_FILE_SIZE_LIMIT)
|
||||
const lineNumAdd = s.type === 'CodeSelection' ? lineNumAddition(s.range) : ''
|
||||
const content = val === null ? 'null' : `${tripleTick[0]}${s.language}\n${val}\n${tripleTick[1]}`
|
||||
const str = `${s.uri.fsPath}${lineNumAdd}:\n${content}`
|
||||
return str
|
||||
}
|
||||
else if (s.type === 'Folder') {
|
||||
const dirStr: string = await opts.directoryStrService.getDirectoryStrTool(s.uri)
|
||||
const folderStructure = `${s.uri.fsPath} folder structure:${tripleTick[0]}\n${dirStr}\n${tripleTick[1]}`
|
||||
|
||||
const uris = await opts.directoryStrService.getAllURIsInDirectory(s.uri, { maxResults: opts.folderOpts.maxChildren })
|
||||
const strOfFiles = await Promise.all(uris.map(async uri => {
|
||||
const { val, truncated } = await readFile(opts.fileService, uri, opts.folderOpts.maxCharsPerFile)
|
||||
const truncationStr = truncated ? `\n... file truncated ...` : ''
|
||||
const content = val === null ? 'null' : `${tripleTick[0]}\n${val}${truncationStr}\n${tripleTick[1]}`
|
||||
const str = `${uri.fsPath}:\n${content}`
|
||||
return str
|
||||
}))
|
||||
const contentStr = [folderStructure, ...strOfFiles].join('\n\n')
|
||||
return contentStr
|
||||
}
|
||||
else
|
||||
return ''
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
export const chat_userMessageContent = async (instructions: string, currSelns: StagingSelectionItem[] | null,
|
||||
opts: { directoryStrService: IDirectoryStrService, fileService: IFileService }
|
||||
export const chat_userMessageContent = async (
|
||||
instructions: string,
|
||||
currSelns: StagingSelectionItem[] | null,
|
||||
opts: {
|
||||
directoryStrService: IDirectoryStrService,
|
||||
fileService: IFileService
|
||||
},
|
||||
) => {
|
||||
|
||||
const lineNumAddition = (range: [number, number]) => ` (lines ${range[0]}:${range[1]})`
|
||||
let selnsStrs: string[] = []
|
||||
selnsStrs = await Promise.all(currSelns?.map(async (s) => {
|
||||
const selnsStrs = await Promise.all(
|
||||
(currSelns ?? []).map(async (s) =>
|
||||
messageOfSelection(s, {
|
||||
...opts,
|
||||
folderOpts: { maxChildren: 100, maxCharsPerFile: 100_000, }
|
||||
})
|
||||
)
|
||||
)
|
||||
|
||||
if (s.type === 'File' || s.type === 'CodeSelection') {
|
||||
const { val } = await readFile(opts.fileService, s.uri, 2_000_000)
|
||||
const lineNumAdd = s.type === 'CodeSelection' ? lineNumAddition(s.range) : ''
|
||||
const content = val === null ? 'null' : `${tripleTick[0]}${s.language}\n${val}\n${tripleTick[1]}`
|
||||
const str = `${s.uri.fsPath}${lineNumAdd}:\n${content}`
|
||||
return str
|
||||
}
|
||||
else if (s.type === 'Folder') {
|
||||
const dirStr: string = await opts.directoryStrService.getDirectoryStrTool(s.uri)
|
||||
const folderStructure = `${s.uri.fsPath} folder structure:${tripleTick[0]}\n${dirStr}\n${tripleTick[1]}`
|
||||
|
||||
const uris = await opts.directoryStrService.getAllURIsInDirectory(s.uri, { maxResults: 100 })
|
||||
const strOfFiles = await Promise.all(uris.map(async uri => {
|
||||
const { val, truncated } = await readFile(opts.fileService, uri, 100_000)
|
||||
const truncationStr = truncated ? `\n... file truncated ...` : ''
|
||||
const content = val === null ? 'null' : `${tripleTick[0]}\n${val}${truncationStr}\n${tripleTick[1]}`
|
||||
const str = `${uri.fsPath}:\n${content}`
|
||||
return str
|
||||
}))
|
||||
const contentStr = [folderStructure, ...strOfFiles].join('\n\n')
|
||||
return contentStr
|
||||
}
|
||||
else
|
||||
return ''
|
||||
}) ?? [])
|
||||
|
||||
const selnsStr = selnsStrs.join('\n') ?? ''
|
||||
let str = ''
|
||||
str += `${instructions}`
|
||||
|
||||
const selnsStr = selnsStrs.join('\n\n') ?? ''
|
||||
if (selnsStr) str += `\n---\nSELECTIONS\n${selnsStr}`
|
||||
return str;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -147,7 +147,12 @@ const newOpenAICompatibleSDK = async ({ settingsOfProvider, providerName, includ
|
|||
|
||||
const _sendOpenAICompatibleFIM = async ({ messages: { prefix, suffix, stopTokens }, onFinalMessage, onError, settingsOfProvider, modelName: modelName_, _setAborter, providerName, overridesOfModel }: SendFIMParams_Internal) => {
|
||||
|
||||
const { modelName, supportsFIM } = getModelCapabilities(providerName, modelName_, overridesOfModel)
|
||||
const {
|
||||
modelName,
|
||||
supportsFIM,
|
||||
additionalOpenAIPayload,
|
||||
} = getModelCapabilities(providerName, modelName_, overridesOfModel)
|
||||
|
||||
if (!supportsFIM) {
|
||||
if (modelName === modelName_)
|
||||
onError({ message: `Model ${modelName} does not support FIM.`, fullError: null })
|
||||
|
|
@ -156,7 +161,7 @@ const _sendOpenAICompatibleFIM = async ({ messages: { prefix, suffix, stopTokens
|
|||
return
|
||||
}
|
||||
|
||||
const openai = await newOpenAICompatibleSDK({ providerName, settingsOfProvider })
|
||||
const openai = await newOpenAICompatibleSDK({ providerName, settingsOfProvider, includeInPayload: additionalOpenAIPayload })
|
||||
openai.completions
|
||||
.create({
|
||||
model: modelName,
|
||||
|
|
@ -236,6 +241,7 @@ const _sendOpenAICompatibleChat = async ({ messages, onText, onFinalMessage, onE
|
|||
modelName,
|
||||
specialToolFormat,
|
||||
reasoningCapabilities,
|
||||
additionalOpenAIPayload,
|
||||
} = getModelCapabilities(providerName, modelName_, overridesOfModel)
|
||||
|
||||
const { providerReasoningIOSettings } = getProviderCapabilities(providerName)
|
||||
|
|
@ -243,7 +249,11 @@ const _sendOpenAICompatibleChat = async ({ messages, onText, onFinalMessage, onE
|
|||
// reasoning
|
||||
const { canIOReasoning, openSourceThinkTags } = reasoningCapabilities || {}
|
||||
const reasoningInfo = getSendableReasoningInfo('Chat', providerName, modelName_, modelSelectionOptions, overridesOfModel) // user's modelName_ here
|
||||
const includeInPayload = providerReasoningIOSettings?.input?.includeInPayload?.(reasoningInfo) || {}
|
||||
|
||||
const includeInPayload = {
|
||||
...providerReasoningIOSettings?.input?.includeInPayload?.(reasoningInfo),
|
||||
...additionalOpenAIPayload
|
||||
}
|
||||
|
||||
// tools
|
||||
const potentialTools = chatMode !== null ? openAITools(chatMode) : null
|
||||
|
|
@ -258,6 +268,7 @@ const _sendOpenAICompatibleChat = async ({ messages, onText, onFinalMessage, onE
|
|||
messages: messages as any,
|
||||
stream: true,
|
||||
...nativeToolsObj,
|
||||
...additionalOpenAIPayload
|
||||
// max_completion_tokens: maxTokens,
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue