feat: add configurable chat display modes
This commit is contained in:
1 parent
3715af3138
commit
40542db400
18 files changed
+421
-121
No files matched your search
@@ -39,8 +39,14 @@ import {
|
||||
useLocalSettings,
|
||||
useThreadSettings,
|
||||
} from "@/core/settings";
|
||||
import { usePluginManagementSettings } from "@/core/system-settings/hooks";
|
||||
import { stopActiveThreadBeforeClarificationReply, useThreadStream } from "@/core/threads/hooks";
|
||||
import {
|
||||
useCitationDisplaySettings,
|
||||
usePluginManagementSettings,
|
||||
} from "@/core/system-settings/hooks";
|
||||
import {
|
||||
stopActiveThreadBeforeClarificationReply,
|
||||
useThreadStream,
|
||||
} from "@/core/threads/hooks";
|
||||
import { textOfMessage } from "@/core/threads/utils";
|
||||
import { env } from "@/env";
|
||||
import { cn } from "@/lib/utils";
|
||||
@@ -383,6 +389,9 @@ export default function IframeChatPage() {
|
||||
}, [forceDefaultAssistant, pendingIframeSubmit, selectedAgentId]);
|
||||
|
||||
const ragModeLocked = isThreadRagModeLocked(threadId);
|
||||
const { data: citationDisplay } = useCitationDisplaySettings();
|
||||
const referenceModeEntryEnabled =
|
||||
citationDisplay?.reference_mode_enabled ?? false;
|
||||
const ragModeEnabled =
|
||||
localSettings.display.ragModeEnabled || ragModeLocked;
|
||||
const contextCompressionEnabled =
|
||||
@@ -529,6 +538,7 @@ export default function IframeChatPage() {
|
||||
memoryInjectionEnabled: Boolean(
|
||||
settings.context.memory_injection_enabled ?? true,
|
||||
),
|
||||
referenceModeEntryEnabled,
|
||||
ragModeEnabled,
|
||||
ragModeLocked,
|
||||
contextCompressionEnabled,
|
||||
|
||||
@@ -46,6 +46,8 @@ export default function PromptPrefixSettingsPage({
|
||||
const [enabled, setEnabled] = useState(false);
|
||||
const [switchLabel, setSwitchLabel] = useState("");
|
||||
const [promptPrefix, setPromptPrefix] = useState("");
|
||||
const [ordinaryQaMarkdownFormatEnabled, setOrdinaryQaMarkdownFormatEnabled] =
|
||||
useState(false);
|
||||
// Only seed the draft from server data once. Re-syncing every time react-query
|
||||
// refetches (window focus, route remount, etc.) would silently overwrite the
|
||||
// user's in-progress edits — and made the toggle look unresponsive: a click
|
||||
@@ -57,6 +59,9 @@ export default function PromptPrefixSettingsPage({
|
||||
setEnabled(data.enabled);
|
||||
setSwitchLabel(data.switch_label);
|
||||
setPromptPrefix(data.prompt_prefix);
|
||||
setOrdinaryQaMarkdownFormatEnabled(
|
||||
data.ordinary_qa_markdown_format_enabled === true,
|
||||
);
|
||||
initializedRef.current = true;
|
||||
}, [data]);
|
||||
|
||||
@@ -79,6 +84,8 @@ export default function PromptPrefixSettingsPage({
|
||||
enabled,
|
||||
switch_label: switchLabel,
|
||||
prompt_prefix: promptPrefix,
|
||||
ordinary_qa_markdown_format_enabled:
|
||||
ordinaryQaMarkdownFormatEnabled,
|
||||
});
|
||||
toast.success("已保存",darkToastOpts.success);
|
||||
} catch (e) {
|
||||
@@ -95,10 +102,9 @@ export default function PromptPrefixSettingsPage({
|
||||
}
|
||||
>
|
||||
<div>
|
||||
<h1 className={embedded ? "text-base font-semibold" : "text-xl font-semibold"}>问答前缀配置</h1>
|
||||
<h1 className={embedded ? "text-base font-semibold" : "text-xl font-semibold"}>问答提示词配置</h1>
|
||||
<p className="text-muted-foreground mt-1 text-sm">
|
||||
管理员可在此配置问答页输入框中的「前缀开关」。开启后,用户在新会话中第一次提问时,
|
||||
会将下方配置的前缀文本和原问题拼接后再发送给模型。
|
||||
管理员可在此配置问答前缀和普通问答的固定 Markdown 格式提示词。
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@@ -147,6 +153,21 @@ export default function PromptPrefixSettingsPage({
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="flex items-start justify-between gap-4 rounded-lg border p-4">
|
||||
<div>
|
||||
<div className="text-sm font-medium">固定格式提示词</div>
|
||||
<p className="text-muted-foreground mt-1 max-w-md text-xs leading-relaxed">
|
||||
开启后,普通问答的长篇内容会按“# 主标题、## 一、标题、###
|
||||
(一) 标题、#### 1. 标题”的固定 Markdown 格式生成。默认关闭。
|
||||
</p>
|
||||
</div>
|
||||
<Switch
|
||||
checked={ordinaryQaMarkdownFormatEnabled}
|
||||
onCheckedChange={setOrdinaryQaMarkdownFormatEnabled}
|
||||
aria-label="固定格式提示词"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="flex justify-end">
|
||||
<Button onClick={handleSave} disabled={update.isPending}>
|
||||
{update.isPending && (
|
||||
|
||||
@@ -9,6 +9,7 @@ test("includes the context compression toggle in the iframe chat toolbar", () =>
|
||||
agentSelected: false,
|
||||
writingModeEnabled: false,
|
||||
memoryInjectionEnabled: true,
|
||||
referenceModeEntryEnabled: true,
|
||||
ragModeEnabled: false,
|
||||
ragModeLocked: false,
|
||||
contextCompressionEnabled: false,
|
||||
@@ -28,11 +29,27 @@ test("includes the context compression toggle in the iframe chat toolbar", () =>
|
||||
);
|
||||
});
|
||||
|
||||
test("hides the references toggle when reference mode is disabled globally", () => {
|
||||
const buttons = buildIframeModeButtons({
|
||||
agentSelected: false,
|
||||
writingModeEnabled: false,
|
||||
memoryInjectionEnabled: true,
|
||||
referenceModeEntryEnabled: false,
|
||||
ragModeEnabled: true,
|
||||
ragModeLocked: false,
|
||||
contextCompressionEnabled: false,
|
||||
proModeEnabled: false,
|
||||
});
|
||||
|
||||
assert.equal(buttons.some((button) => button.key === "references"), false);
|
||||
});
|
||||
|
||||
test("returns only concrete toolbar button configs", () => {
|
||||
const buttons = buildIframeModeButtons({
|
||||
agentSelected: true,
|
||||
writingModeEnabled: false,
|
||||
memoryInjectionEnabled: true,
|
||||
referenceModeEntryEnabled: true,
|
||||
ragModeEnabled: false,
|
||||
ragModeLocked: false,
|
||||
contextCompressionEnabled: false,
|
||||
|
||||
@@ -15,6 +15,7 @@ type BuildIframeModeButtonsInput = {
|
||||
agentSelected: boolean;
|
||||
writingModeEnabled: boolean;
|
||||
memoryInjectionEnabled: boolean;
|
||||
referenceModeEntryEnabled: boolean;
|
||||
ragModeEnabled: boolean;
|
||||
ragModeLocked: boolean;
|
||||
contextCompressionEnabled: boolean;
|
||||
@@ -25,12 +26,13 @@ export function buildIframeModeButtons({
|
||||
agentSelected,
|
||||
writingModeEnabled,
|
||||
memoryInjectionEnabled,
|
||||
referenceModeEntryEnabled,
|
||||
ragModeEnabled,
|
||||
ragModeLocked,
|
||||
contextCompressionEnabled,
|
||||
proModeEnabled,
|
||||
}: BuildIframeModeButtonsInput): IframeModeButtonState[] {
|
||||
return [
|
||||
const buttons: IframeModeButtonState[] = [
|
||||
{
|
||||
key: "writing",
|
||||
label: "写作",
|
||||
@@ -63,4 +65,7 @@ export function buildIframeModeButtons({
|
||||
active: agentSelected,
|
||||
},
|
||||
];
|
||||
return referenceModeEntryEnabled
|
||||
? buttons
|
||||
: buttons.filter((button) => button.key !== "references");
|
||||
}
|
||||
Reference in new issue
Block a user