АДРЕСНЫЙ РЕЖИМ - авторан история - юи + адресный рендер прогонов в реалтайме

This commit is contained in:
2026-04-09 23:48:32 +03:00
parent cf5ba1afc2
commit fd6764d412
38 changed files with 6179 additions and 777 deletions
File diff suppressed because it is too large Load Diff
@@ -1,3 +1,4 @@
import { useEffect, useState } from "react";
import { PanelFrame } from "./PanelFrame";
import type { ConnectionState } from "../state/types";
@@ -26,6 +27,46 @@ export function ConnectionPanel({
}: ConnectionPanelProps) {
const isLocal = value.llmProvider === "local";
const modelInCatalog = modelOptions.includes(value.model);
const [temperatureInput, setTemperatureInput] = useState(String(value.temperature));
const [maxOutputTokensInput, setMaxOutputTokensInput] = useState(String(value.maxOutputTokens));
useEffect(() => {
setTemperatureInput(String(value.temperature));
}, [value.temperature]);
useEffect(() => {
setMaxOutputTokensInput(String(value.maxOutputTokens));
}, [value.maxOutputTokens]);
const commitTemperatureInput = (raw: string) => {
const normalized = raw.replace(",", ".").trim();
if (!normalized) {
setTemperatureInput(String(value.temperature));
return;
}
const parsed = Number(normalized);
if (!Number.isFinite(parsed)) {
setTemperatureInput(String(value.temperature));
return;
}
onChange({ ...value, temperature: parsed });
setTemperatureInput(String(parsed));
};
const commitMaxOutputTokensInput = (raw: string) => {
const normalized = raw.trim();
if (!normalized) {
setMaxOutputTokensInput(String(value.maxOutputTokens));
return;
}
const parsed = Number.parseInt(normalized, 10);
if (!Number.isFinite(parsed) || parsed <= 0) {
setMaxOutputTokensInput(String(value.maxOutputTokens));
return;
}
onChange({ ...value, maxOutputTokens: parsed });
setMaxOutputTokensInput(String(parsed));
};
return (
<PanelFrame
@@ -108,8 +149,14 @@ export function ConnectionPanel({
<input
type="number"
step="0.1"
value={value.temperature}
onChange={(event) => onChange({ ...value, temperature: Number(event.target.value) })}
value={temperatureInput}
onChange={(event) => setTemperatureInput(event.target.value)}
onBlur={(event) => commitTemperatureInput(event.target.value)}
onKeyDown={(event) => {
if (event.key === "Enter") {
commitTemperatureInput((event.target as HTMLInputElement).value);
}
}}
/>
</label>
@@ -117,8 +164,14 @@ export function ConnectionPanel({
Max output tokens
<input
type="number"
value={value.maxOutputTokens}
onChange={(event) => onChange({ ...value, maxOutputTokens: Number(event.target.value) })}
value={maxOutputTokensInput}
onChange={(event) => setMaxOutputTokensInput(event.target.value)}
onBlur={(event) => commitMaxOutputTokensInput(event.target.value)}
onKeyDown={(event) => {
if (event.key === "Enter") {
commitMaxOutputTokensInput((event.target as HTMLInputElement).value);
}
}}
/>
</label>
</div>