diff --git a/gui/src/components/AccountDialog.tsx b/gui/src/components/AccountDialog.tsx index c979e2e1f0..04937b31da 100644 --- a/gui/src/components/AccountDialog.tsx +++ b/gui/src/components/AccountDialog.tsx @@ -110,7 +110,7 @@ function AccountDialog() { {profiles.map((option, idx) => ( diff --git a/gui/src/components/OnboardingCard/components/BestExperienceConfigForm.tsx b/gui/src/components/OnboardingCard/components/BestExperienceConfigForm.tsx index 78f2f95b25..52f1d2a607 100644 --- a/gui/src/components/OnboardingCard/components/BestExperienceConfigForm.tsx +++ b/gui/src/components/OnboardingCard/components/BestExperienceConfigForm.tsx @@ -9,7 +9,10 @@ import { providers } from "../../../pages/AddNewModel/configs/providers"; import { setDefaultModel } from "../../../redux/slices/stateSlice"; import AddModelButtonSubtext from "../../AddModelButtonSubtext"; -const { anthropic: chatProvider, mistral: autocompleteProvider } = providers; +const { anthropic, mistral } = providers; +const chatProvider = anthropic!; +const autocompleteProvider = mistral!; + const { claude35Sonnet: chatModel, claude3Haiku: repoMapModel, diff --git a/gui/src/components/OnboardingCard/components/OllamaStatus.tsx b/gui/src/components/OnboardingCard/components/OllamaStatus.tsx index dc09449384..15132518ed 100644 --- a/gui/src/components/OnboardingCard/components/OllamaStatus.tsx +++ b/gui/src/components/OnboardingCard/components/OllamaStatus.tsx @@ -13,9 +13,7 @@ interface OllamaStatusProps { isOllamaConnected: boolean; } -const { - ollama: { downloadUrl }, -} = providers; +const downloadUrl = providers.ollama!.downloadUrl!; export function OllamaStatus({ isOllamaConnected }: OllamaStatusProps) { const ideMessenger = useContext(IdeMessengerContext); diff --git a/gui/src/components/dialogs/AddDocsDialog.tsx b/gui/src/components/dialogs/AddDocsDialog.tsx index 00134a6f73..2559dc2050 100644 --- a/gui/src/components/dialogs/AddDocsDialog.tsx +++ b/gui/src/components/dialogs/AddDocsDialog.tsx @@ -123,21 +123,23 @@ function AddDocsDialog() { } const handleSelectSuggestion = (docsResult: PackageDocsResult) => { - if (docsResult.error) { + if (docsResult.error || !docsResult.details) { setTitle(docsResult.packageInfo.name); setStartUrl(""); urlRef.current?.focus(); return; } + const suggestedTitle = + docsResult.details.title ?? docsResult.packageInfo.name; if (docsResult.details?.docsLinkWarning) { - setTitle(docsResult.packageInfo.name); + setTitle(suggestedTitle); setStartUrl(docsResult.details.docsLink); urlRef.current?.focus(); return; } const siteIndexingConfig: SiteIndexingConfig = { startUrl: docsResult.details.docsLink, - title: docsResult.details.title, + title: suggestedTitle, faviconUrl: undefined, }; @@ -185,7 +187,7 @@ function AddDocsDialog() { }} >
- {error || details.docsLinkWarning ? ( + {error || details?.docsLinkWarning ? (
{name}
- {error ? ( + {error || !details?.docsLink ? ( No docs link found diff --git a/gui/src/components/find/FindWidget.tsx b/gui/src/components/find/FindWidget.tsx index 60a9bf2a96..cd9088302c 100644 --- a/gui/src/components/find/FindWidget.tsx +++ b/gui/src/components/find/FindWidget.tsx @@ -75,7 +75,7 @@ export const useFindWidget = (searchRef: RefObject) => { const [open, setOpen] = useState(false); const openWidget = useCallback(() => { setOpen(true); - inputRef?.current.select(); + inputRef?.current?.select(); }, [setOpen, inputRef]); // Search settings and results @@ -92,7 +92,7 @@ export const useFindWidget = (searchRef: RefObject) => { const scrollToMatch = useCallback( (match: SearchMatch) => { setCurrentMatch(match); - searchRef.current.scrollTo({ + searchRef?.current?.scrollTo({ top: match.overlayRectangle.top - searchRef.current.clientHeight / 2, left: match.overlayRectangle.left - searchRef.current.clientWidth / 2, behavior: "smooth", @@ -173,8 +173,10 @@ export const useFindWidget = (searchRef: RefObject) => { (scrollTo: ScrollToMatchOption = "none", clearFirst = false) => { if (clearFirst) setMatches([]); + const searchContainer = searchRef.current; + const _query = debouncedInput.current; // trimStart - decided no because spaces should be fully searchable - if (!searchRef.current || !_query) { + if (!searchContainer || !_query) { setMatches([]); return; } @@ -215,7 +217,7 @@ export const useFindWidget = (searchRef: RefObject) => { textNodes.forEach((textNode, idx) => { // Hacky way to detect code blocks that be wider than client and cause absolute positioning to fail const highlightFullLine = - textNode.parentElement.className.includes("hljs"); + textNode.parentElement?.className.includes("hljs"); let nodeTextValue = caseSensitive ? textNode.nodeValue @@ -232,13 +234,9 @@ export const useFindWidget = (searchRef: RefObject) => { startIndex = endIndex; const top = - rect.top + - searchRef.current.clientTop + - searchRef.current.scrollTop; + rect.top + searchContainer.clientTop + searchContainer.scrollTop; const left = - rect.left + - searchRef.current.clientLeft + - searchRef.current.scrollLeft; + rect.left + searchContainer.clientLeft + searchContainer.scrollLeft; // Build a match result and push to matches const newMatch: SearchMatch = { @@ -248,7 +246,7 @@ export const useFindWidget = (searchRef: RefObject) => { top, left: highlightFullLine ? 2 : left, width: highlightFullLine - ? searchRef.current.clientWidth - 4 + ? searchContainer.clientWidth - 4 : rect.width, // equivalent of adding 2 px x padding height: rect.height, }, @@ -294,7 +292,9 @@ export const useFindWidget = (searchRef: RefObject) => { scrollToMatch(filteredMatches[0]); } if (scrollTo === "closest") { - scrollToMatch(closestMatchToMiddle); + if (closestMatchToMiddle) { + scrollToMatch(closestMatchToMiddle); + } } if (scrollTo === "none") { if (closestMatchToMiddle) { @@ -333,13 +333,14 @@ export const useFindWidget = (searchRef: RefObject) => { // Could consider doing any window click but I only handled search div here // Since usually only clicks in search div will cause content changes in search div useEffect(() => { - if (!open || !searchRef.current) return; + const searchContainer = searchRef.current; + if (!open || !searchContainer) return; const handleSearchRefClick = () => { refreshSearch("none"); }; - searchRef.current.addEventListener("click", handleSearchRefClick); + searchContainer.addEventListener("click", handleSearchRefClick); return () => { - searchRef.current.removeEventListener("click", handleSearchRefClick); + searchContainer.removeEventListener("click", handleSearchRefClick); }; }, [searchRef.current, refreshSearch, open]); diff --git a/gui/src/components/mainInput/ContextItemsPeek.tsx b/gui/src/components/mainInput/ContextItemsPeek.tsx index 56608b837b..c403b63950 100644 --- a/gui/src/components/mainInput/ContextItemsPeek.tsx +++ b/gui/src/components/mainInput/ContextItemsPeek.tsx @@ -1,7 +1,7 @@ import { ChevronDownIcon, ChevronRightIcon } from "@heroicons/react/24/outline"; import { ContextItemWithId } from "core"; import { ctxItemToRifWithContents } from "core/commands/util"; -import { useContext, useState } from "react"; +import { useContext, useMemo, useState } from "react"; import { AnimatedEllipsis, lightGray, vscBackground } from ".."; import { IdeMessengerContext } from "../../context/IdeMessenger"; import FileIcon from "../FileIcon"; @@ -124,9 +124,13 @@ function ContextItemsPeek({ }: ContextItemsPeekProps) { const [open, setOpen] = useState(false); - const ctxItems = contextItems?.filter( - (ctxItem) => !ctxItem.name.includes(INSTRUCTIONS_BASE_ITEM.name), - ); + const ctxItems = useMemo(() => { + return ( + contextItems?.filter( + (ctxItem) => !ctxItem.name.includes(INSTRUCTIONS_BASE_ITEM.name), + ) ?? [] + ); + }, [contextItems]); const isGatheringContext = useSelector( (store: RootState) => store.state.context.isGathering, diff --git a/gui/src/components/mainInput/InputToolbar.tsx b/gui/src/components/mainInput/InputToolbar.tsx index c335ce978b..e1fd7ad745 100644 --- a/gui/src/components/mainInput/InputToolbar.tsx +++ b/gui/src/components/mainInput/InputToolbar.tsx @@ -21,7 +21,7 @@ import { import { ToolTip } from "../gui/Tooltip"; import ModelSelect from "../modelSelection/ModelSelect"; -const StyledDiv = styled.div<{ isHidden: boolean }>` +const StyledDiv = styled.div<{ isHidden?: boolean }>` padding-top: 4px; justify-content: space-between; gap: 1px; @@ -117,8 +117,9 @@ function InputToolbar(props: InputToolbarProps) { style={{ display: "none" }} accept=".jpg,.jpeg,.png,.gif,.svg,.webp" onChange={(e) => { - for (const file of e.target.files) { - props.onImageFileSelected(file); + const files = e.target?.files ?? []; + for (const file of files) { + props.onImageFileSelected?.(file); } }} /> @@ -157,9 +158,9 @@ function InputToolbar(props: InputToolbarProps) { ) : ( - props.onEnter({ + props.onEnter?.({ useCodebase: true, noContext: !useActiveFile, }) diff --git a/gui/src/components/mainInput/TipTapEditor.tsx b/gui/src/components/mainInput/TipTapEditor.tsx index 2004d9fc60..5d015e9d40 100644 --- a/gui/src/components/mainInput/TipTapEditor.tsx +++ b/gui/src/components/mainInput/TipTapEditor.tsx @@ -132,7 +132,10 @@ const HoverTextDiv = styled.div` `; const IMAGE_RESOLUTION = 1024; -function getDataUrlForFile(file: File, img): string { +function getDataUrlForFile( + file: File, + img: HTMLImageElement, +): string | undefined { const targetWidth = IMAGE_RESOLUTION; const targetHeight = IMAGE_RESOLUTION; const scaleFactor = Math.min( @@ -145,6 +148,10 @@ function getDataUrlForFile(file: File, img): string { canvas.height = img.height * scaleFactor; const ctx = canvas.getContext("2d"); + if (!ctx) { + console.error("Error getting image data url: 2d context not found"); + return; + } ctx.drawImage(img, 0, 0, canvas.width, canvas.height); const downsizedDataUrl = canvas.toDataURL("image/jpeg", 0.7); @@ -293,6 +300,9 @@ function TipTapEditor(props: TipTapEditorProps) { return await new Promise((resolve) => { img.onload = function () { const dataUrl = getDataUrlForFile(file, img); + if (!dataUrl) { + return; + } let image = new window.Image(); image.src = dataUrl; @@ -327,26 +337,29 @@ function TipTapEditor(props: TipTapEditorProps) { handleDOMEvents: { paste(view, event) { const model = defaultModelRef.current; - const items = event.clipboardData.items; - for (const item of items) { - const file = item.getAsFile(); - file && - modelSupportsImages( - model.provider, - model.model, - model.title, - model.capabilities, - ) && - handleImageFile(file).then((resp) => { - if (!resp) return; - const [img, dataUrl] = resp; - const { schema } = view.state; - const node = schema.nodes.image.create({ - src: dataUrl, + if (!model) return; + const items = event.clipboardData?.items; + if (items) { + for (const item of items) { + const file = item.getAsFile(); + file && + modelSupportsImages( + model.provider, + model.model, + model.title, + model.capabilities, + ) && + handleImageFile(file).then((resp) => { + if (!resp) return; + const [img, dataUrl] = resp; + const { schema } = view.state; + const node = schema.nodes.image.create({ + src: dataUrl, + }); + const tr = view.state.tr.insert(0, node); + view.dispatch(tr); }); - const tr = view.state.tr.insert(0, node); - view.dispatch(tr); - }); + } } }, }, diff --git a/gui/src/components/mainInput/handleMetaKeyIssues.ts b/gui/src/components/mainInput/handleMetaKeyIssues.ts index 35fd847c9e..77cbbb4dce 100644 --- a/gui/src/components/mainInput/handleMetaKeyIssues.ts +++ b/gui/src/components/mainInput/handleMetaKeyIssues.ts @@ -16,11 +16,11 @@ export const handleJetBrainsOSRMetaKeyIssues = ( const handlers: Record void> = { Backspace: () => handleJetBrainsMetaBackspace(editor), - ArrowLeft: () => selection.modify(alter, "backward", "lineboundary"), - ArrowRight: () => selection.modify(alter, "forward", "lineboundary"), - ArrowDown: () => selection.modify(alter, "forward", "documentboundary"), + ArrowLeft: () => selection?.modify(alter, "backward", "lineboundary"), + ArrowRight: () => selection?.modify(alter, "forward", "lineboundary"), + ArrowDown: () => selection?.modify(alter, "forward", "documentboundary"), ArrowUp: () => { - selection.modify(alter, "backward", "documentboundary"); + selection?.modify(alter, "backward", "documentboundary"); }, }; diff --git a/gui/src/components/mainInput/resolveInput.ts b/gui/src/components/mainInput/resolveInput.ts index b12804d724..96ab0d93ba 100644 --- a/gui/src/components/mainInput/resolveInput.ts +++ b/gui/src/components/mainInput/resolveInput.ts @@ -36,72 +36,74 @@ async function resolveEditorContent( let parts: MessagePart[] = []; let contextItemAttrs: MentionAttrs[] = []; const selectedCode: RangeInFile[] = []; - let slashCommand = undefined; - for (const p of editorState?.content) { - if (p.type === "paragraph") { - const [text, ctxItems, foundSlashCommand] = resolveParagraph(p); + let slashCommand: string | undefined = undefined; + if (editorState?.content) { + for (const p of editorState.content) { + if (p.type === "paragraph") { + const [text, ctxItems, foundSlashCommand] = resolveParagraph(p); - // Only take the first slash command\ - if (foundSlashCommand && typeof slashCommand === "undefined") { - slashCommand = foundSlashCommand; - } + // Only take the first slash command\ + if (foundSlashCommand && typeof slashCommand === "undefined") { + slashCommand = foundSlashCommand; + } - contextItemAttrs.push(...ctxItems); + contextItemAttrs.push(...ctxItems); - if (text === "") { - continue; - } + if (text === "") { + continue; + } - if (parts[parts.length - 1]?.type === "text") { - parts[parts.length - 1].text += "\n" + text; - } else { - parts.push({ type: "text", text }); - } - } else if (p.type === "codeBlock") { - if (!p.attrs.item.editing) { - let meta = p.attrs.item.description.split(" "); - let relativePath = meta[0] || ""; - let extName = relativePath.split(".").slice(-1)[0]; - const text = - "\n\n" + - "```" + - extName + - " " + - p.attrs.item.description + - "\n" + - p.attrs.item.content + - "\n```"; if (parts[parts.length - 1]?.type === "text") { parts[parts.length - 1].text += "\n" + text; } else { - parts.push({ - type: "text", - text, - }); + parts.push({ type: "text", text }); + } + } else if (p.type === "codeBlock") { + if (!p.attrs.item.editing) { + let meta = p.attrs.item.description.split(" "); + let relativePath = meta[0] || ""; + let extName = relativePath.split(".").slice(-1)[0]; + const text = + "\n\n" + + "```" + + extName + + " " + + p.attrs.item.description + + "\n" + + p.attrs.item.content + + "\n```"; + if (parts[parts.length - 1]?.type === "text") { + parts[parts.length - 1].text += "\n" + text; + } else { + parts.push({ + type: "text", + text, + }); + } } - } - const name: string = p.attrs.item.name; - let lines = name.substring(name.lastIndexOf("(") + 1); - lines = lines.substring(0, lines.lastIndexOf(")")); - const [start, end] = lines.split("-"); + const name: string = p.attrs.item.name; + let lines = name.substring(name.lastIndexOf("(") + 1); + lines = lines.substring(0, lines.lastIndexOf(")")); + const [start, end] = lines.split("-"); - selectedCode.push({ - filepath: p.attrs.item.description, - range: { - start: { line: parseInt(start) - 1, character: 0 }, - end: { line: parseInt(end) - 1, character: 0 }, - }, - }); - } else if (p.type === "image") { - parts.push({ - type: "imageUrl", - imageUrl: { - url: p.attrs.src, - }, - }); - } else { - console.warn("Unexpected content type", p.type); + selectedCode.push({ + filepath: p.attrs.item.description, + range: { + start: { line: parseInt(start) - 1, character: 0 }, + end: { line: parseInt(end) - 1, character: 0 }, + }, + }); + } else if (p.type === "image") { + parts.push({ + type: "imageUrl", + imageUrl: { + url: p.attrs.src, + }, + }); + } else { + console.warn("Unexpected content type", p.type); + } } } @@ -209,10 +211,12 @@ function findLastIndex( return -1; // if no element satisfies the predicate } -function resolveParagraph(p: JSONContent): [string, MentionAttrs[], string] { +function resolveParagraph( + p: JSONContent, +): [string, MentionAttrs[], string | undefined] { let text = ""; const contextItems = []; - let slashCommand = undefined; + let slashCommand: string | undefined = undefined; for (const child of p.content || []) { if (child.type === "text") { text += text === "" ? child.text.trimStart() : child.text; diff --git a/gui/src/components/markdown/StepContainerPreActionButtons.tsx b/gui/src/components/markdown/StepContainerPreActionButtons.tsx index c316e769ff..fa84ae8ecc 100644 --- a/gui/src/components/markdown/StepContainerPreActionButtons.tsx +++ b/gui/src/components/markdown/StepContainerPreActionButtons.tsx @@ -64,7 +64,7 @@ export default function StepContainerPreActionButtons({ const [hovering, setHovering] = useState(false); const ideMessenger = useContext(IdeMessengerContext); const uiConfig = useUIConfig(); - const streamIdRef = useRef(null); + const streamIdRef = useRef(uuidv4()); const nextCodeBlockIndex = useSelector( (state: RootState) => state.state.nextCodeBlockToApplyIndex, ); @@ -75,12 +75,11 @@ export default function StepContainerPreActionButtons({ !isJetBrains() && isTerminalCodeBlock(language, codeBlockContent); const isNextCodeBlock = nextCodeBlockIndex === codeBlockIndex; - if (streamIdRef.current === null) { - streamIdRef.current = uuidv4(); - } - const defaultModel = useSelector(defaultModelSelector); function onClickApply() { + if (!defaultModel) { + return; + } ideMessenger.post("applyToFile", { streamId: streamIdRef.current, text: codeBlockContent, diff --git a/gui/src/components/markdown/StepContainerPreToolbar/StepContainerPreToolbar.tsx b/gui/src/components/markdown/StepContainerPreToolbar/StepContainerPreToolbar.tsx index 6a1d597095..b147fff2ed 100644 --- a/gui/src/components/markdown/StepContainerPreToolbar/StepContainerPreToolbar.tsx +++ b/gui/src/components/markdown/StepContainerPreToolbar/StepContainerPreToolbar.tsx @@ -101,6 +101,9 @@ export default function StepContainerPreToolbar( const defaultModel = useSelector(defaultModelSelector); function onClickApply() { + if (!defaultModel) { + return; + } ideMessenger.post("applyToFile", { streamId: streamIdRef.current, filepath: props.filepath, diff --git a/gui/src/components/markdown/StyledMarkdownPreview.tsx b/gui/src/components/markdown/StyledMarkdownPreview.tsx index 8db7e42535..caad6428c5 100644 --- a/gui/src/components/markdown/StyledMarkdownPreview.tsx +++ b/gui/src/components/markdown/StyledMarkdownPreview.tsx @@ -112,7 +112,7 @@ function getLanuageFromClassName(className: any): string | null { .find((word) => word.startsWith(HLJS_LANGUAGE_CLASSNAME_PREFIX)) ?.split("-")[1]; - return language; + return language ?? null; } function getCodeChildrenContent(children: any) { diff --git a/gui/src/components/modelSelection/ModelCard.tsx b/gui/src/components/modelSelection/ModelCard.tsx index 35891df799..85658d1734 100644 --- a/gui/src/components/modelSelection/ModelCard.tsx +++ b/gui/src/components/modelSelection/ModelCard.tsx @@ -120,8 +120,7 @@ function ModelCard(props: ModelCardProps) { if ((e.target as any).closest("a")) { return; } - - props.onClick(e, dimensionChoices, selectedProvider); + props.onClick?.(e, dimensionChoices, selectedProvider); } } > diff --git a/gui/src/components/modelSelection/ModelSelect.tsx b/gui/src/components/modelSelection/ModelSelect.tsx index fbaf52af4c..4725932114 100644 --- a/gui/src/components/modelSelection/ModelSelect.tsx +++ b/gui/src/components/modelSelection/ModelSelect.tsx @@ -41,7 +41,7 @@ interface ModelOptionProps { interface Option { value: string; title: string; - apiKey: string; + apiKey?: string; } const MAX_HEIGHT_PX = 300; @@ -278,6 +278,9 @@ function ModelSelect() { }, [options, defaultModel]); function calculatePosition() { + if (!buttonRef.current) { + return; + } const rect = buttonRef.current.getBoundingClientRect(); const spaceBelow = window.innerHeight - rect.bottom; const spaceAbove = rect.top; diff --git a/gui/src/context/VscTheme.tsx b/gui/src/context/VscTheme.tsx index dd3343493e..c376ee2b4a 100644 --- a/gui/src/context/VscTheme.tsx +++ b/gui/src/context/VscTheme.tsx @@ -56,7 +56,7 @@ const hljsToTextMate: Record = { function constructTheme( tmTheme: typeof window.fullColorTheme, ): Record { - const rules = tmTheme["rules"] || []; + const rules = tmTheme?.["rules"] || []; const tokenToForeground = {}; rules.forEach(({ token, foreground }) => { diff --git a/gui/src/hooks/useTutorialCard.ts b/gui/src/hooks/useTutorialCard.ts index 2fcbca0389..0a8e7aee97 100644 --- a/gui/src/hooks/useTutorialCard.ts +++ b/gui/src/hooks/useTutorialCard.ts @@ -12,7 +12,7 @@ export function useTutorialCard(): UseTutorialCard { const posthog = usePostHog(); const [showTutorialCard, setShowTutorialCard] = useState( - getLocalStorage("showTutorialCard"), + getLocalStorage("showTutorialCard") ?? true, ); function closeTutorialCard() { diff --git a/gui/src/pages/edit/Edit.tsx b/gui/src/pages/edit/Edit.tsx index 25647da95b..201a4bc4cf 100644 --- a/gui/src/pages/edit/Edit.tsx +++ b/gui/src/pages/edit/Edit.tsx @@ -2,7 +2,7 @@ import { ArrowLeftIcon } from "@heroicons/react/24/outline"; import { Editor, JSONContent } from "@tiptap/core"; import { InputModifiers, RangeInFileWithContents } from "core"; import { stripImages } from "core/llm/images"; -import { useCallback, useContext, useEffect } from "react"; +import { useCallback, useContext, useEffect, useMemo } from "react"; import { useDispatch, useSelector } from "react-redux"; import { useNavigate } from "react-router-dom"; import { NewSessionButton } from "../../components/mainInput/NewSessionButton"; @@ -45,6 +45,15 @@ export default function Edit() { (store: RootState) => store.state.config.contextProviders, ); + const filteredContextProviders = useMemo(() => { + return ( + availableContextProviders?.filter( + (provider) => + !EDIT_DISALLOWED_CONTEXT_PROVIDERS.includes(provider.title), + ) ?? [] + ); + }, [availableContextProviders]); + const history = useSelector((state: RootState) => state.state.history); const applyStates = useSelector( @@ -89,10 +98,6 @@ export default function Edit() { const hasPendingApplies = pendingApplyStates.length > 0; - const filteredContextProviders = availableContextProviders.filter( - (provider) => !EDIT_DISALLOWED_CONTEXT_PROVIDERS.includes(provider.title), - ); - async function handleSingleRangeEdit( editorState: JSONContent, modifiers: InputModifiers, diff --git a/gui/src/redux/slices/stateSlice.ts b/gui/src/redux/slices/stateSlice.ts index c92ee442a5..7b32247ff4 100644 --- a/gui/src/redux/slices/stateSlice.ts +++ b/gui/src/redux/slices/stateSlice.ts @@ -312,7 +312,7 @@ export const stateSlice = createSlice({ state.history = payload.history as any; state.title = payload.title; state.sessionId = payload.sessionId; - state.checkpoints = payload.checkpoints; + state.checkpoints = payload.checkpoints ?? []; state.curCheckpointIndex = 0; } else { state.history = []; diff --git a/gui/src/util/symbols.ts b/gui/src/util/symbols.ts index 5c4e1be127..5ce3b66c0a 100644 --- a/gui/src/util/symbols.ts +++ b/gui/src/util/symbols.ts @@ -15,7 +15,7 @@ export async function updateFileSymbolsFromContextItems( new Set( contextItems .filter((item) => item.uri?.type === "file" && item?.uri?.value) - .map((item) => item.uri.value), + .map((item) => item.uri!.value), ), ); // And then update symbols for those files