diff --git a/src/vs/workbench/contrib/void/browser/react/src/markdown/ApplyBlockHoverButtons.tsx b/src/vs/workbench/contrib/void/browser/react/src/markdown/ApplyBlockHoverButtons.tsx index 6a4d393a..93e26b0d 100644 --- a/src/vs/workbench/contrib/void/browser/react/src/markdown/ApplyBlockHoverButtons.tsx +++ b/src/vs/workbench/contrib/void/browser/react/src/markdown/ApplyBlockHoverButtons.tsx @@ -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(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 ( + { + interruptToolRef.current?.(); + setIsShellRunning(false); + }} + {...tooltipPropsForApplyBlock({ tooltipName: 'Stop' })} + /> + ); + } + if (isDisabled) { + return null + } + return +} + + + +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 } - if (isDisabled) { return null } - - if (currStreamState === 'idle-no-changes') { return } - if (currStreamState === 'idle-has-changes') { return { + const { language } = params + const isShellLanguage = !!language && terminalLanguages.has(language) + + if (isShellLanguage) { + return + } + else { + return + } +} + + + + + export const EditToolAcceptRejectButtonsHTML = ({ codeStr, applyBoxId, @@ -456,7 +547,7 @@ export const BlockCodeApplyWrapper = ({
{currStreamState === 'idle-no-changes' && } - +
diff --git a/src/vs/workbench/contrib/void/browser/terminalToolService.ts b/src/vs/workbench/contrib/void/browser/terminalToolService.ts index b079eb5a..2e18511b 100644 --- a/src/vs/workbench/contrib/void/browser/terminalToolService.ts +++ b/src/vs/workbench/contrib/void/browser/terminalToolService.ts @@ -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 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 () => { diff --git a/src/vs/workbench/contrib/void/browser/toolsService.ts b/src/vs/workbench/contrib/void/browser/toolsService.ts index bba085d8..02edf047 100644 --- a/src/vs/workbench/contrib/void/browser/toolsService.ts +++ b/src/vs/workbench/contrib/void/browser/toolsService.ts @@ -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 }) => { diff --git a/src/vs/workbench/contrib/void/common/prompt/prompts.ts b/src/vs/workbench/contrib/void/common/prompt/prompts.ts index 5746067e..37f16c84 100644 --- a/src/vs/workbench/contrib/void/common/prompt/prompts.ts +++ b/src/vs/workbench/contrib/void/common/prompt/prompts.ts @@ -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).