mirror of
https://github.com/pacnpal/Roo-Code.git
synced 2025-12-20 12:21:13 -05:00
Fuzzy search openrouter models
This commit is contained in:
@@ -85,6 +85,7 @@ const HistoryView = ({ onDone }: HistoryViewProps) => {
|
|||||||
((a.tokensIn || 0) + (a.tokensOut || 0) + (a.cacheWrites || 0) + (a.cacheReads || 0))
|
((a.tokensIn || 0) + (a.tokensOut || 0) + (a.cacheWrites || 0) + (a.cacheReads || 0))
|
||||||
)
|
)
|
||||||
case "mostRelevant":
|
case "mostRelevant":
|
||||||
|
// NOTE: you must never sort directly on object since it will cause members to be reordered
|
||||||
return searchQuery ? 0 : b.ts - a.ts // Keep fuse order if searching, otherwise sort by newest
|
return searchQuery ? 0 : b.ts - a.ts // Keep fuse order if searching, otherwise sort by newest
|
||||||
case "newest":
|
case "newest":
|
||||||
default:
|
default:
|
||||||
@@ -427,7 +428,10 @@ const ExportButton = ({ itemId }: { itemId: string }) => (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// https://gist.github.com/evenfrost/1ba123656ded32fb7a0cd4651efd4db0
|
// https://gist.github.com/evenfrost/1ba123656ded32fb7a0cd4651efd4db0
|
||||||
const highlight = (fuseSearchResult: FuseResult<any>[], highlightClassName: string = "history-item-highlight") => {
|
export const highlight = (
|
||||||
|
fuseSearchResult: FuseResult<any>[],
|
||||||
|
highlightClassName: string = "history-item-highlight"
|
||||||
|
) => {
|
||||||
const set = (obj: Record<string, any>, path: string, value: any) => {
|
const set = (obj: Record<string, any>, path: string, value: any) => {
|
||||||
const pathValue = path.split(".")
|
const pathValue = path.split(".")
|
||||||
let i: number
|
let i: number
|
||||||
|
|||||||
@@ -1,11 +1,13 @@
|
|||||||
import React, { useMemo, useState, useRef, useEffect, memo } from "react"
|
|
||||||
import { VSCodeTextField } from "@vscode/webview-ui-toolkit/react"
|
import { VSCodeTextField } from "@vscode/webview-ui-toolkit/react"
|
||||||
|
import Fuse from "fuse.js"
|
||||||
|
import React, { memo, useEffect, useMemo, useRef, useState } from "react"
|
||||||
|
import { useRemark } from "react-remark"
|
||||||
|
import { useMount } from "react-use"
|
||||||
import styled from "styled-components"
|
import styled from "styled-components"
|
||||||
import { useExtensionState } from "../../context/ExtensionStateContext"
|
import { useExtensionState } from "../../context/ExtensionStateContext"
|
||||||
import { useMount } from "react-use"
|
|
||||||
import { vscode } from "../../utils/vscode"
|
import { vscode } from "../../utils/vscode"
|
||||||
import { ModelInfoView, normalizeApiConfiguration } from "./ApiOptions"
|
import { ModelInfoView, normalizeApiConfiguration } from "./ApiOptions"
|
||||||
import { useRemark } from "react-remark"
|
import { highlight } from "../history/HistoryView"
|
||||||
|
|
||||||
const OpenRouterModelPicker: React.FC = () => {
|
const OpenRouterModelPicker: React.FC = () => {
|
||||||
const { apiConfiguration, setApiConfiguration, openRouterModels } = useExtensionState()
|
const { apiConfiguration, setApiConfiguration, openRouterModels } = useExtensionState()
|
||||||
@@ -31,12 +33,6 @@ const OpenRouterModelPicker: React.FC = () => {
|
|||||||
vscode.postMessage({ type: "refreshOpenRouterModels" })
|
vscode.postMessage({ type: "refreshOpenRouterModels" })
|
||||||
})
|
})
|
||||||
|
|
||||||
const filteredModelIds = useMemo(() => {
|
|
||||||
return Object.keys(openRouterModels)
|
|
||||||
.filter((modelId) => modelId.toLowerCase().includes(searchTerm.toLowerCase()))
|
|
||||||
.sort((a, b) => a.localeCompare(b))
|
|
||||||
}, [openRouterModels, searchTerm])
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const handleClickOutside = (event: MouseEvent) => {
|
const handleClickOutside = (event: MouseEvent) => {
|
||||||
if (dropdownRef.current && !dropdownRef.current.contains(event.target as Node)) {
|
if (dropdownRef.current && !dropdownRef.current.contains(event.target as Node)) {
|
||||||
@@ -50,8 +46,45 @@ const OpenRouterModelPicker: React.FC = () => {
|
|||||||
}
|
}
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
|
const searchableItems = useMemo(() => {
|
||||||
|
return Object.keys(openRouterModels)
|
||||||
|
.sort((a, b) => a.localeCompare(b))
|
||||||
|
.map((id) => ({
|
||||||
|
id,
|
||||||
|
html: id,
|
||||||
|
}))
|
||||||
|
}, [openRouterModels])
|
||||||
|
|
||||||
|
const fuse = useMemo(() => {
|
||||||
|
return new Fuse(searchableItems, {
|
||||||
|
keys: ["html"], // highlight function will update this
|
||||||
|
threshold: 0.6,
|
||||||
|
shouldSort: true,
|
||||||
|
isCaseSensitive: false,
|
||||||
|
ignoreLocation: false,
|
||||||
|
includeMatches: true,
|
||||||
|
minMatchCharLength: 1,
|
||||||
|
})
|
||||||
|
}, [searchableItems])
|
||||||
|
|
||||||
|
const modelSearchResults = useMemo(() => {
|
||||||
|
let results: { id: string; html: string }[] = searchTerm
|
||||||
|
? highlight(fuse.search(searchTerm), "model-item-highlight")
|
||||||
|
: searchableItems
|
||||||
|
// results.sort((a, b) => a.id.localeCompare(b.id)) NOTE: sorting like this causes ids in objects to be reordered and mismatched
|
||||||
|
return results
|
||||||
|
}, [searchableItems, searchTerm, fuse])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
<style>
|
||||||
|
{`
|
||||||
|
.model-item-highlight {
|
||||||
|
background-color: var(--vscode-editor-findMatchHighlightBackground);
|
||||||
|
color: inherit;
|
||||||
|
}
|
||||||
|
`}
|
||||||
|
</style>
|
||||||
<DropdownWrapper ref={dropdownRef}>
|
<DropdownWrapper ref={dropdownRef}>
|
||||||
<label htmlFor="model-search">
|
<label htmlFor="model-search">
|
||||||
<span style={{ fontWeight: 500 }}>Model</span>
|
<span style={{ fontWeight: 500 }}>Model</span>
|
||||||
@@ -65,7 +98,7 @@ const OpenRouterModelPicker: React.FC = () => {
|
|||||||
setIsDropdownVisible(true)
|
setIsDropdownVisible(true)
|
||||||
}}
|
}}
|
||||||
onFocus={() => setIsDropdownVisible(true)}
|
onFocus={() => setIsDropdownVisible(true)}
|
||||||
style={{ width: "100%", zIndex: 1001 }}>
|
style={{ width: "100%" }}>
|
||||||
{searchTerm && (
|
{searchTerm && (
|
||||||
<div
|
<div
|
||||||
className="input-icon-button codicon codicon-close"
|
className="input-icon-button codicon codicon-close"
|
||||||
@@ -83,10 +116,14 @@ const OpenRouterModelPicker: React.FC = () => {
|
|||||||
</VSCodeTextField>
|
</VSCodeTextField>
|
||||||
{isDropdownVisible && (
|
{isDropdownVisible && (
|
||||||
<DropdownList>
|
<DropdownList>
|
||||||
{filteredModelIds.map((modelId) => (
|
{modelSearchResults.map((item) => (
|
||||||
<DropdownItem key={modelId} onClick={() => handleModelChange(modelId)}>
|
<DropdownItem
|
||||||
{modelId}
|
key={item.id}
|
||||||
</DropdownItem>
|
onClick={() => handleModelChange(item.id)}
|
||||||
|
dangerouslySetInnerHTML={{
|
||||||
|
__html: item.html,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
))}
|
))}
|
||||||
</DropdownList>
|
</DropdownList>
|
||||||
)}
|
)}
|
||||||
|
|||||||
Reference in New Issue
Block a user