refactor(tui): extract shared frontend helpers (#37868)
This commit is contained in:
parent
deee40c572
commit
0eb71d0fc7
52 changed files with 1655 additions and 1614 deletions
|
|
@ -9,6 +9,14 @@ import { useArgs } from "./args"
|
|||
import { useClient } from "./client"
|
||||
import { RGBA } from "@opentui/core"
|
||||
import { readJson, writeJsonAtomic } from "../util/persistence"
|
||||
import {
|
||||
createModelPreferenceRepository,
|
||||
cycleModelVariant,
|
||||
modelPreferenceKey,
|
||||
normalizeModelVariant,
|
||||
type ModelPreference,
|
||||
type ModelPreferenceModel,
|
||||
} from "../model-preference"
|
||||
import { useTheme } from "./theme"
|
||||
import { useToast } from "../ui/toast"
|
||||
import { useRoute } from "./route"
|
||||
|
|
@ -34,13 +42,13 @@ export function parseModel(model: string) {
|
|||
}
|
||||
|
||||
export function recentModels(
|
||||
model: { providerID: string; modelID: string },
|
||||
recent: { providerID: string; modelID: string }[],
|
||||
model: ModelPreferenceModel,
|
||||
recent: ModelPreferenceModel[],
|
||||
) {
|
||||
const seen = new Set<string>()
|
||||
return [model, ...recent]
|
||||
.filter((item) => {
|
||||
const key = `${item.providerID}/${item.modelID}`
|
||||
const key = modelPreferenceKey(item)
|
||||
if (seen.has(key)) return false
|
||||
seen.add(key)
|
||||
return true
|
||||
|
|
@ -62,13 +70,13 @@ export const { use: useLocal, provider: LocalProvider } = createSimpleContext({
|
|||
const event = useEvent()
|
||||
const permission = usePermission()
|
||||
|
||||
function isModelValid(model: { providerID: string; modelID: string }) {
|
||||
function isModelValid(model: ModelPreferenceModel) {
|
||||
return !!data.location.model
|
||||
.list()
|
||||
?.some((item) => item.providerID === model.providerID && item.id === model.modelID)
|
||||
}
|
||||
|
||||
function getFirstValidModel(...modelFns: (() => { providerID: string; modelID: string } | undefined)[]) {
|
||||
function getFirstValidModel(...modelFns: (() => ModelPreferenceModel | undefined)[]) {
|
||||
for (const modelFn of modelFns) {
|
||||
const model = modelFn()
|
||||
if (!model) continue
|
||||
|
|
@ -144,25 +152,12 @@ export const { use: useLocal, provider: LocalProvider } = createSimpleContext({
|
|||
const agent = createAgent()
|
||||
|
||||
function createModel() {
|
||||
const [modelStore, setModelStore] = createStore<{
|
||||
ready: boolean
|
||||
model: Record<
|
||||
string,
|
||||
{
|
||||
providerID: string
|
||||
modelID: string
|
||||
}
|
||||
>
|
||||
recent: {
|
||||
providerID: string
|
||||
modelID: string
|
||||
}[]
|
||||
favorite: {
|
||||
providerID: string
|
||||
modelID: string
|
||||
}[]
|
||||
variant: Record<string, string | undefined>
|
||||
}>({
|
||||
const [modelStore, setModelStore] = createStore<
|
||||
ModelPreference & {
|
||||
ready: boolean
|
||||
model: Record<string, ModelPreferenceModel>
|
||||
}
|
||||
>({
|
||||
ready: false,
|
||||
model: {},
|
||||
recent: [],
|
||||
|
|
@ -170,7 +165,7 @@ export const { use: useLocal, provider: LocalProvider } = createSimpleContext({
|
|||
variant: {},
|
||||
})
|
||||
|
||||
const filePath = path.join(paths.state, "model.json")
|
||||
const repository = createModelPreferenceRepository(path.join(paths.state, "model.json"))
|
||||
const state = {
|
||||
pending: false,
|
||||
}
|
||||
|
|
@ -181,21 +176,21 @@ export const { use: useLocal, provider: LocalProvider } = createSimpleContext({
|
|||
return
|
||||
}
|
||||
state.pending = false
|
||||
void writeJsonAtomic(filePath, {
|
||||
recent: modelStore.recent,
|
||||
favorite: modelStore.favorite,
|
||||
variant: modelStore.variant,
|
||||
})
|
||||
void repository
|
||||
.patch({
|
||||
recent: modelStore.recent,
|
||||
favorite: modelStore.favorite,
|
||||
variant: modelStore.variant,
|
||||
})
|
||||
.catch(() => undefined)
|
||||
}
|
||||
|
||||
readJson<unknown>(filePath)
|
||||
.then((x) => {
|
||||
if (!x || typeof x !== "object") return
|
||||
const value = x as Record<string, unknown>
|
||||
if (Array.isArray(value.recent)) setModelStore("recent", value.recent)
|
||||
if (Array.isArray(value.favorite)) setModelStore("favorite", value.favorite)
|
||||
if (typeof value.variant === "object" && value.variant !== null)
|
||||
setModelStore("variant", value.variant as Record<string, string | undefined>)
|
||||
repository
|
||||
.load()
|
||||
.then((value) => {
|
||||
setModelStore("recent", value.recent)
|
||||
setModelStore("favorite", value.favorite)
|
||||
setModelStore("variant", value.variant)
|
||||
})
|
||||
.catch(() => {})
|
||||
.finally(() => {
|
||||
|
|
@ -360,14 +355,12 @@ export const { use: useLocal, provider: LocalProvider } = createSimpleContext({
|
|||
selected() {
|
||||
const m = currentModel()
|
||||
if (!m) return undefined
|
||||
const key = `${m.providerID}/${m.modelID}`
|
||||
return modelStore.variant[key] ?? "default"
|
||||
return normalizeModelVariant(modelStore.variant[modelPreferenceKey(m)])
|
||||
},
|
||||
current() {
|
||||
const v = this.selected()
|
||||
if (!v) return undefined
|
||||
if (v !== "default" && this.list().includes(v)) return v
|
||||
return "default"
|
||||
if (v && this.list().includes(v)) return v
|
||||
return undefined
|
||||
},
|
||||
list() {
|
||||
const m = currentModel()
|
||||
|
|
@ -380,24 +373,13 @@ export const { use: useLocal, provider: LocalProvider } = createSimpleContext({
|
|||
set(value: string | undefined) {
|
||||
const m = currentModel()
|
||||
if (!m) return
|
||||
const key = `${m.providerID}/${m.modelID}`
|
||||
setModelStore("variant", key, value ?? "default")
|
||||
setModelStore("variant", modelPreferenceKey(m), normalizeModelVariant(value))
|
||||
save()
|
||||
},
|
||||
cycle() {
|
||||
const variants = this.list()
|
||||
if (variants.length === 0) return
|
||||
const current = this.current()
|
||||
if (!current) {
|
||||
this.set(variants[0])
|
||||
return
|
||||
}
|
||||
const index = variants.indexOf(current)
|
||||
if (index === -1 || index === variants.length - 1) {
|
||||
this.set(variants[0])
|
||||
return
|
||||
}
|
||||
this.set(variants[index + 1])
|
||||
this.set(cycleModelVariant(this.current(), variants))
|
||||
},
|
||||
},
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
import path from "path"
|
||||
import { abbreviateHome } from "../runtime"
|
||||
import { formatPath } from "../util/path-format"
|
||||
import { useLocation } from "./location"
|
||||
import { useTuiPaths } from "./runtime"
|
||||
|
||||
|
|
@ -8,17 +7,6 @@ export function usePathFormatter() {
|
|||
const location = useLocation()
|
||||
return {
|
||||
path: () => location.current?.directory || paths.cwd,
|
||||
format: (input?: string) => formatPath(input, location.current?.directory || paths.cwd, paths.home),
|
||||
format: (input?: string) => formatPath(input, { base: location.current?.directory || paths.cwd, home: paths.home }),
|
||||
}
|
||||
}
|
||||
|
||||
function formatPath(input: string | undefined, base: string, home: string) {
|
||||
if (typeof input !== "string" || !input) return ""
|
||||
|
||||
const absolute = path.isAbsolute(input) ? input : path.resolve(base, input)
|
||||
const relative = path.relative(base, absolute)
|
||||
|
||||
if (!relative) return "."
|
||||
if (relative !== ".." && !relative.startsWith(".." + path.sep)) return relative
|
||||
return abbreviateHome(absolute, home)
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue