diff --git a/src/lib/store.ts b/src/lib/store.ts
index 42e62b8..4bbd3be 100644
--- a/src/lib/store.ts
+++ b/src/lib/store.ts
@@ -439,7 +439,7 @@ export const BUILTIN_PROMPTS: PromptPreset[] = [
builtin: true,
temperature: 0.3,
prompt:
- "Сделай краткое саммари разговора на русском: 3–6 предложений о сути, без воды. Не выдумывай детали, которых нет в тексте.",
+ "Сделай краткое саммари разговора на русском: несколько предложений о сути, без воды. Не выдумывай детали, которых нет в тексте.",
},
{
id: "summary-bullets",
@@ -457,7 +457,7 @@ export const BUILTIN_PROMPTS: PromptPreset[] = [
builtin: true,
temperature: 0.2,
prompt:
- "Из разговора выдели на русском три раздела: 1) Принятые решения; 2) Задачи и поручения (кто — что — срок, если есть); 3) Открытые вопросы. Если раздел пустой — пропусти его.",
+ "Из разговора выдели на русском три раздела: 1) Принятые решения; 2) Задачи и поручения (кто, что, срок, если есть); 3) Открытые вопросы. Если раздел пустой, пропусти его.",
},
];
diff --git a/src/windows/settings/SettingsApp.tsx b/src/windows/settings/SettingsApp.tsx
index 21f4e12..707888f 100644
--- a/src/windows/settings/SettingsApp.tsx
+++ b/src/windows/settings/SettingsApp.tsx
@@ -97,7 +97,7 @@ const TABS: { id: Tab; label: string; icon: LucideIcon; note: string }[] = [
icon: Cpu,
note: "Ключи и подключение модели",
},
- { id: "style", label: "Стиль и промпты", icon: Sparkles, note: "Стиль обработки и промпты для summary" },
+ { id: "style", label: "Стиль и Промпты", icon: Sparkles, note: "Стиль обработки и Промпты для summary" },
];
function TabButton({
diff --git a/src/windows/settings/tabs/SettingsTabs.tsx b/src/windows/settings/tabs/SettingsTabs.tsx
index 5e42970..043b253 100644
--- a/src/windows/settings/tabs/SettingsTabs.tsx
+++ b/src/windows/settings/tabs/SettingsTabs.tsx
@@ -9,7 +9,6 @@ import {
Check,
Cloud,
Code,
- Copy,
Crown,
Download,
Gauge,
@@ -21,9 +20,9 @@ import {
Plus,
Server,
Sparkles,
- Star,
Target,
Trash2,
+ Type,
User,
X,
Zap,
@@ -37,7 +36,6 @@ import {
listPromptsByKind,
upsertPrompt,
deletePrompt,
- type PromptPreset,
} from "../../../lib/store";
import { CloudProfile, fetchCloudProfile, getAuthLoginUrl, cloudLogout, handleAuthToken, generateExchangeCode, getAuthLoginUrlWithCode, pollForToken, getCachedCloudProfile, subscribeCloudProfile } from "../../../lib/cloudAuth";
import { logInfo } from "../../../lib/logger";
@@ -705,26 +703,21 @@ function PromptLibrary({
const summaryPrompts = listPromptsByKind(settings, "summary");
const defaultId = settings.defaultSummaryPromptId;
+ const selectedPreset = summaryPrompts.find((preset) => preset.id === defaultId);
+ const selectedIsCustom = selectedPreset ? !selectedPreset.builtin : false;
const startNew = () => {
setError(null);
setEditor({ name: "", prompt: "" });
};
- const startEdit = (preset: PromptPreset) => {
+ const startEditSelected = () => {
+ if (!selectedPreset) return;
setError(null);
setEditor({
- id: preset.id,
- name: preset.name,
- prompt: preset.prompt,
- temperature: preset.temperature,
- });
- };
- const startDuplicate = (preset: PromptPreset) => {
- setError(null);
- setEditor({
- name: `${preset.name} (копия)`,
- prompt: preset.prompt,
- temperature: preset.temperature,
+ id: selectedPreset.id,
+ name: selectedPreset.name,
+ prompt: selectedPreset.prompt,
+ temperature: selectedPreset.temperature,
});
};
@@ -741,9 +734,7 @@ function PromptLibrary({
temperature: editor.temperature,
});
await onReload();
- if (!editor.id && !defaultId) {
- update({ defaultSummaryPromptId: saved.id });
- }
+ update({ defaultSummaryPromptId: saved.id });
setEditor(null);
} catch (e) {
setError(e instanceof Error ? e.message : String(e));
@@ -752,11 +743,12 @@ function PromptLibrary({
}
};
- const handleDelete = async (preset: PromptPreset) => {
- setBusyId(preset.id);
+ const handleDeleteSelected = async () => {
+ if (!selectedPreset || selectedPreset.builtin) return;
+ setBusyId(selectedPreset.id);
setError(null);
try {
- await deletePrompt(preset.id);
+ await deletePrompt(selectedPreset.id);
await onReload();
} catch (e) {
setError(e instanceof Error ? e.message : String(e));
@@ -765,296 +757,181 @@ function PromptLibrary({
}
};
- return (
-
-
-
-
+
+
Название
+
setEditor({ ...editor, name: e.target.value })}
+ placeholder="Например: Протокол встречи"
+ maxLength={80}
+ style={PROMPT_FIELD_STYLE}
+ />
+
+
+ {error && (
+
+ {error}
+
+ )}
+
+
-
- Готовые и свои промпты для пересказа разговора. Промпт по умолчанию
- предлагается на экране результата.
-
+ Отмена
+
+
+
+ );
+ }
+
+ return (
+
+
+ Выберите промпт для summary. Он предлагается по умолчанию на экране
+ результата транскрибации.
+
+
+ {summaryPrompts.map((preset) => {
+ const active = preset.id === defaultId;
+
+ return (
+
}
+ title={preset.name}
+ description={preset.prompt}
+ onClick={() => update({ defaultSummaryPromptId: preset.id })}
+ />
+ );
+ })}
+
+ {error && (
+
+ {error}
+
+ )}
+
+
-
- {editor && (
-
-
-
Название
-
setEditor({ ...editor, name: e.target.value })}
- placeholder="Например: Протокол встречи"
- maxLength={80}
- style={PROMPT_FIELD_STYLE}
- />
-
-
- {error && (
-
- {error}
-
- )}
-
+ {selectedIsCustom && (
+ <>
-
-
- )}
-
- {error && !editor && (
-
- {error}
-
- )}
-
-
- {summaryPrompts.map((preset) => {
- const isDefault = preset.id === defaultId;
- const isBusy = busyId === preset.id;
-
- return (
-
-
-
-
- {preset.name}
-
- {preset.builtin && (
-
- Встроенный
-
- )}
- {isDefault && (
-
- По умолчанию
-
- )}
-
-
-
-
- {!preset.builtin && (
- <>
-
-
- >
- )}
-
-
-
- {preset.prompt}
-
-
- );
- })}
+ >
+ )}
);
}
-/**
- * Text (LLM) model used for summary / text processing in API mode: a custom
- * OpenAI-compatible endpoint, key and model. Empty endpoint = OpenAI with the
- * user's own key. Local mode uses the bundled runtime instead (Phase 3).
- */
function TextModelCard({
settings,
update,
@@ -1119,6 +996,7 @@ export function SettingsTabs({ type }: SettingsTabsProps) {
const [waitingForAuth, setWaitingForAuth] = useState(false);
const [waitingForSubscriptionRefresh, setWaitingForSubscriptionRefresh] = useState(false);
const [modelModeView, setModelModeView] = useState
(null);
+ const [styleTabView, setStyleTabView] = useState<"style" | "prompts">("style");
const [expandedApiAdapter, setExpandedApiAdapter] = useState(null);
const [expandedLocalModel, setExpandedLocalModel] = useState(null);
const [pendingDeleteModel, setPendingDeleteModel] = useState(null);
@@ -2919,41 +2797,87 @@ export function SettingsTabs({ type }: SettingsTabsProps) {
tech: Code,
};
+ const styleTabOptions: Array<{
+ id: "style" | "prompts";
+ label: string;
+ Icon: LucideIcon;
+ }> = [
+ { id: "style", label: "Стиль", Icon: Type },
+ { id: "prompts", label: "Промпты", Icon: MessageSquare },
+ ];
+
return (
-
Стиль обработки текста
-
Выберите режим обработки.
+
Обработка текста
+
+ Стиль очистки расшифровки и Промпты для summary.
+
-
- {TRANSCRIPTION_STYLE_OPTIONS.map((st) => {
- const isActive = settings.style === st.id;
- const Icon = STYLE_ICONS[st.id];
+
+ {styleTabOptions.map(({ id, label, Icon }) => {
+ const active = styleTabView === id;
return (
- }
- title={st.title}
- description={st.description}
- onClick={() =>
- update({
- style: st.id as AppSettings["style"],
- selectedCleanupPromptId: st.id,
- })
- }
- />
+
);
})}
-
+ {styleTabView === "style" && (
+
+ {TRANSCRIPTION_STYLE_OPTIONS.map((st) => {
+ const isActive = settings.style === st.id;
+ const Icon = STYLE_ICONS[st.id];
-
+ return (
+
}
+ title={st.title}
+ description={st.description}
+ onClick={() =>
+ update({
+ style: st.id as AppSettings["style"],
+ selectedCleanupPromptId: st.id,
+ })
+ }
+ />
+ );
+ })}
+
+ )}
- {IS_DEV && (
+ {styleTabView === "prompts" && (
+
+ )}
+
+ {IS_DEV && styleTabView === "style" && (