Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 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
4 changes: 3 additions & 1 deletion 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 @@ -105,22 +105,24 @@
try {
// Only check mmproj for llamacpp provider
if (selectedProvider === 'llamacpp') {
const hasLocalMmproj = await serviceHub.models().checkMmprojExists(selectedModel.id)
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')
) {
setHasMmproj(true)
} else {
setHasMmproj(false)
}

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

View workflow job for this annotation

GitHub Actions / coverage-check

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

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

View workflow job for this annotation

GitHub Actions / coverage-check

123-125 lines are not covered with tests
}
}

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

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

View workflow job for this annotation

GitHub Actions / coverage-check

141-142 lines are not covered with tests
setMessage('')
sendMessage(
prompt,
Expand Down Expand Up @@ -178,8 +180,8 @@

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

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

View workflow job for this annotation

GitHub Actions / coverage-check

183-184 lines are not covered with tests
}, [dropdownToolsAvailable, tooltipToolsAvailable])

// Focus when thread changes
Expand All @@ -201,39 +203,39 @@

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

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

View workflow job for this annotation

GitHub Actions / coverage-check

206-208 lines are not covered with tests
[abortControllers, cancelToolCall]
)

const fileInputRef = useRef<HTMLInputElement>(null)

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

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

View workflow job for this annotation

GitHub Actions / coverage-check

215-216 lines are not covered with tests

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

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

View workflow job for this annotation

GitHub Actions / coverage-check

219-222 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 235 in web-app/src/containers/ChatInput.tsx

View workflow job for this annotation

GitHub Actions / coverage-check

225-235 lines are not covered with tests

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

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

View workflow job for this annotation

GitHub Actions / coverage-check

238 line is not covered with tests

if (files && files.length > 0) {
const maxSize = 10 * 1024 * 1024 // 10MB in bytes
Expand Down
69 changes: 43 additions & 26 deletions web-app/src/containers/DropdownModelProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ const DropdownModelProvider = ({
[getProviderByName, updateProvider, serviceHub]
)

// Initialize model provider only once
// Initialize model provider - avoid race conditions with manual selections
useEffect(() => {
const initializeModel = async () => {
// Auto select model when existing thread is passed
Expand All @@ -150,11 +150,13 @@ const DropdownModelProvider = ({
}
// Check mmproj existence for llamacpp models
if (model?.provider === 'llamacpp') {
await serviceHub.models().checkMmprojExistsAndUpdateOffloadMMprojSetting(
model.id as string,
updateProvider,
getProviderByName
)
await serviceHub
.models()
.checkMmprojExistsAndUpdateOffloadMMprojSetting(
model.id as string,
updateProvider,
getProviderByName
)
// Also check vision capability
await checkAndUpdateModelVisionCapability(model.id as string)
}
Expand All @@ -164,11 +166,13 @@ const DropdownModelProvider = ({
if (lastUsed && checkModelExists(lastUsed.provider, lastUsed.model)) {
selectModelProvider(lastUsed.provider, lastUsed.model)
if (lastUsed.provider === 'llamacpp') {
await serviceHub.models().checkMmprojExistsAndUpdateOffloadMMprojSetting(
lastUsed.model,
updateProvider,
getProviderByName
)
await serviceHub
.models()
.checkMmprojExistsAndUpdateOffloadMMprojSetting(
lastUsed.model,
updateProvider,
getProviderByName
)
// Also check vision capability
await checkAndUpdateModelVisionCapability(lastUsed.model)
}
Expand All @@ -186,19 +190,28 @@ const DropdownModelProvider = ({
}
selectModelProvider('', '')
}
} else if (PlatformFeatures[PlatformFeature.WEB_AUTO_MODEL_SELECTION] && !selectedModel) {
// For web-only builds, always auto-select the first model from jan provider if none is selected
const janProvider = providers.find(
(p) => p.provider === 'jan' && p.active && p.models.length > 0
)
if (janProvider && janProvider.models.length > 0) {
const firstModel = janProvider.models[0]
selectModelProvider(janProvider.provider, firstModel.id)
} else {
// Get current state for web auto-selection check
const currentState = { selectedModel, selectedProvider }
if (
PlatformFeatures[PlatformFeature.WEB_AUTO_MODEL_SELECTION] &&
!currentState.selectedModel &&
!currentState.selectedProvider
) {
// For web-only builds, auto-select the first model from jan provider only if nothing is selected
const janProvider = providers.find(
(p) => p.provider === 'jan' && p.active && p.models.length > 0
)
if (janProvider && janProvider.models.length > 0) {
const firstModel = janProvider.models[0]
selectModelProvider(janProvider.provider, firstModel.id)
}
}
}
}

initializeModel()
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [
model,
selectModelProvider,
Expand All @@ -210,7 +223,7 @@ const DropdownModelProvider = ({
getProviderByName,
checkAndUpdateModelVisionCapability,
serviceHub,
selectedModel,
// selectedModel and selectedProvider intentionally excluded to prevent race conditions
])

// Update display model when selection changes
Expand Down Expand Up @@ -376,11 +389,13 @@ const DropdownModelProvider = ({

// Check mmproj existence for llamacpp models
if (searchableModel.provider.provider === 'llamacpp') {
await serviceHub.models().checkMmprojExistsAndUpdateOffloadMMprojSetting(
searchableModel.model.id,
updateProvider,
getProviderByName
)
await serviceHub
.models()
.checkMmprojExistsAndUpdateOffloadMMprojSetting(
searchableModel.model.id,
updateProvider,
getProviderByName
)
// Also check vision capability
await checkAndUpdateModelVisionCapability(searchableModel.model.id)
}
Expand Down Expand Up @@ -572,7 +587,9 @@ const DropdownModelProvider = ({
{getProviderTitle(providerInfo.provider)}
</span>
</div>
{PlatformFeatures[PlatformFeature.MODEL_PROVIDER_SETTINGS] && (
{PlatformFeatures[
PlatformFeature.MODEL_PROVIDER_SETTINGS
] && (
<div
className="size-6 cursor-pointer flex items-center justify-center rounded-sm hover:bg-main-view-fg/10 transition-all duration-200 ease-in-out"
onClick={(e) => {
Expand Down
Loading
Loading