204 lines
5.9 KiB
TypeScript
204 lines
5.9 KiB
TypeScript
import type { SessionConfigOption } from "@agentclientprotocol/sdk"
|
|
|
|
export const DEFAULT_VARIANT_VALUE = "default"
|
|
|
|
export type ConfigOptionModel = {
|
|
id: string
|
|
name: string
|
|
variants?: Record<string, Record<string, unknown>>
|
|
}
|
|
|
|
export type ConfigOptionProvider = {
|
|
id: string
|
|
name: string
|
|
models: Record<string, ConfigOptionModel>
|
|
}
|
|
|
|
export type ConfigOptionMode = {
|
|
id: string
|
|
name: string
|
|
description?: string
|
|
}
|
|
|
|
export type ModelSelection = {
|
|
model: {
|
|
providerID: string
|
|
modelID: string
|
|
}
|
|
variant?: string
|
|
}
|
|
|
|
export function buildModelSelectOption(input: {
|
|
providers: readonly ConfigOptionProvider[]
|
|
currentModel: ModelSelection["model"]
|
|
currentVariant?: string
|
|
includeVariants?: boolean
|
|
}): SessionConfigOption {
|
|
return {
|
|
id: "model",
|
|
name: "Model",
|
|
category: "model",
|
|
type: "select",
|
|
currentValue: formatCurrentModelId({
|
|
model: input.currentModel,
|
|
variant: input.currentVariant,
|
|
variants: variantsForModel(input.providers, input.currentModel),
|
|
includeVariant: input.includeVariants ?? false,
|
|
}),
|
|
options: buildModelSelectOptions(input.providers, { includeVariants: input.includeVariants ?? false }),
|
|
}
|
|
}
|
|
|
|
export function buildEffortSelectOption(input: {
|
|
variants: readonly string[]
|
|
currentVariant?: string
|
|
}): SessionConfigOption | undefined {
|
|
if (input.variants.length === 0) return undefined
|
|
|
|
return {
|
|
id: "effort",
|
|
name: "Effort",
|
|
description: "Available effort levels for this model",
|
|
category: "thought_level",
|
|
type: "select",
|
|
currentValue: selectVariant(input.currentVariant, input.variants),
|
|
options: input.variants.map((variant) => ({
|
|
value: variant,
|
|
name: formatVariantName(variant),
|
|
})),
|
|
}
|
|
}
|
|
|
|
export function buildModeSelectOption(input: {
|
|
modes: readonly ConfigOptionMode[]
|
|
currentModeId: string
|
|
}): SessionConfigOption {
|
|
return {
|
|
id: "mode",
|
|
name: "Session Mode",
|
|
category: "mode",
|
|
type: "select",
|
|
currentValue: input.currentModeId,
|
|
options: input.modes.map((mode) => ({
|
|
value: mode.id,
|
|
name: mode.name,
|
|
...(mode.description ? { description: mode.description } : {}),
|
|
})),
|
|
}
|
|
}
|
|
|
|
export function buildConfigOptions(input: {
|
|
providers: readonly ConfigOptionProvider[]
|
|
currentModel: ModelSelection["model"]
|
|
currentVariant?: string
|
|
includeModelVariants?: boolean
|
|
modes?: readonly ConfigOptionMode[]
|
|
currentModeId?: string
|
|
}): SessionConfigOption[] {
|
|
const variants = variantsForModel(input.providers, input.currentModel)
|
|
const effort = buildEffortSelectOption({ variants, currentVariant: input.currentVariant })
|
|
|
|
return [
|
|
buildModelSelectOption({
|
|
providers: input.providers,
|
|
currentModel: input.currentModel,
|
|
currentVariant: input.currentVariant,
|
|
includeVariants: input.includeModelVariants ?? false,
|
|
}),
|
|
...(effort ? [effort] : []),
|
|
...(input.modes && input.currentModeId
|
|
? [buildModeSelectOption({ modes: input.modes, currentModeId: input.currentModeId })]
|
|
: []),
|
|
]
|
|
}
|
|
|
|
export function parseModelSelection(modelId: string, providers: readonly ConfigOptionProvider[]): ModelSelection {
|
|
const provider = providers.find((item) => modelId.startsWith(`${item.id}/`))
|
|
if (provider) {
|
|
const modelID = modelId.slice(provider.id.length + 1)
|
|
if (provider.models[modelID]) {
|
|
return { model: { providerID: provider.id, modelID } }
|
|
}
|
|
|
|
const separator = modelID.lastIndexOf("/")
|
|
if (separator > -1) {
|
|
const baseModelID = modelID.slice(0, separator)
|
|
const variant = modelID.slice(separator + 1)
|
|
if (provider.models[baseModelID]?.variants?.[variant]) {
|
|
return { model: { providerID: provider.id, modelID: baseModelID }, variant }
|
|
}
|
|
}
|
|
|
|
return { model: { providerID: provider.id, modelID } }
|
|
}
|
|
|
|
const separator = modelId.indexOf("/")
|
|
if (separator === -1) {
|
|
return { model: { providerID: modelId, modelID: "" } }
|
|
}
|
|
|
|
return {
|
|
model: {
|
|
providerID: modelId.slice(0, separator),
|
|
modelID: modelId.slice(separator + 1),
|
|
},
|
|
}
|
|
}
|
|
|
|
export function formatCurrentModelId(input: {
|
|
model: ModelSelection["model"]
|
|
variant?: string
|
|
variants?: readonly string[]
|
|
includeVariant?: boolean
|
|
}) {
|
|
const base = `${input.model.providerID}/${input.model.modelID}`
|
|
if (!input.includeVariant || !input.variants?.length) return base
|
|
return `${base}/${selectVariant(input.variant, input.variants)}`
|
|
}
|
|
|
|
export function formatVariantName(variant: string) {
|
|
return variant
|
|
.split(/[_-]/)
|
|
.map((part) => (part ? part.charAt(0).toUpperCase() + part.slice(1) : part))
|
|
.join(" ")
|
|
}
|
|
|
|
function buildModelSelectOptions(
|
|
providers: readonly ConfigOptionProvider[],
|
|
options: { includeVariants: boolean },
|
|
): Array<{ value: string; name: string }> {
|
|
return providers.flatMap((provider) =>
|
|
Object.values(provider.models)
|
|
.sort((a, b) => a.name.localeCompare(b.name))
|
|
.flatMap((model) => {
|
|
const base = {
|
|
value: `${provider.id}/${model.id}`,
|
|
name: `${provider.name}/${model.name}`,
|
|
}
|
|
if (!options.includeVariants || !model.variants) return [base]
|
|
|
|
return [
|
|
base,
|
|
...Object.keys(model.variants)
|
|
.filter((variant) => variant !== DEFAULT_VARIANT_VALUE)
|
|
.map((variant) => ({
|
|
value: `${provider.id}/${model.id}/${variant}`,
|
|
name: `${provider.name}/${model.name} (${formatVariantName(variant)})`,
|
|
})),
|
|
]
|
|
}),
|
|
)
|
|
}
|
|
|
|
function variantsForModel(providers: readonly ConfigOptionProvider[], model: ModelSelection["model"]) {
|
|
return Object.keys(
|
|
providers.find((provider) => provider.id === model.providerID)?.models[model.modelID]?.variants ?? {},
|
|
)
|
|
}
|
|
|
|
function selectVariant(variant: string | undefined, variants: readonly string[]) {
|
|
if (variant && variants.includes(variant)) return variant
|
|
if (variants.includes(DEFAULT_VARIANT_VALUE)) return DEFAULT_VARIANT_VALUE
|
|
return variants[0]
|
|
}
|