fix(studio): clarify additional persona instructions

Problem: "After the first-party guidance" exposes prompt-construction jargon
without explaining what users should enter.

Root cause: Both persona editors use a position-based label; the composition
editor has no suffix helper text.

Fix: Label both suffix inputs "Additional instructions" and explain that the
text follows the built-in system instructions and may be left blank. Add the
Chinese/English copy and associate the helper with each textarea. Keep the
existing literal suffix binding and update affected interaction expectations.

Verification: 24 focused persona, preset and localization tests; production
build/typecheck; formatting, vet, lint, changed-file checks and builtin/boot
suites.
This commit is contained in:
SivanCola committed 2026-10-19 23:59:15 +08:00
1 parent 5ea0ed7046
commit 9023835220
5 files changed
+14 -11

No files matched your search

+2 -2
View File
@@ -19,8 +19,8 @@ export const EN_PERSONA: Record<string, string> = {
"已修改预设内容,按下面的字段保存。": "The preset text has been edited; save the fields below.",
"系统提示词开头": "Start of the system prompt",
"作为系统提示词的第一段,写在内置指令之前;留空表示不添加。": "Leads the system prompt, ahead of the built-in guidance; leave it empty to add nothing.",
"第一方指令之后": "After the first-party guidance",
"紧跟在内置指令之后、运行时上下文之前;留空表示不添加。": "Follows the built-in guidance and precedes the runtime context; leave it empty to add nothing.",
"补充要求": "Additional instructions",
"放在内置系统指令之后,留空则不添加": "Placed after the built-in system instructions. Leave blank to add nothing.",
"不注入可选运行时上下文": "Do not inject optional runtime context",
"关闭后不注入探测到的运行环境与离线提示;指令、记忆与技能照常写入。": "When on, the probed environment and the offline note are not injected; instructions, memory and skills are written as usual.",
"写入用户配置,在新会话及现有会话下一次重建时生效;保存本身不会重建会话。": "Writes the user config; applies to new sessions and the next rebuild of an existing session. Saving itself does not rebuild it.",
@@ -102,7 +102,7 @@ describe("Agent preset management", () => {
await user.type(screen.getByLabelText("预设名称"), "My agent");
await user.type(screen.getByLabelText("人设与要求"), "Literal prefix");
await user.click(screen.getByText("高级设置", { selector: "summary" }));
await user.type(screen.getByLabelText("第一方指令之后"), "Literal suffix");
await user.type(screen.getByLabelText("补充要求"), "Literal suffix");
expect(screen.queryByRole("switch", { name: /complete/ })).toBeNull();
await user.click(screen.getByRole("switch", { name: "注入运行环境与离线提示" }));
await user.click(screen.getByRole("button", { name: "保存预设" }));
@@ -114,9 +114,10 @@ export function CompositionEditor({
<span className="ds" id={`${helpId}-id`}>{t("自动生成,用于保存和引用预设;保存后不可修改。")}</span>
</label>
<label className="pers-field">
<span className="lb">{t("第一方指令之后")}</span>
<span className="lb">{t("补充要求")}</span>
<textarea
aria-label={t("第一方指令之后")}
aria-label={t("补充要求")}
aria-describedby={`${helpId}-suffix`}
data-action-change="persona.suffix"
rows={3}
maxLength={32768}
@@ -124,6 +125,7 @@ export function CompositionEditor({
value={persona.suffix}
onChange={(e) => updatePersona({ suffix: e.target.value })}
/>
<span className="ds" id={`${helpId}-suffix`}>{t("放在内置系统指令之后,留空则不添加")}</span>
</label>
<div className="lrow">
<span className="tx">
@@ -37,13 +37,13 @@ describe("the system persona page", () => {
await userEvent.click(screen.getByRole("button", { name: "严谨工程师" }));
expect((await field("系统提示词开头")).value).toBe("Rigorous engineer prefix.");
expect((await field("第一方指令之后")).value).toBe("");
expect((await field("补充要求")).value).toBe("");
expect(screen.queryByRole("switch", { name: /complete/ })).toBeNull();
expect(now(container)).toBe("严谨工程师");
await userEvent.click(screen.getByRole("button", { name: "简洁" }));
expect((await field("系统提示词开头")).value).toBe("");
expect((await field("第一方指令之后")).value).toBe("Be terse.");
expect((await field("补充要求")).value).toBe("Be terse.");
// The runtime-context switch shows the inverse of the field it writes.
expect(screen.getByRole("switch", { name: "不注入可选运行时上下文" }).getAttribute("aria-checked")).toBe("true");
});
@@ -63,7 +63,7 @@ describe("the system persona page", () => {
expect(saveButton().disabled).toBe(true);
await userEvent.type(prefix, "Lead with evidence.");
await userEvent.type(await field("第一方指令之后"), "Stay terse.");
await userEvent.type(await field("补充要求"), "Stay terse.");
await userEvent.click(screen.getByRole("switch", { name: "不注入可选运行时上下文" }));
expect(saveButton().disabled).toBe(false);
+4 -3
View File
@@ -156,15 +156,16 @@ export function Persona({ port, onDirtyChange, onBusyChange, onSaved }: { port:
</div>
<div className="pers-field">
<label className="lb" htmlFor={suffixId}>{t("第一方指令之后")}</label>
<span className="ds">{t("紧跟在内置指令之后、运行时上下文之前;留空表示不添加。")}</span>
<label className="lb" htmlFor={suffixId}>{t("补充要求")}</label>
<span className="ds" id={`${suffixId}-help`}>{t("放在内置系统指令之后,留空则不添加")}</span>
<textarea
id={suffixId}
dir="auto"
rows={5}
maxLength={LIMIT}
spellCheck={false}
aria-label={t("第一方指令之后")}
aria-label={t("补充要求")}
aria-describedby={`${suffixId}-help`}
data-action-change="persona.suffix"
value={draft.suffix}
disabled={busy}