Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions web-app/src/containers/ChatInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@
const { prompt, setPrompt } = usePrompt()
const { currentThreadId } = useThreads()
const { t } = useTranslation()
const { spellCheckChatInput } = useGeneralSetting()
const { spellCheckChatInput, experimentalFeatures } = useGeneralSetting()

const maxRows = 10

Expand All @@ -78,9 +78,9 @@
const servers = await getConnectedServers()
setConnectedServers(servers)
} catch (error) {
console.error('Failed to get connected servers:', error)
setConnectedServers([])
}

Check warning on line 83 in web-app/src/containers/ChatInput.tsx

View workflow job for this annotation

GitHub Actions / coverage-check

81-83 lines are not covered with tests
}

checkConnectedServers()
Expand All @@ -100,8 +100,8 @@
return
}
if (!prompt.trim()) {
return
}

Check warning on line 104 in web-app/src/containers/ChatInput.tsx

View workflow job for this annotation

GitHub Actions / coverage-check

103-104 lines are not covered with tests
setMessage('')
sendMessage(prompt)
}
Expand All @@ -109,8 +109,8 @@
useEffect(() => {
const handleFocusIn = () => {
if (document.activeElement === textareaRef.current) {
setIsFocused(true)
}

Check warning on line 113 in web-app/src/containers/ChatInput.tsx

View workflow job for this annotation

GitHub Actions / coverage-check

112-113 lines are not covered with tests
}

const handleFocusOut = () => {
Expand All @@ -137,8 +137,8 @@

useEffect(() => {
if (tooltipToolsAvailable && dropdownToolsAvailable) {
setTooltipToolsAvailable(false)
}

Check warning on line 141 in web-app/src/containers/ChatInput.tsx

View workflow job for this annotation

GitHub Actions / coverage-check

140-141 lines are not covered with tests
}, [dropdownToolsAvailable, tooltipToolsAvailable])

// Focus when thread changes
Expand All @@ -160,44 +160,44 @@

const stopStreaming = useCallback(
(threadId: string) => {
abortControllers[threadId]?.abort()
},

Check warning on line 164 in web-app/src/containers/ChatInput.tsx

View workflow job for this annotation

GitHub Actions / coverage-check

163-164 lines are not covered with tests
[abortControllers]
)

const fileInputRef = useRef<HTMLInputElement>(null)

const handleAttachmentClick = () => {
fileInputRef.current?.click()
}

Check warning on line 172 in web-app/src/containers/ChatInput.tsx

View workflow job for this annotation

GitHub Actions / coverage-check

171-172 lines are not covered with tests

const handleRemoveFile = (indexToRemove: number) => {
setUploadedFiles((prev) =>
prev.filter((_, index) => index !== indexToRemove)
)
}

Check warning on line 178 in web-app/src/containers/ChatInput.tsx

View workflow job for this annotation

GitHub Actions / coverage-check

175-178 lines are not covered with tests

const getFileTypeFromExtension = (fileName: string): string => {
const extension = fileName.toLowerCase().split('.').pop()
switch (extension) {
case 'jpg':
case 'jpeg':
return 'image/jpeg'
case 'png':
return 'image/png'
case 'pdf':
return 'application/pdf'
default:
return ''
}
}

Check warning on line 193 in web-app/src/containers/ChatInput.tsx

View workflow job for this annotation

GitHub Actions / coverage-check

181-193 lines are not covered with tests

const handleFileChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const files = e.target.files

Check warning on line 196 in web-app/src/containers/ChatInput.tsx

View workflow job for this annotation

GitHub Actions / coverage-check

196 line is not covered with tests

if (files && files.length > 0) {
const maxSize = 10 * 1024 * 1024 // 10MB in bytes
const newFiles: Array<{

Check warning on line 200 in web-app/src/containers/ChatInput.tsx

View workflow job for this annotation

GitHub Actions / coverage-check

198-200 lines are not covered with tests
name: string
type: string
size: number
Expand Down Expand Up @@ -459,7 +459,8 @@
</TooltipProvider>
)}

{selectedModel?.capabilities?.includes('tools') &&
{experimentalFeatures &&
selectedModel?.capabilities?.includes('tools') &&
hasActiveMCPServers && (
<TooltipProvider>
<Tooltip
Expand Down
1 change: 1 addition & 0 deletions web-app/src/containers/__tests__/ChatInput.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ describe('ChatInput', () => {
vi.mocked(useGeneralSetting).mockReturnValue({
spellCheckChatInput: true,
allowSendWhenUnloaded: false,
experimentalFeatures: true,
})

vi.mocked(useModelProvider).mockReturnValue({
Expand Down
15 changes: 9 additions & 6 deletions web-app/src/hooks/useChat.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,11 @@
import { updateSettings } from '@/services/providers'
import { useContextSizeApproval } from './useModelContextApproval'
import { useModelLoad } from './useModelLoad'
import { useGeneralSetting } from './useGeneralSetting'

export const useChat = () => {
const { prompt, setPrompt } = usePrompt()
const { experimentalFeatures } = useGeneralSetting()
const {
tools,
updateTokenSpeed,
Expand Down Expand Up @@ -247,12 +249,13 @@
let isCompleted = false

// Filter tools based on model capabilities and available tools for this thread
let availableTools = selectedModel?.capabilities?.includes('tools')
? tools.filter((tool) => {
const disabledTools = getDisabledToolsForThread(activeThread.id)
return !disabledTools.includes(tool.name)
})
: []
let availableTools =
experimentalFeatures && selectedModel?.capabilities?.includes('tools')
? tools.filter((tool) => {
const disabledTools = getDisabledToolsForThread(activeThread.id)
return !disabledTools.includes(tool.name)
})
: []

// TODO: Later replaced by Agent setup?
const followUpWithToolUse = true
Expand Down Expand Up @@ -433,7 +436,7 @@
updateStreamingContent(undefined)
}
},
[

Check warning on line 439 in web-app/src/hooks/useChat.ts

View workflow job for this annotation

GitHub Actions / test-on-macos

React Hook useCallback has a missing dependency: 'experimentalFeatures'. Either include it or remove the dependency array

Check warning on line 439 in web-app/src/hooks/useChat.ts

View workflow job for this annotation

GitHub Actions / test-on-ubuntu

React Hook useCallback has a missing dependency: 'experimentalFeatures'. Either include it or remove the dependency array

Check warning on line 439 in web-app/src/hooks/useChat.ts

View workflow job for this annotation

GitHub Actions / test-on-windows-pr

React Hook useCallback has a missing dependency: 'experimentalFeatures'. Either include it or remove the dependency array

Check warning on line 439 in web-app/src/hooks/useChat.ts

View workflow job for this annotation

GitHub Actions / coverage-check

React Hook useCallback has a missing dependency: 'experimentalFeatures'. Either include it or remove the dependency array
getCurrentThread,
resetTokenSpeed,
currentProviderId,
Expand Down
40 changes: 39 additions & 1 deletion web-app/src/routes/settings/general.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,9 @@ import { emit } from '@tauri-apps/api/event'
import { stopAllModels } from '@/services/models'
import { SystemEvent } from '@/types/events'
import { Input } from '@/components/ui/input'
import { getConnectedServers } from '@/services/mcp'
import { invoke } from '@tauri-apps/api/core'
import { useMCPServers } from '@/hooks/useMCPServers'

// eslint-disable-next-line @typescript-eslint/no-explicit-any
export const Route = createFileRoute(route.settings.general as any)({
Expand Down Expand Up @@ -202,6 +205,38 @@ function General() {
}
}, [t, checkForUpdate])

const handleStopAllMCPServers = async () => {
try {
const connectedServers = await getConnectedServers()

// Stop each connected server
const stopPromises = connectedServers.map((serverName) =>
invoke('deactivate_mcp_server', { name: serverName }).catch((error) => {
console.error(`Error stopping MCP server ${serverName}:`, error)
return Promise.resolve() // Continue with other servers even if one fails
})
)

await Promise.all(stopPromises)

// Update server configs to set active: false for stopped servers
const { mcpServers, editServer } = useMCPServers.getState()
connectedServers.forEach((serverName) => {
const serverConfig = mcpServers[serverName]
if (serverConfig) {
editServer(serverName, { ...serverConfig, active: false })
}
})

if (connectedServers.length > 0) {
toast.success(`Stopped ${connectedServers.length} MCP server(s)`)
}
} catch (error) {
console.error('Error stopping MCP servers:', error)
toast.error('Failed to stop MCP servers')
}
}

return (
<div className="flex flex-col h-full">
<HeaderPage>
Expand Down Expand Up @@ -395,7 +430,10 @@ function General() {
actions={
<Switch
checked={experimentalFeatures}
onCheckedChange={(e) => setExperimentalFeatures(e)}
onCheckedChange={async (e) => {
await handleStopAllMCPServers()
setExperimentalFeatures(e)
}}
/>
}
/>
Expand Down
11 changes: 10 additions & 1 deletion web-app/src/routes/settings/mcp-servers.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -114,8 +114,15 @@ function MCPServers() {
setDeleteDialogOpen(true)
}

const handleConfirmDelete = () => {
const handleConfirmDelete = async () => {
if (serverToDelete) {
// Stop the server before deletion
try {
await invoke('deactivate_mcp_server', { name: serverToDelete })
} catch (error) {
console.error('Error stopping server before deletion:', error)
}

deleteServer(serverToDelete)
setServerToDelete(null)
syncServersAndRestart()
Expand Down Expand Up @@ -226,6 +233,8 @@ function MCPServers() {
return () => clearInterval(intervalId)
}, [setConnectedServers])

console.log(mcpServers)

return (
<div className="flex flex-col h-full">
<HeaderPage>
Expand Down
Loading