Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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 Down Expand Up @@ -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,50 +160,50 @@

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
base64: string
dataUrl: string
}> = []

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

View workflow job for this annotation

GitHub Actions / coverage-check

206 line is not covered with tests

Array.from(files).forEach((file) => {
// Check file size
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-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 / 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 / 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
10 changes: 9 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,7 @@ function MCPServers() {
return () => clearInterval(intervalId)
}, [setConnectedServers])


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