АДРЕСНЫЙ РЕЖИМ - локальная подель на декомпозе
This commit is contained in:
@@ -3,7 +3,10 @@ import type { ConnectionState } from "../state/types";
|
||||
|
||||
interface ConnectionPanelProps {
|
||||
value: ConnectionState;
|
||||
modelOptions: string[];
|
||||
modelsBusy: boolean;
|
||||
onChange: (next: ConnectionState) => void;
|
||||
onReloadModels: () => Promise<void> | void;
|
||||
onTestConnection: () => Promise<void> | void;
|
||||
onSaveLocalConfig: () => void;
|
||||
lastStatus: string;
|
||||
@@ -12,36 +15,94 @@ interface ConnectionPanelProps {
|
||||
|
||||
export function ConnectionPanel({
|
||||
value,
|
||||
modelOptions,
|
||||
modelsBusy,
|
||||
onChange,
|
||||
onReloadModels,
|
||||
onTestConnection,
|
||||
onSaveLocalConfig,
|
||||
lastStatus,
|
||||
busy
|
||||
}: ConnectionPanelProps) {
|
||||
const isLocal = value.llmProvider === "local";
|
||||
const modelInCatalog = modelOptions.includes(value.model);
|
||||
|
||||
return (
|
||||
<PanelFrame
|
||||
title="Подключение OpenAI"
|
||||
subtitle="Ключ живет только в памяти сессии (не пишется в localStorage)."
|
||||
actions={<span className="status-chip">{lastStatus || "Статус: не проверено"}</span>}
|
||||
title="LLM Connection"
|
||||
subtitle="Switch between OpenAI cloud and local OpenAI-compatible server."
|
||||
actions={<span className="status-chip">{lastStatus || "Status: not checked"}</span>}
|
||||
>
|
||||
<div className="grid-two">
|
||||
<label>
|
||||
OpenAI API Key
|
||||
Provider
|
||||
<select
|
||||
value={value.llmProvider}
|
||||
onChange={(event) => {
|
||||
const nextProvider = event.target.value === "local" ? "local" : "openai";
|
||||
onChange({
|
||||
...value,
|
||||
llmProvider: nextProvider,
|
||||
baseUrl: nextProvider === "local" ? "http://127.0.0.1:1234/v1" : "https://api.openai.com/v1"
|
||||
});
|
||||
}}
|
||||
>
|
||||
<option value="openai">OpenAI (token)</option>
|
||||
<option value="local">Local (LM Studio / OpenAI-compatible)</option>
|
||||
</select>
|
||||
</label>
|
||||
|
||||
<label>
|
||||
Model
|
||||
<select
|
||||
value={modelInCatalog ? value.model : "__manual__"}
|
||||
onChange={(event) => {
|
||||
const selected = event.target.value;
|
||||
if (selected === "__manual__") {
|
||||
return;
|
||||
}
|
||||
onChange({ ...value, model: selected });
|
||||
}}
|
||||
>
|
||||
<option value="__manual__">Manual input</option>
|
||||
{modelOptions.map((modelId) => (
|
||||
<option key={modelId} value={modelId}>
|
||||
{modelId}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</label>
|
||||
|
||||
<label>
|
||||
Model ID (manual)
|
||||
<input
|
||||
type="password"
|
||||
value={value.apiKey}
|
||||
onChange={(event) => onChange({ ...value, apiKey: event.target.value })}
|
||||
placeholder="sk-..."
|
||||
value={value.model}
|
||||
onChange={(event) => onChange({ ...value, model: event.target.value })}
|
||||
placeholder="qwen2.5-14b-instruct or lmstudio loaded model id"
|
||||
/>
|
||||
</label>
|
||||
<label>
|
||||
Model ID
|
||||
<input value={value.model} onChange={(event) => onChange({ ...value, model: event.target.value })} />
|
||||
</label>
|
||||
<label>
|
||||
Base URL
|
||||
<input value={value.baseUrl} onChange={(event) => onChange({ ...value, baseUrl: event.target.value })} />
|
||||
|
||||
{!isLocal ? (
|
||||
<label className="full-width">
|
||||
OpenAI API Key
|
||||
<input
|
||||
type="password"
|
||||
value={value.apiKey}
|
||||
onChange={(event) => onChange({ ...value, apiKey: event.target.value })}
|
||||
placeholder="sk-..."
|
||||
/>
|
||||
</label>
|
||||
) : null}
|
||||
|
||||
<label className={isLocal ? "full-width" : undefined}>
|
||||
{isLocal ? "Local server base URL" : "Base URL"}
|
||||
<input
|
||||
value={value.baseUrl}
|
||||
onChange={(event) => onChange({ ...value, baseUrl: event.target.value })}
|
||||
placeholder={isLocal ? "http://127.0.0.1:1234/v1" : "https://api.openai.com/v1"}
|
||||
/>
|
||||
</label>
|
||||
|
||||
<label>
|
||||
Temperature
|
||||
<input
|
||||
@@ -51,6 +112,7 @@ export function ConnectionPanel({
|
||||
onChange={(event) => onChange({ ...value, temperature: Number(event.target.value) })}
|
||||
/>
|
||||
</label>
|
||||
|
||||
<label>
|
||||
Max output tokens
|
||||
<input
|
||||
@@ -60,12 +122,16 @@ export function ConnectionPanel({
|
||||
/>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div className="button-row">
|
||||
<button type="button" onClick={() => onSaveLocalConfig()}>
|
||||
Сохранить локальную конфигурацию
|
||||
Save local config
|
||||
</button>
|
||||
<button type="button" onClick={() => onReloadModels()} disabled={busy || modelsBusy}>
|
||||
{modelsBusy ? "Loading models..." : "Load model list"}
|
||||
</button>
|
||||
<button type="button" onClick={() => onTestConnection()} disabled={busy}>
|
||||
{busy ? "Проверяем..." : "Проверить подключение"}
|
||||
{busy ? "Checking..." : "Test connection"}
|
||||
</button>
|
||||
</div>
|
||||
</PanelFrame>
|
||||
|
||||
Reference in New Issue
Block a user