From bb4394013521cda368cb9d295990746ca827a9ae Mon Sep 17 00:00:00 2001 From: tianma-if Date: Sun, 13 Sep 2026 22:11:35 +0800 Subject: [PATCH] feat(ai): replace social starter prompts with note workflows Keep six factory prompts, swap Xiaohongshu and Twitter presets for extract-todos and continue-writing, and use four-character Chinese names. --- apps/api/src/ai-prompt-routes.test.mjs | 85 +++++++++++++++++-- apps/api/src/ai-service.ts | 6 +- apps/api/src/demo-seed-data.ts | 4 +- .../Features/Workspace/AiAssistantSheet.swift | 10 +-- .../src/components/LocalTiptapEditor.tsx | 10 +-- .../src/components/MobileAiAssistantModal.tsx | 10 +-- docs/demo-sample-note.md | 2 +- docs/demo-sample-note.zh-CN.md | 2 +- migrations/0047_replace_social_ai_prompts.sql | 33 +++++++ packages/shared/src/ai-assistant.ts | 8 +- packages/shared/src/ai-prompt-seeds.ts | 34 ++++---- packages/shared/src/i18n/en-US.ts | 6 +- packages/shared/src/i18n/zh-CN.ts | 12 +-- tests/e2e/ai-custom-prompts.spec.ts | 10 +-- 14 files changed, 167 insertions(+), 65 deletions(-) create mode 100644 migrations/0047_replace_social_ai_prompts.sql diff --git a/apps/api/src/ai-prompt-routes.test.mjs b/apps/api/src/ai-prompt-routes.test.mjs index e6fcc101..be3100db 100644 --- a/apps/api/src/ai-prompt-routes.test.mjs +++ b/apps/api/src/ai-prompt-routes.test.mjs @@ -120,12 +120,12 @@ const createApp = ({ currentAuth = auth, demoMode = false } = {}) => { describe("AI prompt template routes", () => { test("keeps the starter catalog focused on six common workflows", () => { expect(DEFAULT_AI_PROMPT_SEEDS.map((prompt) => [prompt.key, prompt.name])).toEqual([ - ["summarize", "总结"], - ["translate", "翻译"], - ["improve-writing", "润色"], + ["summarize", "精简总结"], + ["translate", "全文翻译"], + ["improve-writing", "润色表达"], ["make-shorter", "精炼表达"], - ["rewrite-proofread", "转为小红书风格"], - ["simplify-language", "转为推特风格"], + ["extract-todos", "提取待办"], + ["continue-writing", "继续写作"], ]); }); @@ -158,10 +158,79 @@ describe("AI prompt template routes", () => { ORDER BY name`, ).all("ws_migration"); expect(rows).toHaveLength(6); + expect(rows.filter((row) => row.seed_key !== null).map((row) => row.seed_key).sort()).toEqual([ + "improve-writing", + "make-shorter", + "rewrite-proofread", + "simplify-language", + "summarize", + "translate", + ]); + expect(rows.find((row) => row.instruction === "Keep my specialized proofreading prompt.")).toBeUndefined(); + }); + + test("replaces social-style starters with extract-todos and continue-writing", () => { + const sqlite = new Database(":memory:"); + const migrations = globSync("migrations/*.sql").sort(); + for (const migration of migrations.filter((path) => path < "migrations/0027")) { + sqlite.exec(readFileSync(migration, "utf8")); + } + sqlite.query("INSERT INTO workspaces (id, name, is_personal) VALUES (?, ?, 1)") + .run("ws_migration", "Migration workspace"); + for (const migration of migrations.filter( + (path) => path >= "migrations/0027" && path < "migrations/0047", + )) { + sqlite.exec(readFileSync(migration, "utf8")); + } + + sqlite.query( + `UPDATE ai_prompt_templates + SET instruction = ?, instruction_customized = 1 + WHERE workspace_id = ? AND seed_key = ?`, + ).run("Keep my Xiaohongshu voice.", "ws_migration", "rewrite-proofread"); + sqlite.query( + `INSERT INTO ai_prompt_templates ( + id, workspace_id, seed_key, action, parameter_kind, result_mode, + name, description, instruction, + name_customized, description_customized, instruction_customized, + created_at, updated_at + ) VALUES (?, ?, NULL, 'custom', 'none', 'both', ?, NULL, ?, 1, 1, 1, ?, ?)`, + ).run( + "aiprompt_user_custom", + "ws_migration", + "周报提炼", + "提炼本周进展与风险。", + "2026-08-12T01:00:00.000Z", + "2026-08-12T01:00:00.000Z", + ); + + sqlite.exec(readFileSync("migrations/0047_replace_social_ai_prompts.sql", "utf8")); + + const rows = sqlite.query( + `SELECT seed_key, action, name, instruction + FROM ai_prompt_templates + WHERE workspace_id = ? + ORDER BY name`, + ).all("ws_migration"); expect(rows.filter((row) => row.seed_key !== null).map((row) => row.seed_key).sort()).toEqual( DEFAULT_AI_PROMPT_SEEDS.map((prompt) => prompt.key).sort(), ); - expect(rows.find((row) => row.instruction === "Keep my specialized proofreading prompt.")).toBeUndefined(); + expect(rows.find((row) => row.instruction === "Keep my Xiaohongshu voice.")).toBeUndefined(); + expect(rows.find((row) => row.seed_key === "rewrite-proofread")).toBeUndefined(); + expect(rows.find((row) => row.seed_key === "simplify-language")).toBeUndefined(); + expect(rows.find((row) => row.seed_key === "extract-todos")).toMatchObject({ + action: "extract-todos", + name: "提取待办", + }); + expect(rows.find((row) => row.seed_key === "continue-writing")).toMatchObject({ + action: "continue-writing", + name: "继续写作", + }); + expect(rows.find((row) => row.name === "周报提炼")).toMatchObject({ + seed_key: null, + action: "custom", + instruction: "提炼本周进展与风险。", + }); }); test("validates create and update payloads", () => { @@ -387,7 +456,7 @@ describe("AI prompt template routes", () => { (prompt) => prompt.seedKey === "summarize", ); expect(chineseSummary).toMatchObject({ - name: "总结", + name: "精简总结", description: "压缩全文,提炼主题、结论与可执行结果", instruction: "Only this instruction was customized before the metadata migration.", }); @@ -474,7 +543,7 @@ describe("AI prompt template routes", () => { (prompt) => prompt.seedKey === "summarize", ); expect(chineseSummary).toMatchObject({ - name: "总结", + name: "精简总结", description: "压缩全文,提炼主题、结论与可执行结果", nameCustomized: false, descriptionCustomized: false, diff --git a/apps/api/src/ai-service.ts b/apps/api/src/ai-service.ts index eba15ae9..83f93c41 100644 --- a/apps/api/src/ai-service.ts +++ b/apps/api/src/ai-service.ts @@ -413,14 +413,14 @@ export const testAiModel = async (config: { export const aiActionInstructions: Record, string> = { summarize: getDefaultAiPromptSeed("summarize")!.instruction, "extract-key-points": "提取笔记中最重要的要点,用简洁的 Markdown 列表输出。保持原语言,不要添加原文没有的信息。", - "extract-todos": "从笔记中提取明确或隐含的可执行任务,用 Markdown 任务列表(- [ ])输出。保持原语言,不要编造任务。若没有可执行事项,用原文语言简短说明。", + "extract-todos": getDefaultAiPromptSeed("extract-todos")!.instruction, "rewrite-proofread": "改写并校对完整笔记。修正拼写、语法、标点、清晰度与结构,不改变原意。保持原语言与 Markdown 格式。只返回完整修订稿。", "improve-writing": getDefaultAiPromptSeed("improve-writing")!.instruction, "fix-spelling-grammar": "只修正拼写、语法与标点。不要改变语气、结构或含义。保持原语言与 Markdown 格式。只返回修正后的内容。", "make-shorter": getDefaultAiPromptSeed("make-shorter")!.instruction, "make-longer": "扩写内容,补充有用的说明与更顺畅的过渡,但不要编造事实。保持原语言与有用的 Markdown 格式。只返回扩写后的内容。", - "simplify-language": getDefaultAiPromptSeed("simplify-language")!.instruction, - "continue-writing": "从笔记结束处自然续写。只返回新增续写内容,不要重复原文。保持原语言与 Markdown 风格。", + "simplify-language": "用清晰、平实、更好懂的语言改写内容。保持原意、原语言与有用的 Markdown 格式。只返回简化后的内容。", + "continue-writing": getDefaultAiPromptSeed("continue-writing")!.instruction, }; const AI_PROMPT_OUTPUT_INSTRUCTION = diff --git a/apps/api/src/demo-seed-data.ts b/apps/api/src/demo-seed-data.ts index f0fb9e8f..15c6f965 100644 --- a/apps/api/src/demo-seed-data.ts +++ b/apps/api/src/demo-seed-data.ts @@ -159,7 +159,7 @@ sequenceDiagram 在正文空白行直接按下 **\`空格键 (Space)\`**、输入 **\`/ai\`**、通过 **\`/\`** 斜杠指令菜单,或选中文本点击浮动工具栏中的 **AI 按钮**,即可即时呼出 AI 写作助手面板: - **精炼总结与要点提取**:一键压缩提炼全文核心结论、提取待办事项与关键行动项; - **格式保真智能翻译**:在严格保留原有 Markdown、数学公式、链接与代码块的前提下,精准翻译多国语言; -- **内容重塑与风格改写**:支持改进表达、修正错别字与语法、转为社交媒体(如小红书/推特)风格,或按上下文顺滑续写; +- **内容重塑与续写**:支持润色与精炼表达,或按上下文顺滑续写; - **BYOK 隐私直连 (Bring Your Own Key)**:支持直连 OpenAI、Anthropic Claude、Google Gemini、DeepSeek 及各类 OpenAI 兼容的中继 API,数据完全由端侧直发,不经过任何第三方中转。 ### 2️⃣ 开放 MCP 协议 (Model Context Protocol) @@ -378,7 +378,7 @@ sequenceDiagram Press the **\`Space\` bar** in an empty block, type **\`/ai\`**, use the **\`/\`** slash command menu, or select text and click the **AI button** on the floating toolbar to instantly summon the AI writing assistant: - **Summarization & Action Items**: Condense documents into key takeaways, conclusions, and actionable todos; - **Format-Preserving Translation**: Translate accurately into multiple languages while strictly preserving Markdown, math equations, links, and code blocks; -- **Rewriting & Style Transformation**: Improve phrasing, fix spelling/grammar, adapt to social media styles (e.g. Xiaohongshu / Twitter), or continue writing seamlessly; +- **Rewriting & Continuation**: Polish phrasing, make writing concise, or continue writing seamlessly; - **BYOK Direct Key (Bring Your Own Key)**: Direct client-side connection with OpenAI, Anthropic Claude, Google Gemini, DeepSeek, and OpenAI-compatible relays with zero third-party data transit. ### 2️⃣ Model Context Protocol (MCP) Integration diff --git a/apps/ios/EdgeEver/Features/Workspace/AiAssistantSheet.swift b/apps/ios/EdgeEver/Features/Workspace/AiAssistantSheet.swift index 9ab425d7..538730c5 100644 --- a/apps/ios/EdgeEver/Features/Workspace/AiAssistantSheet.swift +++ b/apps/ios/EdgeEver/Features/Workspace/AiAssistantSheet.swift @@ -401,17 +401,17 @@ struct AiAssistantSheet: View { private func actionTitle(_ action: AiAction) -> String { switch action { - case .improveWriting: env.preferences.t("改进写作", en: "Improve writing") + case .improveWriting: env.preferences.t("润色表达", en: "Polish") case .fixSpellingGrammar: env.preferences.t("修正拼写与语法", en: "Fix spelling & grammar") - case .summarize: env.preferences.t("总结", en: "Summarize") + case .summarize: env.preferences.t("精简总结", en: "Summarize") case .extractKeyPoints: env.preferences.t("提炼要点", en: "Key points") case .extractTodos: env.preferences.t("提取待办", en: "Extract tasks") - case .rewriteProofread: env.preferences.t("转为小红书风格", en: "Convert to Xiaohongshu style") + case .rewriteProofread: env.preferences.t("改写与校对", en: "Rewrite & proofread") case .makeShorter: env.preferences.t("精炼表达", en: "Make concise") case .makeLonger: env.preferences.t("扩写内容", en: "Make longer") - case .simplifyLanguage: env.preferences.t("转为推特风格", en: "Convert to X (Twitter) style") + case .simplifyLanguage: env.preferences.t("简化表达", en: "Simplify language") case .changeTone: env.preferences.t("调整语气", en: "Change tone") - case .translate: env.preferences.t("翻译", en: "Translate") + case .translate: env.preferences.t("全文翻译", en: "Translate") case .continueWriting: env.preferences.t("继续写作", en: "Continue writing") case .custom: env.preferences.t("自定义指令", en: "Custom prompt") } diff --git a/apps/mobile/src/components/LocalTiptapEditor.tsx b/apps/mobile/src/components/LocalTiptapEditor.tsx index e031af0c..1a0dca06 100644 --- a/apps/mobile/src/components/LocalTiptapEditor.tsx +++ b/apps/mobile/src/components/LocalTiptapEditor.tsx @@ -1740,16 +1740,16 @@ const MobileSelectionAiPanel = ({ const english = locale === "en-US"; const [picker, setPicker] = useState(null); const actionLabels: Record = { - summarize: english ? "Summarize" : "总结", + summarize: english ? "Summarize" : "精简总结", "extract-key-points": english ? "Key points" : "提炼要点", "extract-todos": english ? "Extract tasks" : "提取待办", - "rewrite-proofread": english ? "Convert to Xiaohongshu style" : "转为小红书风格", - translate: english ? "Translate" : "翻译", - "improve-writing": english ? "Improve writing" : "改进写作", + "rewrite-proofread": english ? "Rewrite & proofread" : "改写与校对", + translate: english ? "Translate" : "全文翻译", + "improve-writing": english ? "Polish" : "润色表达", "fix-spelling-grammar": english ? "Fix spelling & grammar" : "修正拼写与语法", "make-shorter": english ? "Make concise" : "精炼表达", "make-longer": english ? "Make longer" : "扩写内容", - "simplify-language": english ? "Convert to X (Twitter) style" : "转为推特风格", + "simplify-language": english ? "Simplify language" : "简化表达", "change-tone": english ? "Change tone" : "调整语气", "continue-writing": english ? "Continue writing" : "继续写作", custom: english ? "Custom prompt" : "自定义指令", diff --git a/apps/mobile/src/components/MobileAiAssistantModal.tsx b/apps/mobile/src/components/MobileAiAssistantModal.tsx index d55e26c7..2f9b4d5f 100644 --- a/apps/mobile/src/components/MobileAiAssistantModal.tsx +++ b/apps/mobile/src/components/MobileAiAssistantModal.tsx @@ -83,17 +83,17 @@ export const MobileAiAssistantModal = ({ ?? (["summarize", "extract-key-points", "extract-todos", "continue-writing"].includes(action) ? "append" : "both"); const labels: Record = { - summarize: tr("总结", "Summarize"), + summarize: tr("精简总结", "Summarize"), "extract-key-points": tr("提炼要点", "Key points"), "extract-todos": tr("提取待办", "Extract tasks"), - "rewrite-proofread": tr("转为小红书风格", "Convert to Xiaohongshu style"), - "improve-writing": tr("改进写作", "Improve writing"), + "rewrite-proofread": tr("改写与校对", "Rewrite & proofread"), + "improve-writing": tr("润色表达", "Polish"), "fix-spelling-grammar": tr("修正拼写与语法", "Fix spelling & grammar"), "make-shorter": tr("精炼表达", "Make concise"), "make-longer": tr("扩写内容", "Make longer"), - "simplify-language": tr("转为推特风格", "Convert to X (Twitter) style"), + "simplify-language": tr("简化表达", "Simplify language"), "change-tone": tr("调整语气", "Change tone"), - translate: tr("翻译", "Translate"), + translate: tr("全文翻译", "Translate"), "continue-writing": tr("继续写作", "Continue writing"), custom: tr("自定义指令", "Custom prompt"), }; diff --git a/docs/demo-sample-note.md b/docs/demo-sample-note.md index 3ff969ec..d4795acf 100644 --- a/docs/demo-sample-note.md +++ b/docs/demo-sample-note.md @@ -132,7 +132,7 @@ sequenceDiagram Press the **`Space` bar** in an empty block, type **`/ai`**, use the **`/`** slash command menu, or select text and click the **AI button** on the floating toolbar to instantly summon the AI writing assistant: - **Summarization & Action Items**: Condense documents into key takeaways, conclusions, and actionable todos; - **Format-Preserving Translation**: Translate accurately into multiple languages while strictly preserving Markdown, math equations, links, and code blocks; -- **Rewriting & Style Transformation**: Improve phrasing, fix spelling/grammar, adapt to social media styles (e.g. Xiaohongshu / Twitter), or continue writing seamlessly; +- **Rewriting & Continuation**: Polish phrasing, make writing concise, or continue writing seamlessly; - **BYOK Direct Key (Bring Your Own Key)**: Direct client-side connection with OpenAI, Anthropic Claude, Google Gemini, DeepSeek, and OpenAI-compatible relays with zero third-party data transit. ### 2️⃣ Model Context Protocol (MCP) Integration diff --git a/docs/demo-sample-note.zh-CN.md b/docs/demo-sample-note.zh-CN.md index 2a7b2bb9..8de150d8 100644 --- a/docs/demo-sample-note.zh-CN.md +++ b/docs/demo-sample-note.zh-CN.md @@ -132,7 +132,7 @@ sequenceDiagram 在正文空白行直接按下 **`空格键 (Space)`**、输入 **`/ai`**、通过 **`/`** 斜杠指令菜单,或选中文本点击浮动工具栏中的 **AI 按钮**,即可即时呼出 AI 写作助手面板: - **精炼总结与要点提取**:一键压缩提炼全文核心结论、提取待办事项与关键行动项; - **格式保真智能翻译**:在严格保留原有 Markdown、数学公式、链接与代码块的前提下,精准翻译多国语言; -- **内容重塑与风格改写**:支持改进表达、修正错别字与语法、转为社交媒体(如小红书/推特)风格,或按上下文顺滑续写; +- **内容重塑与续写**:支持润色与精炼表达,或按上下文顺滑续写; - **BYOK 隐私直连 (Bring Your Own Key)**:支持直连 OpenAI、Anthropic Claude、Google Gemini、DeepSeek 及各类 OpenAI 兼容的中继 API,数据完全由端侧直发,不经过任何第三方中转。 ### 2️⃣ 开放 MCP 协议 (Model Context Protocol) diff --git a/migrations/0047_replace_social_ai_prompts.sql b/migrations/0047_replace_social_ai_prompts.sql new file mode 100644 index 00000000..e4f2b6bb --- /dev/null +++ b/migrations/0047_replace_social_ai_prompts.sql @@ -0,0 +1,33 @@ +PRAGMA foreign_keys = ON; + +-- Replace Xiaohongshu / Twitter starters with extract-todos and continue-writing. +-- Untouched and edited presets both leave the catalog so they do not linger as +-- unexpected custom prompts. User-created prompts have no seed_key and are kept. +DELETE FROM ai_prompt_templates +WHERE seed_key IN ('rewrite-proofread', 'simplify-language'); + +INSERT OR IGNORE INTO ai_prompt_templates ( + id, workspace_id, seed_key, action, parameter_kind, result_mode, + name, description, instruction, + name_customized, description_customized, instruction_customized, + created_at, updated_at +) +SELECT + id || '_aiprompt_extract-todos', id, 'extract-todos', 'extract-todos', 'none', 'append', + '提取待办', '识别可执行任务,生成任务清单', + '从笔记中提取明确或隐含的可执行任务,用 Markdown 任务列表(- [ ])输出。保持原语言,不要编造任务。若没有可执行事项,用原文语言简短说明。', + 0, 0, 0, strftime('%Y-%m-%dT%H:%M:%fZ', 'now'), strftime('%Y-%m-%dT%H:%M:%fZ', 'now') +FROM workspaces; + +INSERT OR IGNORE INTO ai_prompt_templates ( + id, workspace_id, seed_key, action, parameter_kind, result_mode, + name, description, instruction, + name_customized, description_customized, instruction_customized, + created_at, updated_at +) +SELECT + id || '_aiprompt_continue-writing', id, 'continue-writing', 'continue-writing', 'none', 'append', + '继续写作', '从笔记末尾自然续写', + '从笔记结束处自然续写。只返回新增续写内容,不要重复原文。保持原语言与 Markdown 风格。', + 0, 0, 0, strftime('%Y-%m-%dT%H:%M:%fZ', 'now'), strftime('%Y-%m-%dT%H:%M:%fZ', 'now') +FROM workspaces; diff --git a/packages/shared/src/ai-assistant.ts b/packages/shared/src/ai-assistant.ts index f2b362b2..99ed1900 100644 --- a/packages/shared/src/ai-assistant.ts +++ b/packages/shared/src/ai-assistant.ts @@ -61,8 +61,8 @@ export const AI_SELECTED_TEXT_ACTIONS: readonly AiAction[] = [ "translate", "improve-writing", "make-shorter", - "rewrite-proofread", - "simplify-language", + "extract-todos", + "continue-writing", "custom", ]; @@ -71,8 +71,8 @@ export const AI_WHOLE_NOTE_ACTIONS: readonly AiAction[] = [ "translate", "improve-writing", "make-shorter", - "rewrite-proofread", - "simplify-language", + "extract-todos", + "continue-writing", "custom", ]; diff --git a/packages/shared/src/ai-prompt-seeds.ts b/packages/shared/src/ai-prompt-seeds.ts index 2657f5ae..512245a9 100644 --- a/packages/shared/src/ai-prompt-seeds.ts +++ b/packages/shared/src/ai-prompt-seeds.ts @@ -60,7 +60,7 @@ export const DEFAULT_AI_PROMPT_SEEDS: readonly AiPromptSeed[] = [ seed( { key: "summarize", action: "summarize", parameterKind: "none", resultMode: "append" }, { - name: "总结", + name: "精简总结", description: "压缩全文,提炼主题、结论与可执行结果", instruction: [ "对笔记做真正的精简总结,不要逐句改写、同义复述或回声式重写。", @@ -87,7 +87,7 @@ export const DEFAULT_AI_PROMPT_SEEDS: readonly AiPromptSeed[] = [ seed( { key: "translate", action: "translate", parameterKind: "target-language", resultMode: "both" }, { - name: "翻译", + name: "全文翻译", description: "翻译为指定目标语言,保留结构与格式", instruction: "将完整笔记翻译成用户指定的目标语言。保留原意、Markdown 结构、链接与代码块。只返回译文,不要评论。", }, @@ -100,7 +100,7 @@ export const DEFAULT_AI_PROMPT_SEEDS: readonly AiPromptSeed[] = [ seed( { key: "improve-writing", action: "improve-writing", parameterKind: "none", resultMode: "both" }, { - name: "润色", + name: "润色表达", description: "校正语言并提升文字的清晰度与流畅度", instruction: "润色内容,修正错别字、语法与标点,改善用词、句式、清晰度和流畅度,但不要改变原意或刻意缩短内容。保持原语言与有用的 Markdown 格式。只返回润色后的内容。", }, @@ -124,29 +124,29 @@ export const DEFAULT_AI_PROMPT_SEEDS: readonly AiPromptSeed[] = [ }, ), seed( - { key: "rewrite-proofread", action: "rewrite-proofread", parameterKind: "none", resultMode: "both" }, + { key: "extract-todos", action: "extract-todos", parameterKind: "none", resultMode: "append" }, { - name: "转为小红书风格", - description: "改写成自然、有吸引力的小红书笔记", - instruction: "将内容改写成适合小红书发布的笔记:生成吸引人的标题,使用自然、有亲和力的口吻、短段落和清晰层次,可适量加入贴合语义的 Emoji,并在结尾给出 3–8 个相关话题标签。保留原文的关键事实与观点,不夸大效果,不编造经历、数据或结论。只返回可直接发布的内容。", + name: "提取待办", + description: "识别可执行任务,生成任务清单", + instruction: "从笔记中提取明确或隐含的可执行任务,用 Markdown 任务列表(- [ ])输出。保持原语言,不要编造任务。若没有可执行事项,用原文语言简短说明。", }, { - name: "Convert to Xiaohongshu style", - description: "Rewrite as a natural and engaging Xiaohongshu post", - instruction: "Rewrite the content as a Xiaohongshu-ready post. Add an engaging title, use a natural and approachable voice, short paragraphs, and clear structure, include a few contextually appropriate emoji, and end with 3–8 relevant hashtags. Preserve the source's key facts and claims without exaggerating results or inventing experiences, data, or conclusions. Return only the publishable post.", + name: "Extract tasks", + description: "Identify actionable work and produce a task list", + instruction: "Extract explicit or implied actionable tasks from the note as a Markdown task list using '- [ ]'. Preserve its language and do not invent tasks. If there are no actionable tasks, say so briefly in the note's language.", }, ), seed( - { key: "simplify-language", action: "simplify-language", parameterKind: "none", resultMode: "both" }, + { key: "continue-writing", action: "continue-writing", parameterKind: "none", resultMode: "append" }, { - name: "转为推特风格", - description: "改写成简洁、有观点的推文或推文串", - instruction: "将内容改写成适合推特发布的文本:开头直接抓住重点,表达简洁、有观点、易读。内容较短时输出一条推文;无法在一条内保留关键信息时,输出带序号的精简推文串。只在确有帮助时使用少量标签。保留原文事实与立场,不制造噱头或编造信息。只返回可直接发布的内容。", + name: "继续写作", + description: "从笔记末尾自然续写", + instruction: "从笔记结束处自然续写。只返回新增续写内容,不要重复原文。保持原语言与 Markdown 风格。", }, { - name: "Convert to X (Twitter) style", - description: "Rewrite as a concise, opinionated post or thread", - instruction: "Rewrite the content for X (Twitter): lead with the main point and make it concise, opinionated, and easy to scan. Return one post when the key information fits; otherwise return a compact numbered thread. Use hashtags sparingly and only when useful. Preserve the source's facts and position without manufacturing hype or information. Return only the publishable post or thread.", + name: "Continue writing", + description: "Continue naturally from the end of the note", + instruction: "Continue writing naturally from where the note ends. Return only the new continuation, not the original content. Preserve its language and Markdown style.", }, ), ]; diff --git a/packages/shared/src/i18n/en-US.ts b/packages/shared/src/i18n/en-US.ts index e89f50e2..f2f40a7f 100644 --- a/packages/shared/src/i18n/en-US.ts +++ b/packages/shared/src/i18n/en-US.ts @@ -992,13 +992,13 @@ export const enUS = { summarize: "Summarize", "extract-key-points": "Key points", "extract-todos": "Extract tasks", - "rewrite-proofread": "Convert to Xiaohongshu style", + "rewrite-proofread": "Rewrite & proofread", translate: "Translate", - "improve-writing": "Improve writing", + "improve-writing": "Polish", "fix-spelling-grammar": "Fix spelling & grammar", "make-shorter": "Make concise", "make-longer": "Make longer", - "simplify-language": "Convert to X (Twitter) style", + "simplify-language": "Simplify language", "change-tone": "Change tone", "continue-writing": "Continue writing", custom: "Custom prompt", diff --git a/packages/shared/src/i18n/zh-CN.ts b/packages/shared/src/i18n/zh-CN.ts index d92736f4..0c233f21 100644 --- a/packages/shared/src/i18n/zh-CN.ts +++ b/packages/shared/src/i18n/zh-CN.ts @@ -945,7 +945,7 @@ export const zhCN = { restoreDefaults: "恢复默认指令", restoreDefaultsHint: "仅补回已删除的预置项,不会覆盖你改过的内容,也不会删除你新建的指令。", restoreDefaultsConfirmTitle: "恢复默认指令?", - restoreDefaultsConfirmDescription: "将补回缺失的预置指令(如总结、翻译等)。你已编辑过的预置项与自行新建的指令不会被改动。", + restoreDefaultsConfirmDescription: "将补回缺失的预置指令(如精简总结、全文翻译等)。你已编辑过的预置项与自行新建的指令不会被改动。", restoreDefaultsConfirm: "恢复", restoreDefaultsDone: "已恢复 {{count}} 条默认指令。", restoreDefaultsNone: "默认指令都在,无需恢复。", @@ -989,16 +989,16 @@ export const zhCN = { transparentHint: "下方即实际发送给 AI 的指令,与指令库同一套,可直接改。", managePrompts: "指令库", actions: { - summarize: "总结", + summarize: "精简总结", "extract-key-points": "提炼要点", "extract-todos": "提取待办", - "rewrite-proofread": "转为小红书风格", - translate: "翻译", - "improve-writing": "改进表达", + "rewrite-proofread": "改写与校对", + translate: "全文翻译", + "improve-writing": "润色表达", "fix-spelling-grammar": "修正错别字与语法", "make-shorter": "精炼表达", "make-longer": "扩写内容", - "simplify-language": "转为推特风格", + "simplify-language": "简化表达", "change-tone": "改变语气", "continue-writing": "继续写作", custom: "自定义指令", diff --git a/tests/e2e/ai-custom-prompts.spec.ts b/tests/e2e/ai-custom-prompts.spec.ts index 809e074c..6ddcc0d5 100644 --- a/tests/e2e/ai-custom-prompts.spec.ts +++ b/tests/e2e/ai-custom-prompts.spec.ts @@ -309,7 +309,7 @@ test.describe("AI custom prompts", () => { const instruction = assistant.getByRole("textbox", { name: "告诉 AI 你想怎么处理" }); await instruction.fill("写一首诗"); - await selectAction(assistant, "翻译"); + await selectAction(assistant, "全文翻译"); await expect(assistant.getByRole("textbox", { name: "输入要处理的内容" })).toHaveValue("写一首诗"); await assistant.getByRole("button", { name: "生成", exact: true }).click(); await expect(result).toHaveText("Write a poem."); @@ -658,7 +658,7 @@ test.describe("AI custom prompts", () => { await page.getByRole("button", { name: "打开 AI 写作助手", exact: true }).click(); const dialog = page.getByRole("dialog", { name: "AI 笔记助手" }); - await selectAction(dialog, "总结"); + await selectAction(dialog, "精简总结"); await dialog.getByRole("button", { name: "生成", exact: true }).click(); await expect(dialog.getByText("AI 插入段落", { exact: true })).toBeVisible(); const copyButton = dialog.getByRole("button", { name: "复制结果", exact: true }); @@ -753,13 +753,13 @@ test.describe("AI custom prompts", () => { await page.evaluate(() => window.localStorage.removeItem("edgeever.aiAssistant.lastAction")); const dialog = await openMemoAssistant(page, memo.id, notebookName); await expect(dialog.getByRole("combobox", { name: "处理方式" })).toHaveText("自定义指令"); - await selectAction(dialog, "翻译"); - await expect(dialog.getByRole("combobox", { name: "处理方式" })).toHaveText("翻译"); + await selectAction(dialog, "全文翻译"); + await expect(dialog.getByRole("combobox", { name: "处理方式" })).toHaveText("全文翻译"); await dialog.getByRole("button", { name: "关闭", exact: true }).click(); await expect(dialog).toBeHidden(); await page.getByRole("button", { name: "打开 AI 写作助手", exact: true }).click(); await expect(dialog).toBeVisible(); - await expect(dialog.getByRole("combobox", { name: "处理方式" })).toHaveText("翻译"); + await expect(dialog.getByRole("combobox", { name: "处理方式" })).toHaveText("全文翻译"); }); });