fix(auth): deterministic fallback profile selection when default key missing
For models without explicit authProfile: - use bare provider key when present - use :default when present - otherwise choose first available provider profile (sorted) Also reflect inferred profile in TUI status when model has no explicit profile.pull/21353/head
parent
82746621de
commit
2e0666d19d
|
|
@ -1,5 +1,5 @@
|
|||
import { createStore } from "solid-js/store"
|
||||
import { batch, createEffect, createMemo } from "solid-js"
|
||||
import { batch, createEffect, createMemo, createResource } from "solid-js"
|
||||
import { useSync } from "@tui/context/sync"
|
||||
import { useTheme } from "@tui/context/theme"
|
||||
import { uniqueBy } from "remeda"
|
||||
|
|
@ -9,6 +9,7 @@ import { iife } from "@/util/iife"
|
|||
import { createSimpleContext } from "./helper"
|
||||
import { useToast } from "../ui/toast"
|
||||
import { Provider } from "@/provider/provider"
|
||||
import { Auth } from "@/auth"
|
||||
import { useArgs } from "./args"
|
||||
import { useSDK } from "./sdk"
|
||||
import { RGBA } from "@opentui/core"
|
||||
|
|
@ -208,6 +209,20 @@ export const { use: useLocal, provider: LocalProvider } = createSimpleContext({
|
|||
) ?? undefined
|
||||
)
|
||||
})
|
||||
const [auths] = createResource(async () => Auth.all())
|
||||
|
||||
const inferredProfile = (providerID: string) => {
|
||||
const data = auths()
|
||||
if (!data) return undefined
|
||||
if (providerID in data) return undefined
|
||||
if (`${providerID}:default` in data) return "default"
|
||||
const prefix = `${providerID}:`
|
||||
const profiles = Object.keys(data)
|
||||
.filter((key) => key.startsWith(prefix))
|
||||
.map((key) => key.slice(prefix.length))
|
||||
.sort()
|
||||
return profiles[0]
|
||||
}
|
||||
|
||||
return {
|
||||
current: currentModel,
|
||||
|
|
@ -232,10 +247,11 @@ export const { use: useLocal, provider: LocalProvider } = createSimpleContext({
|
|||
}
|
||||
const provider = sync.data.provider.find((x) => x.id === value.providerID)
|
||||
const info = provider?.models[value.modelID]
|
||||
const profile = value.authProfile ?? inferredProfile(value.providerID)
|
||||
return {
|
||||
provider: provider?.name ?? value.providerID,
|
||||
model: info?.name ?? value.modelID,
|
||||
profile: value.authProfile,
|
||||
profile,
|
||||
reasoning: info?.capabilities?.reasoning ?? false,
|
||||
}
|
||||
}),
|
||||
|
|
|
|||
|
|
@ -90,16 +90,29 @@ export namespace LLM {
|
|||
modelID: input.model.id,
|
||||
providerID: input.model.providerID,
|
||||
})
|
||||
const authKey = input.model.authProfile
|
||||
? `${input.model.providerID}:${input.model.authProfile}`
|
||||
: input.model.providerID
|
||||
const [cfg, provider, auth] = await Promise.all([
|
||||
const [cfg, provider, auths] = await Promise.all([
|
||||
Config.get(),
|
||||
Provider.getProvider(input.model.providerID),
|
||||
Auth.get(authKey),
|
||||
Auth.all(),
|
||||
])
|
||||
const chooseProfile = () => {
|
||||
if (input.model.authProfile) return input.model.authProfile
|
||||
if (input.model.providerID in auths) return undefined
|
||||
if (`${input.model.providerID}:default` in auths) return "default"
|
||||
const prefix = `${input.model.providerID}:`
|
||||
const profiles = Object.keys(auths)
|
||||
.filter((key) => key.startsWith(prefix))
|
||||
.map((key) => key.slice(prefix.length))
|
||||
.sort()
|
||||
if (profiles.length === 0) return undefined
|
||||
return profiles[0]
|
||||
}
|
||||
const profile = chooseProfile()
|
||||
const authKey = profile ? `${input.model.providerID}:${profile}` : input.model.providerID
|
||||
const auth = auths[authKey]
|
||||
const runtimeModel = {
|
||||
...input.model,
|
||||
...(profile ? { authProfile: profile } : {}),
|
||||
options:
|
||||
auth?.type === "api"
|
||||
? mergeDeep(input.model.options, { apiKey: auth.key })
|
||||
|
|
|
|||
Loading…
Reference in New Issue