diff --git a/packages/jupyter-ai/src/components/settings/model-id-input.tsx b/packages/jupyter-ai/src/components/settings/model-id-input.tsx
index 888788d0b..0fc660d5c 100644
--- a/packages/jupyter-ai/src/components/settings/model-id-input.tsx
+++ b/packages/jupyter-ai/src/components/settings/model-id-input.tsx
@@ -1,9 +1,38 @@
import React, { useState, useEffect } from 'react';
-import { Autocomplete, TextField, Button, Box } from '@mui/material';
+import {
+ TextField,
+ Button,
+ Box,
+ Typography,
+ Menu,
+ MenuItem
+} from '@mui/material';
import { AiService } from '../../handler';
import { useStackingAlert } from '../mui-extras/stacking-alert';
import Save from '@mui/icons-material/Save';
+/**
+ * Highlights matched substrings in a given text by wrapping them in bold tags.
+ */
+const highlightMatches = (text: string, inputValue: string) => {
+ if (!inputValue) return text;
+
+ const parts = text.split(new RegExp(`(${inputValue})`, 'gi'));
+ return (
+
+ {parts.map((part, index) =>
+ part.toLowerCase() === inputValue.toLowerCase() ? (
+
+ {part}
+
+ ) : (
+ part
+ )
+ )}
+
+ );
+};
+
export type ModelIdInputProps = {
/**
* The label of the model ID input field.
@@ -51,8 +80,26 @@ export function ModelIdInput(props: ModelIdInputProps): JSX.Element {
const [updating, setUpdating] = useState(false);
const [input, setInput] = useState('');
+ const [anchorEl, setAnchorEl] = useState(null);
const alert = useStackingAlert();
+ const handleMenuOpen = (event: React.MouseEvent) => {
+ setAnchorEl(event.currentTarget);
+ };
+
+ const handleMenuClose = () => {
+ setAnchorEl(null);
+ };
+
+ const handleMenuItemClick = (value: string) => {
+ setInput(value);
+ handleMenuClose();
+ };
+
+ const filteredModels = models.filter(model =>
+ model.toLowerCase().includes(input.toLowerCase())
+ );
+
/**
* Effect: Fetch list of models and current model on initial render, based on
* the modality.
@@ -128,29 +175,95 @@ export function ModelIdInput(props: ModelIdInputProps): JSX.Element {
return (
- {
- // This condition prevents whitespace from being inserted in the model
- // ID by accident.
- if (newValue !== null && !newValue.includes(' ')) {
+ onChange={e => {
+ const newValue = e.target.value;
+ if (!newValue.includes(' ')) {
setInput(newValue);
}
}}
- renderInput={params => (
-
- )}
+ InputProps={{
+ endAdornment:
+ // input && filteredModels.length > 0 ? (
+ input ? (
+
+
+
+ {filteredModels.length > 0 ? (
+
+ Click to see {filteredModels.length} match
+ {filteredModels.length !== 1 ? 'es' : ''}
+
+ ) : (
+
+ No matches
+
+ )}
+
+
+ ) : null
+ }}
/>
+