This commit is contained in:
Andrew Pareles 2025-03-06 04:38:17 -08:00
parent f292fa8df6
commit 6d3de34818
3 changed files with 108 additions and 172 deletions

View file

@ -37,7 +37,7 @@ const CopyButton = ({ codeStr }: { codeStr: string }) => {
const isSingleLine = !codeStr.includes('\n')
return <button
className={`${isSingleLine ? '' : 'px-1 py-0.5'} text-sm bg-void-bg-1 text-void-fg-1 hover:brightness-110 border border-vscode-input-border rounded`}
className={`${isSingleLine ? '' : 'px-1 py-0.5'} text-sm bg-void-bg-2 text-void-fg-1 hover:brightness-110 border border-void-border-1 rounded`}
onClick={onCopy}
>
{copyButtonText}
@ -104,16 +104,14 @@ export const ApplyBlockHoverButtons = ({ codeStr, applyBoxId }: { codeStr: strin
const isSingleLine = !codeStr.includes('\n')
const applyButton = <button
// btn btn-secondary btn-sm border text-sm border-vscode-input-border rounded
className={`${isSingleLine ? '' : 'px-1 py-0.5'} text-sm bg-void-bg-1 text-void-fg-1 hover:brightness-110 border border-vscode-input-border rounded`}
className={`${isSingleLine ? '' : 'px-1 py-0.5'} text-sm bg-void-bg-2 text-void-fg-1 hover:brightness-110 border border-void-border-1 rounded`}
onClick={onSubmit}
>
Apply
</button>
const stopButton = <button
// btn btn-secondary btn-sm border text-sm border-vscode-input-border rounded
className={`${isSingleLine ? '' : 'px-1 py-0.5'} text-sm bg-void-bg-1 text-void-fg-1 hover:brightness-110 border border-vscode-input-border rounded`}
className={`${isSingleLine ? '' : 'px-1 py-0.5'} text-sm bg-void-bg-2 text-void-fg-1 hover:brightness-110 border border-void-border-1 rounded`}
onClick={onInterrupt}
>
Stop
@ -121,8 +119,7 @@ export const ApplyBlockHoverButtons = ({ codeStr, applyBoxId }: { codeStr: strin
const acceptRejectButtons = <>
<button
// btn btn-secondary btn-sm border text-sm border-vscode-input-border rounded
className={`${isSingleLine ? '' : 'px-1 py-0.5'} text-sm bg-void-bg-1 text-void-fg-1 hover:brightness-110 border border-vscode-input-border rounded`}
className={`${isSingleLine ? '' : 'px-1 py-0.5'} text-sm bg-void-bg-2 text-void-fg-1 hover:brightness-110 border border-void-border-1 rounded`}
onClick={() => {
const uri = applyingUri()
if (uri) editCodeService.removeDiffAreas({ uri, behavior: 'accept', removeCtrlKs: false })
@ -131,8 +128,7 @@ export const ApplyBlockHoverButtons = ({ codeStr, applyBoxId }: { codeStr: strin
Accept
</button>
<button
// btn btn-secondary btn-sm border text-sm border-vscode-input-border rounded
className={`${isSingleLine ? '' : 'px-1 py-0.5'} text-sm bg-void-bg-1 text-void-fg-1 hover:brightness-110 border border-vscode-input-border rounded`}
className={`${isSingleLine ? '' : 'px-1 py-0.5'} text-sm bg-void-bg-2 text-void-fg-1 hover:brightness-110 border border-void-border-1 rounded`}
onClick={() => {
const uri = applyingUri()
if (uri) editCodeService.removeDiffAreas({ uri, behavior: 'reject', removeCtrlKs: false })

View file

@ -20,71 +20,6 @@ const getApplyBoxId = ({ threadId, messageIdx, tokenIdx }: ApplyBoxLocation) =>
return `${threadId}-${messageIdx}-${tokenIdx}`
}
// all classnames must go in tailwind.config.js/safelist
export const noSpaceStyles = {
blockquote: 'pl-4 border-l-4 border-void-bg-2 italic',
br: '',
code: '',
codespan: 'bg-void-bg-1 px-1 rounded-sm font-mono font-medium break-all',
def: '',
del: 'line-through',
em: 'italic',
escape: '',
heading: {
h1: "text-4xl font-semibold pb-2 border-b border-void-bg-2",
h2: "text-3xl font-semibold pb-2 border-b border-void-bg-2",
h3: "text-2xl font-semibold",
h4: "text-xl font-semibold",
h5: "text-lg font-semibold",
h6: "text-base font-semibold text-gray-600"
},
hr: 'border-t border-void-bg-2',
html: '',
image: 'max-w-full h-auto rounded',
link: 'underline cursor-pointer',
list: 'list-inside pl-2',
list_item: '',
paragraph: '',
space: '',
strong: 'font-semibold',
table: 'overflow-x-auto',
text: '',
}
const defaultStyles = {
blockquote: 'mx-2 pl-4 border-l-4 border-void-bg-2 italic my-4',
br: '',
code: 'mx-2 my-4',
codespan: 'bg-void-bg-1 px-1 rounded-sm font-mono font-medium break-all',
def: '',
del: 'line-through',
em: 'italic',
escape: '',
heading: {
h1: 'mx-2 text-4xl font-semibold mt-6 mb-4 pb-2 border-b border-void-bg-2',
h2: 'mx-2 text-3xl font-semibold mt-6 mb-4 pb-2 border-b border-void-bg-2',
h3: 'mx-2 text-2xl font-semibold mt-6 mb-4',
h4: 'mx-2 text-xl font-semibold mt-6 mb-4',
h5: 'mx-2 text-lg font-semibold mt-6 mb-4',
h6: 'mx-2 text-base font-semibold mt-6 mb-4 text-gray-600'
},
hr: 'mx-2 my-6 border-t border-void-bg-2',
html: 'mx-2 my-4',
image: 'mx-2 my-4 max-w-full h-auto rounded',
link: 'mx-2 underline',
list: 'mx-2 my-2 list-inside pl-2',
list_item: 'mx-2 mb-2',
paragraph: 'mx-2 my-4',
space: '',
strong: 'mx-2 font-semibold',
table: 'mx-2 my-4 overflow-x-auto',
text: '',
}
const RenderToken = ({ token, nested, chatMessageLocationForApply, tokenIdx }: { token: Token | string, nested?: boolean, chatMessageLocationForApply?: ChatMessageLocation, tokenIdx: string }): JSX.Element => {
// deal with built-in tokens first (assume marked token)
@ -287,7 +222,7 @@ const RenderToken = ({ token, nested, chatMessageLocationForApply, tokenIdx }: {
// inline code
if (t.type === "codespan") {
return (
<code className="font-mono font-semibold rounded-sm bg-void-bg-1 px-1">
<code className="font-mono font-medium rounded-sm bg-void-bg-1 px-1">
{t.text}
</code>
)
@ -301,7 +236,6 @@ const RenderToken = ({ token, nested, chatMessageLocationForApply, tokenIdx }: {
if (t.type === "del") {
return <del>{t.text}</del>
}
// default
return (
<div className="bg-orange-50 rounded-sm overflow-hidden p-2">

View file

@ -148,62 +148,6 @@ const getChatBubbleId = (threadId: string, messageIdx: number) => `${threadId}-$
const ReasoningOptionDropdown = () => {
const accessor = useAccessor()
const voidSettingsService = accessor.get('IVoidSettingsService')
const voidSettingsState = useSettingsState()
const modelSelection = voidSettingsState.modelSelectionOfFeature['Ctrl+L']
if (!modelSelection) return null
const { modelName, providerName } = modelSelection
const { canToggleReasoning, reasoningBudgetOptions } = getModelCapabilities(providerName, modelName).supportsReasoningOutput || {}
const defaultEnabledVal = canToggleReasoning ? true : false
const isEnabled = voidSettingsState.optionsOfModelSelection[modelSelection.providerName]?.[modelSelection.modelName]?.reasoningEnabled ?? defaultEnabledVal
let toggleButton: React.ReactNode = null
if (canToggleReasoning) {
toggleButton = <div className='flex items-center gap-x-3'>
<span className='text-void-fg-3 text-xs pointer-events-none inline-block w-10'>{isEnabled ? 'Thinking' : 'Thinking'}</span>
<VoidSwitch
size='xxs'
value={isEnabled}
onChange={(newVal) => { voidSettingsService.setOptionsOfModelSelection(modelSelection.providerName, modelSelection.modelName, { reasoningEnabled: newVal }) }}
/>
</div>
}
let slider: React.ReactNode = null
if (isEnabled && reasoningBudgetOptions?.type === 'slider') {
const { min, max, default: defaultVal } = reasoningBudgetOptions
const value = voidSettingsState.optionsOfModelSelection[modelSelection.providerName]?.[modelSelection.modelName]?.reasoningBudget ?? defaultVal
slider = <div className='flex items-center gap-x-3'>
<span className='text-void-fg-3 text-xs pointer-events-none inline-block w-10'>Budget</span>
<VoidSlider
width={50}
size='xxs'
min={min}
max={max}
step={(max - min) / 8}
value={value}
onChange={(newVal) => { voidSettingsService.setOptionsOfModelSelection(modelSelection.providerName, modelSelection.modelName, { reasoningBudget: newVal }) }}
/>
<span className='text-void-fg-3 text-xs pointer-events-none'>{`${value} tokens`}</span>
</div>
}
return <>
{toggleButton}
{slider}
</>
}
// SLIDER ONLY:
// const ReasoningOptionDropdown = () => {
// const accessor = useAccessor()
@ -219,49 +163,105 @@ const ReasoningOptionDropdown = () => {
// const defaultEnabledVal = canToggleReasoning ? true : false
// const isEnabled = voidSettingsState.optionsOfModelSelection[modelSelection.providerName]?.[modelSelection.modelName]?.reasoningEnabled ?? defaultEnabledVal
// if (canToggleReasoning && !reasoningBudgetOptions) { // if it's just a on/off toggle without a power slider (no models right now)
// return <div className='flex items-center gap-x-2'>
// let toggleButton: React.ReactNode = null
// if (canToggleReasoning) {
// toggleButton = <div className='flex items-center gap-x-3'>
// <span className='text-void-fg-3 text-xs pointer-events-none inline-block w-10'>{isEnabled ? 'Thinking' : 'Thinking'}</span>
// <VoidSwitch
// size='xs'
// size='xxs'
// value={isEnabled}
// onChange={(newVal) => { }}
// onChange={(newVal) => { voidSettingsService.setOptionsOfModelSelection(modelSelection.providerName, modelSelection.modelName, { reasoningEnabled: newVal }) }}
// />
// </div>
// }
// if (reasoningBudgetOptions?.type === 'slider') { // if it's a slider
// const { min: min_, max, default: defaultVal } = reasoningBudgetOptions
// let slider: React.ReactNode = null
// if (isEnabled && reasoningBudgetOptions?.type === 'slider') {
// const { min, max, default: defaultVal } = reasoningBudgetOptions
// const value = voidSettingsState.optionsOfModelSelection[modelSelection.providerName]?.[modelSelection.modelName]?.reasoningBudget ?? defaultVal
// const nSteps = 8 // only used in calculating stepSize, stepSize is what actually matters
// const stepSize = Math.round((max - min_) / 8)
// const min = canToggleReasoning ? min_ - stepSize : min_
// return <div className='flex items-center gap-x-2'>
// <span className='text-void-fg-3 text-xs pointer-events-none inline-block w-10'>Thinking</span>
// slider = <div className='flex items-center gap-x-3'>
// <span className='text-void-fg-3 text-xs pointer-events-none inline-block w-10'>Budget</span>
// <VoidSlider
// width={50}
// size='xs'
// size='xxs'
// min={min}
// max={max}
// step={stepSize}
// step={(max - min) / 8}
// value={value}
// onChange={(newVal) => {
// const disabled = newVal === min && canToggleReasoning
// voidSettingsService.setOptionsOfModelSelection(modelSelection.providerName, modelSelection.modelName, { reasoningEnabled: !disabled, reasoningBudget: newVal })
// }}
// onChange={(newVal) => { voidSettingsService.setOptionsOfModelSelection(modelSelection.providerName, modelSelection.modelName, { reasoningBudget: newVal }) }}
// />
// <span className='text-void-fg-3 text-xs pointer-events-none'>{isEnabled ? `${value} tokens` : 'Thinking disabled'}</span>
// <span className='text-void-fg-3 text-xs pointer-events-none'>{`${value} tokens`}</span>
// </div>
// }
// return null
// return <>
// {toggleButton}
// {slider}
// </>
// }
// SLIDER ONLY:
const ReasoningOptionDropdown = () => {
const accessor = useAccessor()
const voidSettingsService = accessor.get('IVoidSettingsService')
const voidSettingsState = useSettingsState()
const modelSelection = voidSettingsState.modelSelectionOfFeature['Ctrl+L']
if (!modelSelection) return null
const { modelName, providerName } = modelSelection
const { canToggleReasoning, reasoningBudgetOptions } = getModelCapabilities(providerName, modelName).supportsReasoningOutput || {}
const defaultEnabledVal = canToggleReasoning ? true : false
const isEnabled = voidSettingsState.optionsOfModelSelection[modelSelection.providerName]?.[modelSelection.modelName]?.reasoningEnabled ?? defaultEnabledVal
if (canToggleReasoning && !reasoningBudgetOptions) { // if it's just a on/off toggle without a power slider (no models right now)
return <div className='flex items-center gap-x-2'>
<span className='text-void-fg-3 text-xs pointer-events-none inline-block w-10'>{isEnabled ? 'Thinking' : 'Thinking'}</span>
<VoidSwitch
size='xs'
value={isEnabled}
onChange={(newVal) => { }}
/>
</div>
}
if (reasoningBudgetOptions?.type === 'slider') { // if it's a slider
const { min: min_, max, default: defaultVal } = reasoningBudgetOptions
const value = voidSettingsState.optionsOfModelSelection[modelSelection.providerName]?.[modelSelection.modelName]?.reasoningBudget ?? defaultVal
const nSteps = 8 // only used in calculating stepSize, stepSize is what actually matters
const stepSize = Math.round((max - min_) / 8)
const min = canToggleReasoning ? min_ - stepSize : min_
return <div className='flex items-center gap-x-2'>
<span className='text-void-fg-3 text-xs pointer-events-none inline-block w-10'>Thinking</span>
<VoidSlider
width={50}
size='xs'
min={min}
max={max}
step={stepSize}
value={value}
onChange={(newVal) => {
const disabled = newVal === min && canToggleReasoning
voidSettingsService.setOptionsOfModelSelection(modelSelection.providerName, modelSelection.modelName, { reasoningEnabled: !disabled, reasoningBudget: newVal })
}}
/>
<span className='text-void-fg-3 text-xs pointer-events-none'>{isEnabled ? `${value} tokens` : 'Thinking disabled'}</span>
</div>
}
return null
}
interface VoidChatAreaProps {
@ -932,10 +932,24 @@ const AssistantMessageComponent = ({ chatMessage, isLoading, messageIdx }: ChatB
messageIdx: messageIdx,
}
return <div
className='
return <>
{/* reasoning token (anthropic) */}
{hasReasoning && <DropdownComponent
title="Reasoning"
desc1=""
>
<ChatMarkdownRender
string={reasoningStr}
chatMessageLocationForApply={chatMessageLocation}
/>
</DropdownComponent>}
<div
className='
text-void-fg-2
prose
prose-sm
break-words
@ -949,34 +963,26 @@ const AssistantMessageComponent = ({ chatMessage, isLoading, messageIdx }: ChatB
prose-li:my-0
prose-code:before:content-none
prose-code:after:content-none
prose-headings:prose-sm
prose-headings:font-bold
prose-p:leading-normal
prose-ol:leading-normal
prose-ul:leading-normal
max-w-none
'
>
{/* reasoning token (anthropic) */}
{hasReasoning && <DropdownComponent
title="Reasoning"
desc1=""
>
{/* assistant message */}
<ChatMarkdownRender
string={reasoningStr}
string={chatMessage.content || ''}
chatMessageLocationForApply={chatMessageLocation}
/>
</DropdownComponent>}
{/* assistant message */}
<ChatMarkdownRender
string={chatMessage.content || ''}
chatMessageLocationForApply={chatMessageLocation}
/>
{isLoading && <IconLoading className='opacity-50 text-sm mx-4' />}
{isLoading && <IconLoading className='opacity-50 text-sm mx-4' />}
</div>
</div>
</>
}