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
12 changes: 1 addition & 11 deletions web-app/src/containers/ChatInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -85,9 +85,9 @@
const servers = await serviceHub.mcp().getConnectedServers()
setConnectedServers(servers)
} catch (error) {
console.error('Failed to get connected servers:', error)
setConnectedServers([])
}

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

View workflow job for this annotation

GitHub Actions / coverage-check

88-90 lines are not covered with tests
}

checkConnectedServers()
Expand All @@ -104,25 +104,15 @@
if (selectedModel && selectedModel?.id) {
try {
// Only check mmproj for llamacpp provider
if (selectedProvider === 'llamacpp') {
const hasLocalMmproj = await serviceHub
.models()
.checkMmprojExists(selectedModel.id)
setHasMmproj(hasLocalMmproj)
}
// For non-llamacpp providers, only check vision capability
else if (
selectedProvider !== 'llamacpp' &&
selectedModel?.capabilities?.includes('vision')
) {
if (selectedModel?.capabilities?.includes('vision')) {
setHasMmproj(true)
} else {
setHasMmproj(false)
}

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

View workflow job for this annotation

GitHub Actions / coverage-check

110-111 lines are not covered with tests
} catch (error) {
console.error('Error checking mmproj:', error)
setHasMmproj(false)
}

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

View workflow job for this annotation

GitHub Actions / coverage-check

113-115 lines are not covered with tests
}
}

Expand All @@ -138,8 +128,8 @@
return
}
if (!prompt.trim() && uploadedFiles.length === 0) {
return
}

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

View workflow job for this annotation

GitHub Actions / coverage-check

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

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

View workflow job for this annotation

GitHub Actions / coverage-check

145-146 lines are not covered with tests
}

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

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

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

View workflow job for this annotation

GitHub Actions / coverage-check

173-174 lines are not covered with tests
}, [dropdownToolsAvailable, tooltipToolsAvailable])

// Focus when thread changes
Expand All @@ -203,36 +193,36 @@

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

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

View workflow job for this annotation

GitHub Actions / coverage-check

196-198 lines are not covered with tests
[abortControllers, cancelToolCall]
)

const fileInputRef = useRef<HTMLInputElement>(null)

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

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

View workflow job for this annotation

GitHub Actions / coverage-check

205-206 lines are not covered with tests

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

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

View workflow job for this annotation

GitHub Actions / coverage-check

209-212 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'
default:
return ''
}
}

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

View workflow job for this annotation

GitHub Actions / coverage-check

215-225 lines are not covered with tests

const handleFileChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const files = e.target.files
Expand Down
13 changes: 10 additions & 3 deletions web-app/src/containers/DropdownModelProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -119,13 +119,20 @@ const DropdownModelProvider = ({
const model = provider.models[modelIndex]
const capabilities = model.capabilities || []

// Add 'vision' capability if not already present
if (!capabilities.includes('vision')) {
// Add 'vision' capability if not already present AND if user hasn't manually configured capabilities
// Check if model has a custom capabilities config flag
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const hasUserConfiguredCapabilities = (model as any)._userConfiguredCapabilities === true

if (!capabilities.includes('vision') && !hasUserConfiguredCapabilities) {
const updatedModels = [...provider.models]
updatedModels[modelIndex] = {
...model,
capabilities: [...capabilities, 'vision'],
}
// Mark this as auto-detected, not user-configured
_autoDetectedVision: true,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
} as any

updateProvider('llamacpp', { models: updatedModels })
}
Expand Down
18 changes: 18 additions & 0 deletions web-app/src/containers/dialogs/EditModel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
IconPencil,
IconEye,
IconTool,
IconAlertTriangle,
// IconWorld,
// IconAtom,
// IconCodeCircle2,
Expand Down Expand Up @@ -105,6 +106,8 @@ export const DialogEditModel = ({
return {
...m,
capabilities: updatedCapabilities,
// Mark that user has manually configured capabilities
_userConfiguredCapabilities: true,
}
}
return m
Expand Down Expand Up @@ -145,6 +148,21 @@ export const DialogEditModel = ({
</DialogDescription>
</DialogHeader>

{/* Warning Banner */}
<div className="bg-main-view-fg/5 border border-main-view-fg/10 rounded-md p-3">
<div className="flex items-start space-x-3">
<IconAlertTriangle className="size-5 text-yellow-600 mt-0.5 flex-shrink-0" />
<div className="text-sm text-main-view-fg/80">
<p className="font-medium mb-1 text-base">
{t('providers:editModel.warning.title')}
</p>
<p className="text-main-view-fg/70">
{t('providers:editModel.warning.description')}
</p>
</div>
</div>
</div>

<div className="py-1">
<h3 className="text-sm font-medium mb-3">
{t('providers:editModel.capabilities')}
Expand Down
6 changes: 5 additions & 1 deletion web-app/src/locales/de-DE/providers.json
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,11 @@
"tools": "Werkzeuge",
"vision": "Vision",
"embeddings": "Einbettungen",
"notAvailable": "Noch nicht verfügbar"
"notAvailable": "Noch nicht verfügbar",
"warning": {
"title": "Mit Vorsicht fortfahren",
"description": "Das Ändern von Modellfunktionen kann Leistung und Funktionalität beeinträchtigen. Falsche Einstellungen können zu unerwartetem Verhalten oder Fehlern führen."
}
},
"addProvider": "Anbieter hinzufügen",
"addOpenAIProvider": "OpenAI Anbieter hinzufügen",
Expand Down
6 changes: 5 additions & 1 deletion web-app/src/locales/en/providers.json
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,11 @@
"tools": "Tools",
"vision": "Vision",
"embeddings": "Embeddings",
"notAvailable": "Not available yet"
"notAvailable": "Not available yet",
"warning": {
"title": "Proceed with Caution",
"description": "Modifying model capabilities may affect performance and functionality. Incorrect settings could cause unexpected behavior or errors."
}
},
"addProvider": "Add Provider",
"addOpenAIProvider": "Add OpenAI Provider",
Expand Down
6 changes: 5 additions & 1 deletion web-app/src/locales/id/providers.json
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,11 @@
"tools": "Alat",
"vision": "Visi",
"embeddings": "Embedding",
"notAvailable": "Belum tersedia"
"notAvailable": "Belum tersedia",
"warning": {
"title": "Lanjutkan dengan Hati-hati",
"description": "Memodifikasi kemampuan model dapat mempengaruhi kinerja dan fungsionalitas. Pengaturan yang salah dapat menyebabkan perilaku atau kesalahan yang tidak terduga."
}
},
"addProvider": "Tambah Penyedia",
"addOpenAIProvider": "Tambah Penyedia OpenAI",
Expand Down
6 changes: 5 additions & 1 deletion web-app/src/locales/pl/providers.json
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,11 @@
"tools": "Narzędzia",
"vision": "Wizja",
"embeddings": "Osadzenia",
"notAvailable": "Jeszcze nie dostępne"
"notAvailable": "Jeszcze nie dostępne",
"warning": {
"title": "Zachowaj Ostrożność",
"description": "Modyfikowanie możliwości modelu może wpłynąć na wydajność i funkcjonalność. Nieprawidłowe ustawienia mogą spowodować nieoczekiwane zachowanie lub błędy."
}
},
"addProvider": "Dodaj Dostawcę",
"addOpenAIProvider": "Dodaj Dostawcę OpenAI",
Expand Down
6 changes: 5 additions & 1 deletion web-app/src/locales/vn/providers.json
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,11 @@
"tools": "Công cụ",
"vision": "Thị giác",
"embeddings": "Nhúng",
"notAvailable": "Chưa có"
"notAvailable": "Chưa có",
"warning": {
"title": "Hãy Thận Trọng",
"description": "Việc sửa đổi khả năng của mô hình có thể ảnh hưởng đến hiệu suất và chức năng. Cài đặt không chính xác có thể gây ra hành vi hoặc lỗi không mong muốn."
}
},
"addProvider": "Thêm nhà cung cấp",
"addOpenAIProvider": "Thêm nhà cung cấp OpenAI",
Expand Down
6 changes: 5 additions & 1 deletion web-app/src/locales/zh-CN/providers.json
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,11 @@
"tools": "工具",
"vision": "视觉",
"embeddings": "嵌入",
"notAvailable": "尚不可用"
"notAvailable": "尚不可用",
"warning": {
"title": "谨慎操作",
"description": "修改模型功能可能会影响性能和功能。错误的设置可能导致意外行为或错误。"
}
},
"addProvider": "添加提供商",
"addOpenAIProvider": "添加 OpenAI 提供商",
Expand Down
6 changes: 5 additions & 1 deletion web-app/src/locales/zh-TW/providers.json
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,11 @@
"tools": "工具",
"vision": "視覺",
"embeddings": "嵌入",
"notAvailable": "尚不可用"
"notAvailable": "尚不可用",
"warning": {
"title": "請謹慎操作",
"description": "修改模型功能可能會影響效能和功能。錯誤的設定可能導致意外行為或錯誤。"
}
},
"addProvider": "新增提供者",
"addOpenAIProvider": "新增 OpenAI 提供者",
Expand Down
38 changes: 24 additions & 14 deletions web-app/src/routes/settings/providers/$providerName.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -93,16 +93,19 @@ function ProviderDetail() {
const handleModelImportSuccess = async (importedModelName?: string) => {
// Refresh the provider to update the models list
await serviceHub.providers().getProviders().then(setProviders)

// If a model was imported and it might have vision capabilities, check and update
if (importedModelName && providerName === 'llamacpp') {
try {
const mmprojExists = await serviceHub.models().checkMmprojExists(importedModelName)
const mmprojExists = await serviceHub
.models()
.checkMmprojExists(importedModelName)
if (mmprojExists) {
// Get the updated provider after refresh
const { getProviderByName, updateProvider: updateProviderState } = useModelProvider.getState()
const { getProviderByName, updateProvider: updateProviderState } =
useModelProvider.getState()
const llamacppProvider = getProviderByName('llamacpp')

if (llamacppProvider) {
const modelIndex = llamacppProvider.models.findIndex(
(m: Model) => m.id === importedModelName
Expand All @@ -111,16 +114,25 @@ function ProviderDetail() {
const model = llamacppProvider.models[modelIndex]
const capabilities = model.capabilities || []

// Add 'vision' capability if not already present
if (!capabilities.includes('vision')) {
// Add 'vision' capability if not already present AND if user hasn't manually configured capabilities
// Check if model has a custom capabilities config flag
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const hasUserConfiguredCapabilities = (model as any)._userConfiguredCapabilities === true

if (!capabilities.includes('vision') && !hasUserConfiguredCapabilities) {
const updatedModels = [...llamacppProvider.models]
updatedModels[modelIndex] = {
...model,
capabilities: [...capabilities, 'vision'],
}
// Mark this as auto-detected, not user-configured
_autoDetectedVision: true,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
} as any

updateProviderState('llamacpp', { models: updatedModels })
console.log(`Vision capability added to model after provider refresh: ${importedModelName}`)
console.log(
`Vision capability auto-added to model after provider refresh: ${importedModelName}`
)
}
}
}
Expand Down Expand Up @@ -606,12 +618,10 @@ function ProviderDetail() {
}
actions={
<div className="flex items-center gap-0.5">
{provider && provider.provider !== 'llamacpp' && (
<DialogEditModel
provider={provider}
modelId={model.id}
/>
)}
<DialogEditModel
provider={provider}
modelId={model.id}
/>
{model.settings && (
<ModelSetting
provider={provider}
Expand Down
Loading