mirror of
https://github.com/vas3k/TaxHacker.git
synced 2026-07-03 10:52:28 +08:00
fix: show LLM choice only in self-hosted mode
This commit is contained in:
@@ -6,36 +6,25 @@ import { FormError } from "@/components/forms/error"
|
||||
import { FormTextarea } from "@/components/forms/simple"
|
||||
import { Button } from "@/components/ui/button"
|
||||
import { Card, CardTitle } from "@/components/ui/card"
|
||||
import config from "@/lib/config"
|
||||
import { PROVIDERS } from "@/lib/llm-providers"
|
||||
import { Field } from "@/prisma/client"
|
||||
import type { DragEndEvent } from "@dnd-kit/core"
|
||||
import { closestCenter, DndContext, PointerSensor, useSensor, useSensors } from "@dnd-kit/core"
|
||||
import { arrayMove, SortableContext, useSortable, verticalListSortingStrategy } from "@dnd-kit/sortable"
|
||||
import { CircleCheckBig, Edit, GripVertical } from "lucide-react"
|
||||
import Link from "next/link"
|
||||
import { useState, useActionState } from "react"
|
||||
import {
|
||||
DndContext,
|
||||
closestCenter,
|
||||
PointerSensor,
|
||||
useSensor,
|
||||
useSensors
|
||||
} from "@dnd-kit/core"
|
||||
import type { DragEndEvent } from "@dnd-kit/core";
|
||||
import {
|
||||
arrayMove,
|
||||
SortableContext,
|
||||
useSortable,
|
||||
verticalListSortingStrategy
|
||||
} from "@dnd-kit/sortable"
|
||||
import { PROVIDERS } from "@/lib/llm-providers";
|
||||
|
||||
import { useActionState, useState } from "react"
|
||||
|
||||
function getInitialProviderOrder(settings: Record<string, string>) {
|
||||
let order: string[] = []
|
||||
if (!settings.llm_providers) {
|
||||
order = ['openai', 'google', 'mistral', 'openai_compatible']
|
||||
order = ["openai", "google", "mistral", "openai_compatible"]
|
||||
} else {
|
||||
order = settings.llm_providers.split(",").map(p => p.trim())
|
||||
order = settings.llm_providers.split(",").map((p) => p.trim())
|
||||
}
|
||||
// Remove duplicates and keep only valid providers
|
||||
return order.filter((key, idx) => PROVIDERS.some(p => p.key === key) && order.indexOf(key) === idx)
|
||||
return order.filter((key, idx) => PROVIDERS.some((p) => p.key === key) && order.indexOf(key) === idx)
|
||||
}
|
||||
|
||||
export default function LLMSettingsForm({
|
||||
@@ -56,9 +45,7 @@ export default function LLMSettingsForm({
|
||||
values[provider.key] = {
|
||||
apiKey: settings[provider.apiKeyName],
|
||||
model: settings[provider.modelName] || provider.defaultModelName,
|
||||
baseUrl: provider.baseUrlName
|
||||
? (settings[provider.baseUrlName] || provider.defaultBaseUrl || "")
|
||||
: "",
|
||||
baseUrl: provider.baseUrlName ? settings[provider.baseUrlName] || provider.defaultBaseUrl || "" : "",
|
||||
}
|
||||
})
|
||||
return values
|
||||
@@ -77,20 +64,20 @@ export default function LLMSettingsForm({
|
||||
return (
|
||||
<>
|
||||
<form action={saveAction} className="space-y-4">
|
||||
{config.selfHosted.isEnabled && (
|
||||
<div className="space-y-2">
|
||||
<label className="text-sm font-medium">LLM providers</label>
|
||||
<DndProviderBlocks
|
||||
providerOrder={providerOrder}
|
||||
setProviderOrder={setProviderOrder}
|
||||
providerValues={providerValues}
|
||||
handleProviderValueChange={handleProviderValueChange}
|
||||
/>
|
||||
<small className="text-muted-foreground">Drag provider blocks to reorder. First is highest priority.</small>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="space-y-2">
|
||||
<label className="text-sm font-medium">LLM providers</label>
|
||||
<DndProviderBlocks
|
||||
providerOrder={providerOrder}
|
||||
setProviderOrder={setProviderOrder}
|
||||
providerValues={providerValues}
|
||||
handleProviderValueChange={handleProviderValueChange}
|
||||
/>
|
||||
<small className="text-muted-foreground">
|
||||
Drag provider blocks to reorder. First is highest priority.
|
||||
</small>
|
||||
</div>
|
||||
<input type="hidden" name="llm_providers" value={providerOrder.join(",")} />
|
||||
{config.selfHosted.isEnabled && <input type="hidden" name="llm_providers" value={providerOrder.join(",")} />}
|
||||
|
||||
<FormTextarea
|
||||
title="Prompt for File Analysis Form"
|
||||
@@ -142,13 +129,18 @@ export default function LLMSettingsForm({
|
||||
}
|
||||
|
||||
type DndProviderBlocksProps = {
|
||||
providerOrder: string[];
|
||||
setProviderOrder: React.Dispatch<React.SetStateAction<string[]>>;
|
||||
providerValues: Record<string, { apiKey: string; model: string; baseUrl: string }>;
|
||||
handleProviderValueChange: (providerKey: string, field: "apiKey" | "model" | "baseUrl", value: string) => void;
|
||||
};
|
||||
providerOrder: string[]
|
||||
setProviderOrder: React.Dispatch<React.SetStateAction<string[]>>
|
||||
providerValues: Record<string, { apiKey: string; model: string; baseUrl: string }>
|
||||
handleProviderValueChange: (providerKey: string, field: "apiKey" | "model" | "baseUrl", value: string) => void
|
||||
}
|
||||
|
||||
function DndProviderBlocks({ providerOrder, setProviderOrder, providerValues, handleProviderValueChange }: DndProviderBlocksProps) {
|
||||
function DndProviderBlocks({
|
||||
providerOrder,
|
||||
setProviderOrder,
|
||||
providerValues,
|
||||
handleProviderValueChange,
|
||||
}: DndProviderBlocksProps) {
|
||||
const sensors = useSensors(useSensor(PointerSensor))
|
||||
function handleDragEnd(event: DragEndEvent) {
|
||||
const { active, over } = event
|
||||
@@ -176,17 +168,17 @@ function DndProviderBlocks({ providerOrder, setProviderOrder, providerValues, ha
|
||||
}
|
||||
|
||||
type SortableProviderBlockProps = {
|
||||
id: string;
|
||||
idx: number;
|
||||
providerKey: string;
|
||||
value: { apiKey: string; model: string; baseUrl: string };
|
||||
handleValueChange: (providerKey: string, field: "apiKey" | "model" | "baseUrl", value: string) => void;
|
||||
};
|
||||
id: string
|
||||
idx: number
|
||||
providerKey: string
|
||||
value: { apiKey: string; model: string; baseUrl: string }
|
||||
handleValueChange: (providerKey: string, field: "apiKey" | "model" | "baseUrl", value: string) => void
|
||||
}
|
||||
|
||||
function SortableProviderBlock({ id, idx, providerKey, value, handleValueChange }: SortableProviderBlockProps) {
|
||||
const { attributes, listeners, setNodeRef, transform, transition, isDragging } = useSortable({ id })
|
||||
|
||||
const provider = PROVIDERS.find(p => p.key === providerKey)
|
||||
const provider = PROVIDERS.find((p) => p.key === providerKey)
|
||||
if (!provider) return null
|
||||
return (
|
||||
<div
|
||||
@@ -215,7 +207,7 @@ function SortableProviderBlock({ id, idx, providerKey, value, handleValueChange
|
||||
type="text"
|
||||
name={provider.apiKeyName}
|
||||
value={value.apiKey}
|
||||
onChange={e => handleValueChange(provider.key, "apiKey", e.target.value)}
|
||||
onChange={(e) => handleValueChange(provider.key, "apiKey", e.target.value)}
|
||||
className="flex-1 border rounded px-2 py-1"
|
||||
placeholder={provider.baseUrlName ? "API key (optional)" : "API key"}
|
||||
/>
|
||||
@@ -223,7 +215,7 @@ function SortableProviderBlock({ id, idx, providerKey, value, handleValueChange
|
||||
type="text"
|
||||
name={provider.modelName}
|
||||
value={value.model}
|
||||
onChange={e => handleValueChange(provider.key, "model", e.target.value)}
|
||||
onChange={(e) => handleValueChange(provider.key, "model", e.target.value)}
|
||||
className="flex-1 border rounded px-2 py-1"
|
||||
placeholder="Model name"
|
||||
/>
|
||||
@@ -233,7 +225,7 @@ function SortableProviderBlock({ id, idx, providerKey, value, handleValueChange
|
||||
type="text"
|
||||
name={provider.baseUrlName}
|
||||
value={value.baseUrl}
|
||||
onChange={e => handleValueChange(provider.key, "baseUrl", e.target.value)}
|
||||
onChange={(e) => handleValueChange(provider.key, "baseUrl", e.target.value)}
|
||||
className="w-full border rounded px-2 py-1"
|
||||
placeholder="Base URL (e.g. http://localhost:11434/v1)"
|
||||
/>
|
||||
@@ -241,11 +233,7 @@ function SortableProviderBlock({ id, idx, providerKey, value, handleValueChange
|
||||
{provider.apiDoc && (
|
||||
<small className="text-muted-foreground">
|
||||
Get your API key from{" "}
|
||||
<a
|
||||
href={provider.apiDoc}
|
||||
target="_blank"
|
||||
className="underline"
|
||||
>
|
||||
<a href={provider.apiDoc} target="_blank" className="underline">
|
||||
{provider.apiDocLabel}
|
||||
</a>
|
||||
</small>
|
||||
|
||||
Reference in New Issue
Block a user